nmtjs 0.16.0-beta.8 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/entrypoints/worker.js +9 -9
- package/dist/entrypoints/worker.js.map +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/application/index.d.ts +1 -5
- package/dist/runtime/application/index.js +1 -5
- package/dist/runtime/application/index.js.map +1 -1
- package/dist/runtime/enums.d.ts +1 -12
- package/dist/runtime/enums.js +1 -14
- package/dist/runtime/enums.js.map +1 -1
- package/dist/runtime/hooks.d.ts +1 -4
- package/dist/runtime/hooks.js +1 -3
- package/dist/runtime/hooks.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -3
- package/dist/runtime/index.js +1 -3
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/injectables.d.ts +3 -3
- package/dist/runtime/jobs/job.d.ts +1 -2
- package/dist/runtime/jobs/job.js.map +1 -1
- package/dist/runtime/jobs/router.d.ts +2 -5
- package/dist/runtime/jobs/router.js +2 -3
- package/dist/runtime/jobs/router.js.map +1 -1
- package/dist/runtime/jobs/runner.d.ts +1 -1
- package/dist/runtime/jobs/runner.js +1 -1
- package/dist/runtime/jobs/runner.js.map +1 -1
- package/dist/runtime/jobs/types.d.ts +1 -1
- package/dist/runtime/metrics/metric.d.ts +2 -2
- package/dist/runtime/metrics/metric.js +1 -1
- package/dist/runtime/metrics/metric.js.map +1 -1
- package/dist/runtime/metrics/registry.d.ts +3 -3
- package/dist/runtime/metrics/registry.js +1 -1
- package/dist/runtime/metrics/registry.js.map +1 -1
- package/dist/runtime/metrics/server.js +1 -1
- package/dist/runtime/metrics/server.js.map +1 -1
- package/dist/runtime/plugin.d.ts +2 -8
- package/dist/runtime/plugin.js +1 -3
- package/dist/runtime/plugin.js.map +1 -1
- package/dist/runtime/runtime.d.ts +2 -2
- package/dist/runtime/runtime.js +1 -2
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/server/applications.js +3 -0
- package/dist/runtime/server/applications.js.map +1 -1
- package/dist/runtime/server/config.d.ts +15 -12
- package/dist/runtime/server/config.js.map +1 -1
- package/dist/runtime/server/jobs.d.ts +6 -7
- package/dist/runtime/server/jobs.js +44 -30
- package/dist/runtime/server/jobs.js.map +1 -1
- package/dist/runtime/subscription/redis.d.ts +1 -1
- package/dist/runtime/subscription/redis.js.map +1 -1
- package/dist/runtime/types.d.ts +3 -11
- package/dist/runtime/workers/application.d.ts +15 -33
- package/dist/runtime/workers/application.js +46 -139
- package/dist/runtime/workers/application.js.map +1 -1
- package/dist/runtime/workers/job.js +2 -1
- package/dist/runtime/workers/job.js.map +1 -1
- package/dist/vite/server.js +1 -1
- package/dist/vite/server.js.map +1 -1
- package/package.json +19 -14
- package/src/cli.ts +2 -3
- package/src/entrypoints/worker.ts +11 -9
- package/src/index.ts +12 -5
- package/src/runtime/application/index.ts +1 -5
- package/src/runtime/enums.ts +2 -14
- package/src/runtime/hooks.ts +1 -5
- package/src/runtime/index.ts +2 -3
- package/src/runtime/injectables.ts +2 -2
- package/src/runtime/jobs/job.ts +1 -2
- package/src/runtime/jobs/router.ts +12 -15
- package/src/runtime/jobs/runner.ts +2 -2
- package/src/runtime/jobs/types.ts +1 -1
- package/src/runtime/metrics/metric.ts +2 -2
- package/src/runtime/metrics/registry.ts +5 -1
- package/src/runtime/metrics/server.ts +1 -1
- package/src/runtime/plugin.ts +2 -13
- package/src/runtime/runtime.ts +2 -4
- package/src/runtime/server/applications.ts +6 -0
- package/src/runtime/server/config.ts +27 -21
- package/src/runtime/server/jobs.ts +58 -34
- package/src/runtime/subscription/redis.ts +1 -1
- package/src/runtime/types.ts +3 -12
- package/src/runtime/workers/application.ts +76 -160
- package/src/runtime/workers/job.ts +3 -6
- package/src/vite/server.ts +1 -1
- package/dist/runtime/application/api/api.d.ts +0 -55
- package/dist/runtime/application/api/api.js +0 -252
- package/dist/runtime/application/api/api.js.map +0 -1
- package/dist/runtime/application/api/config.d.ts +0 -14
- package/dist/runtime/application/api/config.js +0 -6
- package/dist/runtime/application/api/config.js.map +0 -1
- package/dist/runtime/application/api/constants.d.ts +0 -14
- package/dist/runtime/application/api/constants.js +0 -8
- package/dist/runtime/application/api/constants.js.map +0 -1
- package/dist/runtime/application/api/filters.d.ts +0 -14
- package/dist/runtime/application/api/filters.js +0 -11
- package/dist/runtime/application/api/filters.js.map +0 -1
- package/dist/runtime/application/api/guards.d.ts +0 -15
- package/dist/runtime/application/api/guards.js +0 -8
- package/dist/runtime/application/api/guards.js.map +0 -1
- package/dist/runtime/application/api/index.d.ts +0 -23
- package/dist/runtime/application/api/index.js +0 -17
- package/dist/runtime/application/api/index.js.map +0 -1
- package/dist/runtime/application/api/logging.d.ts +0 -14
- package/dist/runtime/application/api/logging.js +0 -77
- package/dist/runtime/application/api/logging.js.map +0 -1
- package/dist/runtime/application/api/meta.d.ts +0 -21
- package/dist/runtime/application/api/meta.js +0 -2
- package/dist/runtime/application/api/meta.js.map +0 -1
- package/dist/runtime/application/api/middlewares.d.ts +0 -14
- package/dist/runtime/application/api/middlewares.js +0 -12
- package/dist/runtime/application/api/middlewares.js.map +0 -1
- package/dist/runtime/application/api/procedure.d.ts +0 -71
- package/dist/runtime/application/api/procedure.js +0 -41
- package/dist/runtime/application/api/procedure.js.map +0 -1
- package/dist/runtime/application/api/router.d.ts +0 -93
- package/dist/runtime/application/api/router.js +0 -55
- package/dist/runtime/application/api/router.js.map +0 -1
- package/dist/runtime/application/api/types.d.ts +0 -38
- package/dist/runtime/application/api/types.js +0 -2
- package/dist/runtime/application/api/types.js.map +0 -1
- package/dist/runtime/application/config.d.ts +0 -28
- package/dist/runtime/application/config.js +0 -25
- package/dist/runtime/application/config.js.map +0 -1
- package/dist/runtime/application/constants.d.ts +0 -2
- package/dist/runtime/application/constants.js +0 -2
- package/dist/runtime/application/constants.js.map +0 -1
- package/dist/runtime/application/hook.d.ts +0 -19
- package/dist/runtime/application/hook.js +0 -11
- package/dist/runtime/application/hook.js.map +0 -1
- package/dist/runtime/application/hooks.d.ts +0 -3
- package/dist/runtime/application/hooks.js +0 -4
- package/dist/runtime/application/hooks.js.map +0 -1
- package/src/runtime/application/api/api.ts +0 -406
- package/src/runtime/application/api/config.ts +0 -18
- package/src/runtime/application/api/constants.ts +0 -22
- package/src/runtime/application/api/filters.ts +0 -39
- package/src/runtime/application/api/guards.ts +0 -33
- package/src/runtime/application/api/index.ts +0 -69
- package/src/runtime/application/api/logging.ts +0 -110
- package/src/runtime/application/api/meta.ts +0 -37
- package/src/runtime/application/api/middlewares.ts +0 -37
- package/src/runtime/application/api/procedure.ts +0 -224
- package/src/runtime/application/api/router.ts +0 -247
- package/src/runtime/application/api/types.ts +0 -138
- package/src/runtime/application/config.ts +0 -82
- package/src/runtime/application/constants.ts +0 -4
- package/src/runtime/application/hook.ts +0 -51
- package/src/runtime/application/hooks.ts +0 -3
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { TProcedureContract } from '@nmtjs/contract';
|
|
2
|
-
import type { Container } from '@nmtjs/core';
|
|
3
|
-
import type { GatewayConnection } from '@nmtjs/gateway';
|
|
4
|
-
import type { AnyCompatibleType, BaseTypeAny } from '@nmtjs/type';
|
|
5
|
-
import type { Procedure } from './procedure.ts';
|
|
6
|
-
import type { AnyRouter } from './router.ts';
|
|
7
|
-
export type ApiCallContext<Payload = unknown> = Readonly<{
|
|
8
|
-
callId: string;
|
|
9
|
-
connection: GatewayConnection;
|
|
10
|
-
container: Container;
|
|
11
|
-
path: AnyRouter[];
|
|
12
|
-
procedure: Procedure<TProcedureContract<AnyCompatibleType<any, Payload>, BaseTypeAny, true | undefined, string | undefined>, any>;
|
|
13
|
-
}>;
|
|
14
|
-
export type ApiGuardContext<Payload = unknown> = ApiCallContext<Payload> & Readonly<{
|
|
15
|
-
payload: Payload;
|
|
16
|
-
}>;
|
|
17
|
-
export type JsonPrimitive<T> = Equal<T, JsonPrimitiveMain<T>> extends true ? T : JsonPrimitiveMain<T>;
|
|
18
|
-
type Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
|
|
19
|
-
type JsonPrimitiveMain<Instance, InArray extends boolean = false> = Instance extends [never] ? never : ValueOf<Instance> extends bigint ? never : ValueOf<Instance> extends boolean | number | string ? ValueOf<Instance> : Instance extends Function ? InArray extends true ? null : never : ValueOf<Instance> extends object ? Instance extends object ? Instance extends NativeClass ? {} : Instance extends IJsonable<infer Raw> ? ValueOf<Raw> extends object ? Raw extends object ? PrimitiveObject<Raw> : never : ValueOf<Raw> : PrimitiveObject<Instance> : never : ValueOf<Instance>;
|
|
20
|
-
type PrimitiveObject<Instance extends object> = Instance extends Array<infer T> ? IsTuple<Instance> extends true ? PrimitiveTuple<Instance> : JsonPrimitiveMain<T, true>[] : {
|
|
21
|
-
-readonly [P in keyof Instance as JsonPrimitiveMain<Instance[P]> extends never ? never : P]: JsonPrimitiveMain<Instance[P]>;
|
|
22
|
-
};
|
|
23
|
-
type PrimitiveTuple<T extends readonly any[]> = T extends [] ? [] : T extends [infer F] ? [JsonPrimitiveMain<F, true>] : T extends [infer F, ...infer Rest extends readonly any[]] ? [JsonPrimitiveMain<F, true>, ...PrimitiveTuple<Rest>] : T extends [(infer F)?] ? [JsonPrimitiveMain<F, true>?] : T extends [(infer F)?, ...infer Rest extends readonly any[]] ? [JsonPrimitiveMain<F, true>?, ...PrimitiveTuple<Rest>] : [];
|
|
24
|
-
type ValueOf<Instance> = IsValueOf<Instance, boolean> extends true ? boolean : IsValueOf<Instance, number> extends true ? number : IsValueOf<Instance, string> extends true ? string : Instance;
|
|
25
|
-
type NativeClass = Set<any> | Map<any, any> | WeakSet<any> | WeakMap<any, any> | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | BigUint64Array | Int8Array | Int16Array | Int32Array | BigInt64Array | Float32Array | Float64Array | ArrayBuffer | SharedArrayBuffer | DataView;
|
|
26
|
-
type IsTuple<T extends readonly any[] | {
|
|
27
|
-
length: number;
|
|
28
|
-
}> = [T] extends [
|
|
29
|
-
never
|
|
30
|
-
] ? false : T extends readonly any[] ? number extends T['length'] ? false : true : false;
|
|
31
|
-
type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object ? Object extends IValueOf<infer U> ? Instance extends U ? false : true : false : false;
|
|
32
|
-
interface IValueOf<T> {
|
|
33
|
-
valueOf(): T;
|
|
34
|
-
}
|
|
35
|
-
interface IJsonable<T> {
|
|
36
|
-
toJSON(): T;
|
|
37
|
-
}
|
|
38
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/runtime/application/api/types.ts"],"names":[],"mappings":""}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { ConnectionIdentity, GatewayOptions, Transport } from '@nmtjs/gateway';
|
|
2
|
-
import type { LifecycleHooks } from '../hooks.ts';
|
|
3
|
-
import type { RuntimePlugin } from '../plugin.ts';
|
|
4
|
-
import type { ApiOptions } from './api/api.ts';
|
|
5
|
-
import type { AnyFilter } from './api/filters.ts';
|
|
6
|
-
import type { AnyGuard } from './api/guards.ts';
|
|
7
|
-
import type { AnyMiddleware } from './api/middlewares.ts';
|
|
8
|
-
import type { AnyRootRouter, AnyRouterMetaBinding } from './api/router.ts';
|
|
9
|
-
import type { AnyHook } from './hook.ts';
|
|
10
|
-
import { kApplicationConfig } from './constants.ts';
|
|
11
|
-
export type AnyApplicationConfig = ApplicationConfig<AnyRootRouter>;
|
|
12
|
-
export interface ApplicationConfig<Router extends AnyRootRouter = AnyRootRouter, Transports extends Record<string, Transport> = Record<string, Transport>> {
|
|
13
|
-
[kApplicationConfig]: any;
|
|
14
|
-
router: Router;
|
|
15
|
-
api: Pick<ApiOptions, 'timeout'>;
|
|
16
|
-
gateway: Pick<GatewayOptions, 'streamTimeouts' | 'heartbeat'>;
|
|
17
|
-
transports: Transports;
|
|
18
|
-
identity?: ConnectionIdentity;
|
|
19
|
-
plugins: RuntimePlugin[];
|
|
20
|
-
filters: AnyFilter[];
|
|
21
|
-
middlewares: AnyMiddleware[];
|
|
22
|
-
guards: AnyGuard[];
|
|
23
|
-
meta: AnyRouterMetaBinding[];
|
|
24
|
-
hooks: AnyHook[];
|
|
25
|
-
lifecycleHooks: LifecycleHooks['_']['config'];
|
|
26
|
-
}
|
|
27
|
-
export declare function defineApplication<R extends AnyRootRouter, T extends Record<string, Transport> = Record<string, Transport>>(options: Pick<ApplicationConfig<R, T>, 'router'> & Partial<Omit<ApplicationConfig<R, T>, 'router'>>): ApplicationConfig<R, T>;
|
|
28
|
-
export declare function isApplicationConfig(value: any): value is ApplicationConfig;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { assertUniqueMetaBindings } from '@nmtjs/core';
|
|
2
|
-
import { kApplicationConfig } from './constants.js';
|
|
3
|
-
export function defineApplication(options) {
|
|
4
|
-
const { router, transports = {}, guards = [], middlewares = [], meta = [], plugins = [], api = {}, filters = [], hooks = [], lifecycleHooks = {}, gateway = {}, identity: identityResolver, } = options;
|
|
5
|
-
assertUniqueMetaBindings(meta, 'application config');
|
|
6
|
-
return Object.freeze({
|
|
7
|
-
[kApplicationConfig]: true,
|
|
8
|
-
router,
|
|
9
|
-
transports,
|
|
10
|
-
api,
|
|
11
|
-
gateway,
|
|
12
|
-
filters,
|
|
13
|
-
plugins,
|
|
14
|
-
guards,
|
|
15
|
-
middlewares,
|
|
16
|
-
meta,
|
|
17
|
-
hooks,
|
|
18
|
-
lifecycleHooks,
|
|
19
|
-
identity: identityResolver,
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
export function isApplicationConfig(value) {
|
|
23
|
-
return Boolean(value?.[kApplicationConfig]);
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/runtime/application/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAUtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAuBnD,MAAM,UAAU,iBAAiB,CAI/B,OACkD;IAElD,MAAM,EACJ,MAAM,EACN,UAAU,GAAG,EAAE,EACf,MAAM,GAAG,EAAE,EACX,WAAW,GAAG,EAAE,EAChB,IAAI,GAAG,EAAE,EACT,OAAO,GAAG,EAAE,EACZ,GAAG,GAAG,EAA8B,EACpC,OAAO,GAAG,EAAkC,EAC5C,KAAK,GAAG,EAAgC,EACxC,cAAc,GAAG,EAAE,EACnB,OAAO,GAAG,EAAE,EACZ,QAAQ,EAAE,gBAAgB,GAC3B,GAAG,OAAO,CAAA;IAEX,wBAAwB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAA;IAEpD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,CAAC,kBAAkB,CAAC,EAAE,IAAI;QAC1B,MAAM;QACN,UAAU;QACV,GAAG;QACH,OAAO;QACP,OAAO;QACP,OAAO;QACP,MAAM;QACN,WAAW;QACX,IAAI;QACJ,KAAK;QACL,cAAc;QACd,QAAQ,EAAE,gBAAgB;KACI,CAA4B,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAU;IAC5C,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAA;AAC7C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/runtime/application/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAkB,MAAM,CAAC,GAAG,CACzD,2BAA2B,CAC5B,CAAA"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { MaybePromise } from '@nmtjs/common';
|
|
2
|
-
import type { Dependant, Dependencies, DependencyContext, HookTypes } from '@nmtjs/core';
|
|
3
|
-
import { kHook } from '@nmtjs/core';
|
|
4
|
-
export type AnyHook = Hook<HookTypes, string, any>;
|
|
5
|
-
export interface Hook<T extends HookTypes = HookTypes, H extends string = string, Deps extends Dependencies = {}> extends Dependant<Deps> {
|
|
6
|
-
[kHook]: any;
|
|
7
|
-
name: H;
|
|
8
|
-
handler: (ctx: DependencyContext<Deps>, ...args: H extends keyof T ? Parameters<T[H]> : unknown[]) => MaybePromise<any>;
|
|
9
|
-
}
|
|
10
|
-
export declare function createHook<Types extends HookTypes = HookTypes, Name extends Extract<keyof Types, string> | (object & string) = object & string, Deps extends Dependencies = {}>(params: {
|
|
11
|
-
name: Name;
|
|
12
|
-
dependencies?: Deps;
|
|
13
|
-
handler: Hook<Types, Name, Deps>['handler'];
|
|
14
|
-
}): Hook<Types, Name, Deps>;
|
|
15
|
-
export declare function createApplicationHookFactory<Types extends HookTypes>(): <Name extends Extract<keyof Types, string> | (object & string) = object & string, Deps extends Dependencies = {}>(params: {
|
|
16
|
-
name: Name;
|
|
17
|
-
dependencies?: Deps;
|
|
18
|
-
handler: Hook<Types, Name, Deps>['handler'];
|
|
19
|
-
}) => Hook<Types, Name, Deps>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { kHook } from '@nmtjs/core';
|
|
2
|
-
export function createHook(params) {
|
|
3
|
-
const { name, handler, dependencies = {} } = params;
|
|
4
|
-
return Object.freeze({ [kHook]: true, name, handler, dependencies });
|
|
5
|
-
}
|
|
6
|
-
export function createApplicationHookFactory() {
|
|
7
|
-
return (params) => {
|
|
8
|
-
return createHook(params);
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=hook.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../../src/runtime/application/hook.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAiBnC,MAAM,UAAU,UAAU,CAKxB,MAID;IACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,GAAG,EAAU,EAAE,GAAG,MAAM,CAAA;IAC3D,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,CAAQ,CAAA;AAC7E,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO,CAIL,MAID,EAA2B,EAAE;QAC5B,OAAO,UAAU,CAAoB,MAAM,CAAC,CAAA;IAC9C,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/runtime/application/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC,MAAM,OAAO,gBAAiB,SAAQ,KAAK;CAAG"}
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { randomUUID } from 'node:crypto'
|
|
3
|
-
import { inspect } from 'node:util'
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
AnyFactoryMetaBinding,
|
|
7
|
-
AnyMetaBinding,
|
|
8
|
-
Container,
|
|
9
|
-
Logger,
|
|
10
|
-
StaticMetaBinding,
|
|
11
|
-
} from '@nmtjs/core'
|
|
12
|
-
import type {
|
|
13
|
-
GatewayApi,
|
|
14
|
-
GatewayApiCallOptions,
|
|
15
|
-
GatewayApiCallResult,
|
|
16
|
-
GatewayConnection,
|
|
17
|
-
GatewayResolvedProcedure,
|
|
18
|
-
GatewayResolveOptions,
|
|
19
|
-
} from '@nmtjs/gateway'
|
|
20
|
-
import { withTimeout } from '@nmtjs/common'
|
|
21
|
-
import { IsStreamProcedureContract } from '@nmtjs/contract'
|
|
22
|
-
import {
|
|
23
|
-
getMetaBindingMeta,
|
|
24
|
-
getStaticMetaValue,
|
|
25
|
-
isStaticMetaBinding,
|
|
26
|
-
Scope,
|
|
27
|
-
} from '@nmtjs/core'
|
|
28
|
-
import {
|
|
29
|
-
createGatewayStaticMetaView,
|
|
30
|
-
isAsyncIterable,
|
|
31
|
-
rpcStreamAbortSignal,
|
|
32
|
-
} from '@nmtjs/gateway'
|
|
33
|
-
import { ErrorCode } from '@nmtjs/protocol'
|
|
34
|
-
import { ProtocolError } from '@nmtjs/protocol/server'
|
|
35
|
-
import { NeemataTypeError, registerDefaultLocale, type } from '@nmtjs/type'
|
|
36
|
-
import { prettifyError } from 'zod/mini'
|
|
37
|
-
|
|
38
|
-
import type { RuntimeConfig } from './config.ts'
|
|
39
|
-
import type { kDefaultProcedure as kDefaultProcedureKey } from './constants.ts'
|
|
40
|
-
import type { AnyFilter } from './filters.ts'
|
|
41
|
-
import type { AnyGuard } from './guards.ts'
|
|
42
|
-
import type { ApiMetaContext } from './meta.ts'
|
|
43
|
-
import type { AnyMiddleware } from './middlewares.ts'
|
|
44
|
-
import type { AnyProcedure } from './procedure.ts'
|
|
45
|
-
import type { AnyRouter } from './router.ts'
|
|
46
|
-
import type { ApiCallContext } from './types.ts'
|
|
47
|
-
import { config, defaultRuntimeConfig } from './config.ts'
|
|
48
|
-
import { kDefaultProcedure } from './constants.ts'
|
|
49
|
-
|
|
50
|
-
registerDefaultLocale()
|
|
51
|
-
|
|
52
|
-
export type ApiCallOptions<T extends AnyProcedure = AnyProcedure> = Readonly<{
|
|
53
|
-
callId: string
|
|
54
|
-
connection: GatewayConnection
|
|
55
|
-
path: AnyRouter[]
|
|
56
|
-
procedure: T
|
|
57
|
-
container: Container
|
|
58
|
-
payload: any
|
|
59
|
-
signal: AbortSignal
|
|
60
|
-
}>
|
|
61
|
-
|
|
62
|
-
export type ApiOptions = {
|
|
63
|
-
timeout?: number
|
|
64
|
-
container: Container
|
|
65
|
-
logger: Logger
|
|
66
|
-
procedures: Map<
|
|
67
|
-
string | kDefaultProcedureKey,
|
|
68
|
-
{ procedure: AnyProcedure; path: AnyRouter[] }
|
|
69
|
-
>
|
|
70
|
-
meta: readonly AnyMetaBinding[]
|
|
71
|
-
guards: Set<AnyGuard>
|
|
72
|
-
middlewares: Set<AnyMiddleware>
|
|
73
|
-
filters: Set<AnyFilter>
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
type ResolvedMetaBindings = Readonly<{
|
|
77
|
-
static: readonly StaticMetaBinding[]
|
|
78
|
-
beforeDecode: readonly AnyFactoryMetaBinding[]
|
|
79
|
-
afterDecode: readonly AnyFactoryMetaBinding[]
|
|
80
|
-
config: Required<RuntimeConfig>
|
|
81
|
-
}>
|
|
82
|
-
|
|
83
|
-
export class ApiError extends ProtocolError {
|
|
84
|
-
toString() {
|
|
85
|
-
return `${this.code} ${this.message}: \n${inspect(this.data, true, 10, false)}`
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const NotFound = () => new ApiError(ErrorCode.NotFound, 'Procedure not found')
|
|
90
|
-
|
|
91
|
-
export class ApplicationApi implements GatewayApi {
|
|
92
|
-
constructor(public options: ApiOptions) {}
|
|
93
|
-
|
|
94
|
-
find(procedureName: string) {
|
|
95
|
-
const procedure = this.options.procedures.get(procedureName)
|
|
96
|
-
if (procedure) return procedure
|
|
97
|
-
|
|
98
|
-
const fallback = this.options.procedures.get(kDefaultProcedure)
|
|
99
|
-
if (fallback) return fallback
|
|
100
|
-
|
|
101
|
-
throw NotFound()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async resolve(
|
|
105
|
-
options: GatewayResolveOptions,
|
|
106
|
-
): Promise<GatewayResolvedProcedure> {
|
|
107
|
-
const { procedure, path } = this.find(options.procedure)
|
|
108
|
-
|
|
109
|
-
const metaBindings = this.resolveMetaBindings(path, procedure)
|
|
110
|
-
|
|
111
|
-
return Object.freeze({
|
|
112
|
-
stream: IsStreamProcedureContract(procedure.contract),
|
|
113
|
-
meta: createGatewayStaticMetaView(metaBindings.static),
|
|
114
|
-
}) satisfies GatewayResolvedProcedure
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async call(options: GatewayApiCallOptions): Promise<GatewayApiCallResult> {
|
|
118
|
-
const callId = randomUUID()
|
|
119
|
-
|
|
120
|
-
const { payload, container, signal, connection } = options
|
|
121
|
-
|
|
122
|
-
assert(
|
|
123
|
-
container.scope === Scope.Call,
|
|
124
|
-
'Invalid container scope, expected to be Scope.Call',
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
const { procedure, path } = this.find(options.procedure)
|
|
128
|
-
|
|
129
|
-
const metaBindings = this.resolveMetaBindings(path, procedure)
|
|
130
|
-
|
|
131
|
-
const callOptions: ApiCallOptions = Object.freeze({
|
|
132
|
-
callId,
|
|
133
|
-
payload,
|
|
134
|
-
container,
|
|
135
|
-
signal,
|
|
136
|
-
connection,
|
|
137
|
-
procedure,
|
|
138
|
-
path,
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
const timeout = procedure.contract.timeout ?? this.options.timeout
|
|
142
|
-
const streamTimeoutSignal = procedure.streamTimeout
|
|
143
|
-
? AbortSignal.timeout(procedure.streamTimeout)
|
|
144
|
-
: undefined
|
|
145
|
-
|
|
146
|
-
if (streamTimeoutSignal) {
|
|
147
|
-
container.provide(rpcStreamAbortSignal, streamTimeoutSignal)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
const handle = await this.createProcedureHandler(
|
|
152
|
-
callOptions,
|
|
153
|
-
metaBindings,
|
|
154
|
-
)
|
|
155
|
-
return timeout
|
|
156
|
-
? await this.withTimeout(handle(payload), timeout)
|
|
157
|
-
: await handle(payload)
|
|
158
|
-
} catch (error) {
|
|
159
|
-
const handled = await this.handleFilters(callOptions, error)
|
|
160
|
-
if (handled === error && error instanceof ProtocolError === false) {
|
|
161
|
-
const logError = new Error('Unhandled error', { cause: error })
|
|
162
|
-
this.options.logger.error(logError)
|
|
163
|
-
throw new ApiError(
|
|
164
|
-
ErrorCode.InternalServerError,
|
|
165
|
-
'Internal Server Error',
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
throw handled
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
private async createProcedureHandler(
|
|
173
|
-
callOptions: ApiCallOptions,
|
|
174
|
-
metaBindings: ResolvedMetaBindings,
|
|
175
|
-
) {
|
|
176
|
-
const { callId, connection, procedure, container, path } = callOptions
|
|
177
|
-
|
|
178
|
-
const callCtx: ApiCallContext = Object.freeze({
|
|
179
|
-
callId,
|
|
180
|
-
connection,
|
|
181
|
-
container,
|
|
182
|
-
path,
|
|
183
|
-
procedure,
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
const isIterableProcedure = IsStreamProcedureContract(procedure.contract)
|
|
187
|
-
|
|
188
|
-
this.applyStaticMetaBindings(container, metaBindings.static)
|
|
189
|
-
|
|
190
|
-
const middlewares = this.resolveMiddlewares(callOptions)
|
|
191
|
-
|
|
192
|
-
const handleProcedure = async (payload: any) => {
|
|
193
|
-
const middleware = (await middlewares).next().value
|
|
194
|
-
if (middleware) {
|
|
195
|
-
const next = (...args: any[]) =>
|
|
196
|
-
handleProcedure(args.length === 0 ? payload : args[0])
|
|
197
|
-
return middleware.handle(middleware.ctx, callCtx, next, payload)
|
|
198
|
-
} else {
|
|
199
|
-
await this.applyFactoryMetaBindings(
|
|
200
|
-
container,
|
|
201
|
-
metaBindings.beforeDecode,
|
|
202
|
-
callCtx,
|
|
203
|
-
payload,
|
|
204
|
-
)
|
|
205
|
-
const input = this.handleInput(procedure, payload)
|
|
206
|
-
await this.applyFactoryMetaBindings(
|
|
207
|
-
container,
|
|
208
|
-
metaBindings.afterDecode,
|
|
209
|
-
callCtx,
|
|
210
|
-
input,
|
|
211
|
-
)
|
|
212
|
-
await this.handleGuards(callOptions, callCtx, input)
|
|
213
|
-
const { dependencies, handler } = procedure
|
|
214
|
-
const context = await container.createContext(dependencies)
|
|
215
|
-
const result = await handler(context, input)
|
|
216
|
-
if (isIterableProcedure) {
|
|
217
|
-
return this.handleIterableOutput(
|
|
218
|
-
procedure,
|
|
219
|
-
result,
|
|
220
|
-
metaBindings.config,
|
|
221
|
-
)
|
|
222
|
-
} else {
|
|
223
|
-
return this.handleOutput(procedure, result, metaBindings.config)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return handleProcedure
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
private resolveMetaBindings(
|
|
232
|
-
path: AnyRouter[],
|
|
233
|
-
procedure: AnyProcedure,
|
|
234
|
-
): ResolvedMetaBindings {
|
|
235
|
-
const bindings = [
|
|
236
|
-
...this.options.meta,
|
|
237
|
-
...path.flatMap((router) => router.meta),
|
|
238
|
-
...procedure.meta,
|
|
239
|
-
]
|
|
240
|
-
|
|
241
|
-
const staticBindings: StaticMetaBinding[] = []
|
|
242
|
-
const beforeDecode: AnyFactoryMetaBinding[] = []
|
|
243
|
-
const afterDecode: AnyFactoryMetaBinding[] = []
|
|
244
|
-
|
|
245
|
-
for (const binding of bindings) {
|
|
246
|
-
if (isStaticMetaBinding(binding)) {
|
|
247
|
-
staticBindings.push(binding)
|
|
248
|
-
} else if (binding.phase === 'afterDecode') {
|
|
249
|
-
afterDecode.push(binding)
|
|
250
|
-
} else {
|
|
251
|
-
beforeDecode.push(binding)
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const runtimeConfig = getStaticMetaValue(staticBindings, config)
|
|
256
|
-
|
|
257
|
-
return Object.freeze({
|
|
258
|
-
static: Object.freeze(staticBindings),
|
|
259
|
-
beforeDecode: Object.freeze(beforeDecode),
|
|
260
|
-
afterDecode: Object.freeze(afterDecode),
|
|
261
|
-
config: Object.freeze({ ...defaultRuntimeConfig, ...runtimeConfig }),
|
|
262
|
-
})
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
private applyStaticMetaBindings(
|
|
266
|
-
container: Container,
|
|
267
|
-
bindings: readonly StaticMetaBinding[],
|
|
268
|
-
) {
|
|
269
|
-
for (const binding of bindings) {
|
|
270
|
-
container.provide(getMetaBindingMeta(binding), binding.value)
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
private async applyFactoryMetaBindings(
|
|
275
|
-
container: Container,
|
|
276
|
-
bindings: readonly AnyFactoryMetaBinding[],
|
|
277
|
-
callCtx: ApiMetaContext,
|
|
278
|
-
input: unknown,
|
|
279
|
-
) {
|
|
280
|
-
for (const binding of bindings) {
|
|
281
|
-
const context = await container.createContext(binding.dependencies)
|
|
282
|
-
const value = await binding.resolve(context, callCtx, input)
|
|
283
|
-
container.provide(getMetaBindingMeta(binding), value)
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private async resolveMiddlewares(callOptions: ApiCallOptions) {
|
|
288
|
-
const { path, procedure, container } = callOptions
|
|
289
|
-
const middlewares = [
|
|
290
|
-
...this.options.middlewares,
|
|
291
|
-
...path.flatMap((router) => [...router.middlewares]),
|
|
292
|
-
...procedure.middlewares,
|
|
293
|
-
]
|
|
294
|
-
const result = await Promise.all(
|
|
295
|
-
middlewares.map(async (middleware) => {
|
|
296
|
-
const ctx = await container.createContext(middleware.dependencies)
|
|
297
|
-
return { handle: middleware.handle, ctx }
|
|
298
|
-
}),
|
|
299
|
-
)
|
|
300
|
-
return result[Symbol.iterator]()
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
private withTimeout(response: any, timeout: number): unknown {
|
|
304
|
-
const applyTimeout = response instanceof Promise && timeout > 0
|
|
305
|
-
if (!applyTimeout) return response
|
|
306
|
-
return withTimeout(
|
|
307
|
-
response,
|
|
308
|
-
timeout,
|
|
309
|
-
new ApiError(ErrorCode.RequestTimeout, 'Request Timeout'),
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private async handleGuards(
|
|
314
|
-
callOptions: ApiCallOptions,
|
|
315
|
-
callCtx: ApiCallContext,
|
|
316
|
-
payload: any,
|
|
317
|
-
) {
|
|
318
|
-
const { path, procedure, container } = callOptions
|
|
319
|
-
const guards = [
|
|
320
|
-
...this.options.guards,
|
|
321
|
-
...path.flatMap((router) => [...router.guards]),
|
|
322
|
-
...procedure.guards,
|
|
323
|
-
]
|
|
324
|
-
for (const guard of guards) {
|
|
325
|
-
const ctx = await container.createContext(guard.dependencies)
|
|
326
|
-
const result = await guard.can(
|
|
327
|
-
ctx,
|
|
328
|
-
Object.freeze({ ...callCtx, payload }),
|
|
329
|
-
)
|
|
330
|
-
if (result === false) throw new ApiError(ErrorCode.Forbidden)
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
private async handleFilters({ container }: ApiCallOptions, error: any) {
|
|
335
|
-
if (this.options.filters.size) {
|
|
336
|
-
for (const filter of this.options.filters) {
|
|
337
|
-
if (error instanceof filter.errorClass) {
|
|
338
|
-
const ctx = await container.createContext(filter.dependencies)
|
|
339
|
-
const handledError = await filter.catch(ctx, error)
|
|
340
|
-
if (!handledError || handledError instanceof ApiError === false)
|
|
341
|
-
continue
|
|
342
|
-
return handledError
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return error
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
private handleInput(procedure: AnyProcedure, payload: any) {
|
|
350
|
-
if (procedure.contract.input instanceof type.NeverType === false) {
|
|
351
|
-
const type = procedure.contract.input
|
|
352
|
-
try {
|
|
353
|
-
return type.decode(payload)
|
|
354
|
-
} catch (error) {
|
|
355
|
-
if (error instanceof NeemataTypeError)
|
|
356
|
-
throw new ApiError(
|
|
357
|
-
ErrorCode.ValidationError,
|
|
358
|
-
`Input validation error: \n${prettifyError(error)}`,
|
|
359
|
-
error.issues,
|
|
360
|
-
)
|
|
361
|
-
throw error
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private handleIterableOutput(
|
|
367
|
-
procedure: AnyProcedure,
|
|
368
|
-
response: any,
|
|
369
|
-
runtimeConfig: Required<RuntimeConfig>,
|
|
370
|
-
) {
|
|
371
|
-
if (!isAsyncIterable(response))
|
|
372
|
-
throw new Error('Response is an async iterable')
|
|
373
|
-
const chunkType = procedure.contract.output
|
|
374
|
-
if (chunkType instanceof type.NeverType)
|
|
375
|
-
throw new Error('Stream procedure must have a defined output type')
|
|
376
|
-
|
|
377
|
-
return async function* (onDone?: () => void) {
|
|
378
|
-
try {
|
|
379
|
-
if (runtimeConfig.serializeOutput === false) {
|
|
380
|
-
yield* response
|
|
381
|
-
} else if (chunkType instanceof type.AnyType === false) {
|
|
382
|
-
for await (const chunk of response) {
|
|
383
|
-
yield chunkType.encode(chunk)
|
|
384
|
-
}
|
|
385
|
-
} else {
|
|
386
|
-
yield* response
|
|
387
|
-
}
|
|
388
|
-
} finally {
|
|
389
|
-
onDone?.()
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
private handleOutput(
|
|
395
|
-
procedure: AnyProcedure,
|
|
396
|
-
response: any,
|
|
397
|
-
runtimeConfig: Required<RuntimeConfig>,
|
|
398
|
-
) {
|
|
399
|
-
if (procedure.contract.output instanceof type.NeverType === false) {
|
|
400
|
-
if (runtimeConfig.serializeOutput === false) return response
|
|
401
|
-
const type = procedure.contract.output
|
|
402
|
-
return type.encode(response)
|
|
403
|
-
}
|
|
404
|
-
return undefined
|
|
405
|
-
}
|
|
406
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { MetadataKind } from '@nmtjs/core'
|
|
2
|
-
import { createMeta } from '@nmtjs/core'
|
|
3
|
-
|
|
4
|
-
import type { ApiMetaContext } from './meta.ts'
|
|
5
|
-
|
|
6
|
-
export interface RuntimeConfig {
|
|
7
|
-
serializeOutput?: boolean
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const config = createMeta<
|
|
11
|
-
RuntimeConfig,
|
|
12
|
-
MetadataKind.STATIC,
|
|
13
|
-
ApiMetaContext
|
|
14
|
-
>()
|
|
15
|
-
|
|
16
|
-
export const defaultRuntimeConfig = Object.freeze({
|
|
17
|
-
serializeOutput: true,
|
|
18
|
-
} satisfies Required<RuntimeConfig>)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export const kProcedure: unique symbol = Symbol.for('neemata:ProcedureKey')
|
|
2
|
-
export type kProcedure = typeof kProcedure
|
|
3
|
-
|
|
4
|
-
export const kDefaultProcedure: unique symbol = Symbol.for(
|
|
5
|
-
'neemata:DefaultProcedureKey',
|
|
6
|
-
)
|
|
7
|
-
export type kDefaultProcedure = typeof kDefaultProcedure
|
|
8
|
-
|
|
9
|
-
export const kRouter: unique symbol = Symbol.for('neemata:RouterKey')
|
|
10
|
-
export type kRouter = typeof kRouter
|
|
11
|
-
|
|
12
|
-
export const kRootRouter: unique symbol = Symbol.for('neemata:RootRouterKey')
|
|
13
|
-
export type kRootRouter = typeof kRootRouter
|
|
14
|
-
|
|
15
|
-
export const kMiddleware: unique symbol = Symbol.for('neemata:MiddlewareKey')
|
|
16
|
-
export type kMiddleware = typeof kMiddleware
|
|
17
|
-
|
|
18
|
-
export const kGuard: unique symbol = Symbol.for('neemata:GuardKey')
|
|
19
|
-
export type kGuard = typeof kGuard
|
|
20
|
-
|
|
21
|
-
export const kFilter: unique symbol = Symbol.for('neemata:FilterKey')
|
|
22
|
-
export type kFilter = typeof kFilter
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { ErrorClass, MaybePromise } from '@nmtjs/common'
|
|
2
|
-
import type { Dependant, Dependencies, DependencyContext } from '@nmtjs/core'
|
|
3
|
-
|
|
4
|
-
import { kFilter } from './constants.ts'
|
|
5
|
-
|
|
6
|
-
export interface Filter<
|
|
7
|
-
FilterError extends ErrorClass = ErrorClass,
|
|
8
|
-
Deps extends Dependencies = Dependencies,
|
|
9
|
-
> extends Dependant<Deps> {
|
|
10
|
-
[kFilter]: true
|
|
11
|
-
errorClass: FilterError
|
|
12
|
-
catch: (
|
|
13
|
-
ctx: DependencyContext<Deps>,
|
|
14
|
-
error: InstanceType<FilterError>,
|
|
15
|
-
) => MaybePromise<Error>
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type AnyFilter<Error extends ErrorClass = ErrorClass> = Filter<
|
|
19
|
-
Error,
|
|
20
|
-
any
|
|
21
|
-
>
|
|
22
|
-
|
|
23
|
-
export function createFilter<
|
|
24
|
-
FilterError extends ErrorClass,
|
|
25
|
-
Deps extends Dependencies = {},
|
|
26
|
-
>(params: {
|
|
27
|
-
errorClass: FilterError
|
|
28
|
-
dependencies?: Deps
|
|
29
|
-
catch: Filter<FilterError, Deps>['catch']
|
|
30
|
-
}): Filter<FilterError, Deps> {
|
|
31
|
-
const { errorClass, catch: handler, dependencies = {} as Deps } = params
|
|
32
|
-
|
|
33
|
-
return Object.freeze({
|
|
34
|
-
errorClass,
|
|
35
|
-
dependencies,
|
|
36
|
-
catch: handler,
|
|
37
|
-
[kFilter]: true,
|
|
38
|
-
}) as Filter<FilterError, Deps>
|
|
39
|
-
}
|