Services and endpoints
Use legacy TypeScript decorators to replace service methods with Fetcher requests. Enable experimentalDecorators; emitDecoratorMetadata is not needed. Standard (stage-3) decorators do not support this parameter-decorator contract: compiled that way, @api and the method decorators throw a TypeError that says so. The package imports reflect-metadata itself.
Class and method decorators
| Factory | Defaults | Result |
|---|---|---|
api(basePath = '', metadata = {}) | metadata: Omit<ApiMetadata, 'basePath'> | Class decorator, returns the same constructor after binding endpoint methods. |
endpoint(method?, path?, metadata = {}) | Optional method/path | Method decorator recording EndpointMetadata. |
get, post, put, del, patch, head, options | path = '', metadata: MethodEndpointMetadata = {} | Method decorators selecting the corresponding HTTP method; DELETE is named del. |
PathCapable provides optional path. EndpointMetadata extends ApiMetadata and adds optional path/method; MethodEndpointMetadata omits those two fields. To use TRACE, choose endpoint(HttpMethod.TRACE, path) subject to native Fetch restrictions; there is no exported trace decorator.
AutoGenerated is an Error whose message is 'Implementation will be generated automatically.'. autoGeneratedError(...ignored) returns a new instance, does not throw it. Place throw autoGeneratedError(...) in a typed placeholder method. Without successful @api binding it will actually throw; a return annotation alone cannot implement a request.
API metadata and precedence
Field on ApiMetadata | Resolution |
|---|---|
basePath?: string | Endpoint truthy override, then API path, then empty. |
fetcher?: string | Fetcher | Endpoint non-nullish override, then API; resolved through getFetcher. |
headers? / urlParams? | Client defaults (headers), API, endpoint, then bound argument/request values; headers case-insensitive. |
timeout?: number | Endpoint defined value (including zero), API, then client default. |
resultExtractor? | Endpoint, API, then JsonResultExtractor. |
returnType? | Endpoint, API, then EndpointReturnType.RESULT. |
attributes? | API entries followed by endpoint entries, then argument attributes. |
ApiMetadataCapable.apiMetadata enables instance configuration. buildRequestExecutor shallow-spreads instance metadata over decorator metadata on every call and caches nothing, so replacing apiMetadata or mutating it in place takes effect on the next call. Endpoint metadata still takes precedence. Shallow merging means an instance header object replaces the class header object before endpoint/request merging.
The default decorated return is parsed JSON, unlike Fetcher.get, which defaults to Response. For HEAD/204 or raw responses choose ResultExtractors.Response; for diagnostics use returnType: EndpointReturnType.EXCHANGE and annotate Promise<FetchExchange>. See execution for hooks and failures.
Complete example
import { Fetcher } from '@ahoo-wang/fetcher';
import {
api,
get,
path,
autoGeneratedError,
} from '@ahoo-wang/fetcher-decorator';
type User = { id: string; name: string };
const client = new Fetcher({
baseURL: 'https://api.example.com',
timeout: 3000,
});
@api('/users', { fetcher: client })
class Users {
@get('/{id}')
find(@path('id') id: string): Promise<User> {
throw autoGeneratedError(id);
}
}
const users = new Users();
// Requires a service returning JSON at https://api.example.com/users/1.
async function loadUser() {
return await users.find('1');
}
void loadUser;Public symbols and source
| Symbol | Implementation |
|---|---|
ApiMetadata | apiDecorator.ts:41 |
ApiMetadataCapable | apiDecorator.ts:84 |
api | apiDecorator.ts:239 |
PathCapable | endpointDecorator.ts:6 |
EndpointMetadata | endpointDecorator.ts:22 |
MethodEndpointMetadata | endpointDecorator.ts:34 |
endpoint | endpointDecorator.ts:60 |
get | endpointDecorator.ts:103 |
post | endpointDecorator.ts:128 |
put | endpointDecorator.ts:153 |
del | endpointDecorator.ts:178 |
patch | endpointDecorator.ts:203 |
head | endpointDecorator.ts:231 |
options | endpointDecorator.ts:256 |
AutoGenerated | generated.ts:25 |
autoGeneratedError | generated.ts:41 |
