@nmtjs/client 0.0.4 → 0.1.1
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/lib/client-runtime.js +43 -27
- package/dist/lib/client-runtime.js.map +1 -1
- package/dist/lib/client-static.js.map +1 -1
- package/dist/lib/client.js +2 -0
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/subscription.js.map +1 -1
- package/dist/lib/transport.js.map +1 -1
- package/lib/client-runtime.ts +74 -48
- package/lib/client-static.ts +17 -14
- package/lib/client.ts +3 -0
- package/lib/subscription.ts +3 -6
- package/lib/transport.ts +1 -1
- package/package.json +7 -5
|
@@ -1,21 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { NeverType } from '@nmtjs/type';
|
|
2
|
+
import { compile } from '@nmtjs/type/compiler';
|
|
3
3
|
import { Client } from "./client.js";
|
|
4
4
|
export class RuntimeClient extends Client {
|
|
5
|
+
contracts;
|
|
5
6
|
#callers;
|
|
6
|
-
constructor(
|
|
7
|
-
super(options, Object.values(
|
|
7
|
+
constructor(contracts, options){
|
|
8
|
+
super(options, Object.values(contracts).map((s)=>s.contract.name));
|
|
9
|
+
this.contracts = contracts;
|
|
8
10
|
const callers = {};
|
|
9
|
-
for (const [serviceKey,
|
|
10
|
-
|
|
11
|
+
for (const [serviceKey, service] of Object.entries(contracts)){
|
|
12
|
+
service.contract.procedures;
|
|
11
13
|
callers[serviceKey] = {};
|
|
12
|
-
for(const procedureName in
|
|
13
|
-
const { input, output } =
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
for(const procedureName in service.contract.procedures){
|
|
15
|
+
const { input, output } = service.contract.procedures[procedureName];
|
|
16
|
+
function decodeOutput(data) {
|
|
17
|
+
if (output instanceof NeverType) return undefined;
|
|
18
|
+
const compiled = service.compiled.get(output);
|
|
19
|
+
const result = compiled.decode(data);
|
|
20
|
+
if (result.success) {
|
|
21
|
+
return result.value;
|
|
22
|
+
} else {
|
|
23
|
+
console.dir(result.error);
|
|
24
|
+
throw new Error('Failed to decode output', {
|
|
25
|
+
cause: result.error
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
callers[serviceKey][procedureName] = this.createCaller(service.contract.name, procedureName, {
|
|
30
|
+
timeout: service.contract.timeout,
|
|
16
31
|
transformInput: (data)=>{
|
|
17
|
-
if (
|
|
18
|
-
const compiled =
|
|
32
|
+
if (input instanceof NeverType) return undefined;
|
|
33
|
+
const compiled = service.compiled.get(input);
|
|
19
34
|
const result = compiled.encode(data);
|
|
20
35
|
if (result.success) {
|
|
21
36
|
return result.value;
|
|
@@ -27,16 +42,11 @@ export class RuntimeClient extends Client {
|
|
|
27
42
|
}
|
|
28
43
|
},
|
|
29
44
|
transformOutput: (data)=>{
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (result.success) {
|
|
34
|
-
return result.value;
|
|
45
|
+
if (service.contract.procedures[procedureName].type === 'neemata:subscription') {
|
|
46
|
+
data.payload = decodeOutput(data.payload);
|
|
47
|
+
return data;
|
|
35
48
|
} else {
|
|
36
|
-
|
|
37
|
-
throw new Error('Failed to decode output', {
|
|
38
|
-
cause: result.error
|
|
39
|
-
});
|
|
49
|
+
return decodeOutput(data);
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
52
|
});
|
|
@@ -47,21 +57,27 @@ export class RuntimeClient extends Client {
|
|
|
47
57
|
get call() {
|
|
48
58
|
return this.#callers;
|
|
49
59
|
}
|
|
60
|
+
checkTransport(transport) {
|
|
61
|
+
for (const { contract } of Object.values(this.contracts)){
|
|
62
|
+
if (!contract.transports[transport.type]) throw new Error(`Transport [${transport.type}] not supported for service [${contract.name}]`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
50
65
|
}
|
|
51
66
|
export const compileContract = (contract)=>{
|
|
52
67
|
const compiled = new Map();
|
|
53
|
-
for (const
|
|
54
|
-
const { input, output
|
|
55
|
-
if (
|
|
68
|
+
for (const procedure of Object.values(contract.procedures)){
|
|
69
|
+
const { input, output } = procedure;
|
|
70
|
+
if (procedure.type === 'neemata:subscription') {
|
|
71
|
+
const { events } = procedure;
|
|
56
72
|
for (const event of Object.values(events)){
|
|
57
|
-
compiled.set(event, compile(event));
|
|
73
|
+
compiled.set(event.payload, compile(event.payload));
|
|
58
74
|
}
|
|
59
75
|
}
|
|
60
76
|
compiled.set(input, compile(input));
|
|
61
77
|
compiled.set(output, compile(output));
|
|
62
78
|
}
|
|
63
|
-
for (const
|
|
64
|
-
compiled.set(
|
|
79
|
+
for (const event of Object.values(contract.events)){
|
|
80
|
+
compiled.set(event.payload, compile(event.payload));
|
|
65
81
|
}
|
|
66
82
|
return {
|
|
67
83
|
compiled,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/client-runtime.ts"],"sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"sources":["../../../lib/client-runtime.ts"],"sourcesContent":["import type {\n TEventContract,\n TServiceContract,\n TSubscriptionContract,\n} from '@nmtjs/contract'\nimport { type BaseType, NeverType, type t } from '@nmtjs/type'\nimport { type Compiled, compile } from '@nmtjs/type/compiler'\n\nimport { Client, type ClientOptions } from './client.ts'\nimport type { Subscription } from './subscription.ts'\nimport type { ClientTransport } from './transport.ts'\nimport type { ClientCallOptions, InputType, OutputType } from './types.ts'\n\ntype CompiledContract<T extends TServiceContract = TServiceContract> = {\n compiled: Map<BaseType, Compiled>\n contract: T\n}\n\ntype ClientServices = Record<string, CompiledContract>\n\ntype ClientCallers<Services extends ClientServices> = {\n [K in keyof Services]: {\n [P in keyof Services[K]['contract']['procedures']]: (\n ...args: Services[K]['contract']['procedures'][P]['input'] extends NeverType\n ? [options?: ClientCallOptions]\n : [\n data: InputType<\n t.infer.decoded<Services[K]['contract']['procedures'][P]['input']>\n >,\n options?: ClientCallOptions,\n ]\n ) => Promise<\n Services[K]['contract']['procedures'][P] extends TSubscriptionContract\n ? {\n payload: Services[K]['contract']['procedures'][P]['output'] extends NeverType\n ? undefined\n : t.infer.decoded<\n Services[K]['contract']['procedures'][P]['output']\n >\n subscription: Subscription<{\n [KE in keyof Services[K]['contract']['procedures'][P]['events']]: [\n t.infer.decoded<\n Services[K]['contract']['procedures'][P]['events'][KE]['payload']\n >,\n ]\n }>\n }\n : Services[K]['contract']['procedures'][P]['output'] extends NeverType\n ? void\n : OutputType<\n t.infer.decoded<\n Services[K]['contract']['procedures'][P]['output']\n >\n >\n >\n }\n}\n\nexport class RuntimeClient<Services extends ClientServices> extends Client {\n #callers: ClientCallers<Services>\n\n constructor(\n protected readonly contracts: Services,\n options: ClientOptions,\n ) {\n super(\n options,\n Object.values(contracts).map((s) => s.contract.name),\n )\n\n const callers = {} as any\n for (const [serviceKey, service] of Object.entries(contracts)) {\n service.contract.procedures\n\n callers[serviceKey] = {} as any\n\n for (const procedureName in service.contract.procedures) {\n const { input, output } = service.contract.procedures[procedureName]\n\n function decodeOutput(data) {\n if (output instanceof NeverType) return undefined\n const compiled = service.compiled.get(output)!\n const result = compiled.decode(data)\n if (result.success) {\n return result.value\n } else {\n console.dir(result.error)\n throw new Error('Failed to decode output', {\n cause: result.error,\n })\n }\n }\n\n callers[serviceKey][procedureName] = this.createCaller(\n service.contract.name,\n procedureName,\n {\n timeout: service.contract.timeout,\n transformInput: (data: any) => {\n if (input instanceof NeverType) return undefined\n const compiled = service.compiled.get(input)!\n const result = compiled.encode(data)\n if (result.success) {\n return result.value\n } else {\n console.dir(result.error)\n throw new Error('Failed to encode input', {\n cause: result.error,\n })\n }\n },\n transformOutput: (data: any) => {\n if (\n service.contract.procedures[procedureName].type ===\n 'neemata:subscription'\n ) {\n data.payload = decodeOutput(data.payload)\n return data\n } else {\n return decodeOutput(data)\n }\n },\n },\n )\n }\n }\n this.#callers = callers\n }\n\n get call() {\n return this.#callers\n }\n\n protected checkTransport(transport: ClientTransport): void {\n for (const { contract } of Object.values(this.contracts)) {\n if (!contract.transports[transport.type])\n throw new Error(\n `Transport [${transport.type}] not supported for service [${contract.name}]`,\n )\n }\n }\n}\n\nexport const compileContract = <T extends TServiceContract>(\n contract: T,\n): CompiledContract<T> => {\n const compiled = new Map<BaseType, Compiled>()\n\n for (const procedure of Object.values(contract.procedures)) {\n const { input, output } = procedure\n if (procedure.type === 'neemata:subscription') {\n const { events } = procedure\n for (const event of Object.values(events) as TEventContract[]) {\n compiled.set(event.payload, compile(event.payload))\n }\n }\n compiled.set(input, compile(input))\n compiled.set(output, compile(output))\n }\n for (const event of Object.values(contract.events)) {\n compiled.set(event.payload, compile(event.payload))\n }\n\n return {\n compiled,\n contract,\n }\n}\n"],"names":["NeverType","compile","Client","RuntimeClient","constructor","contracts","options","Object","values","map","s","contract","name","callers","serviceKey","service","entries","procedures","procedureName","input","output","decodeOutput","data","undefined","compiled","get","result","decode","success","value","console","dir","error","Error","cause","createCaller","timeout","transformInput","encode","transformOutput","type","payload","call","checkTransport","transport","transports","compileContract","Map","procedure","events","event","set"],"mappings":"AAKA,SAAwBA,SAAS,QAAgB,cAAa;AAC9D,SAAwBC,OAAO,QAAQ,uBAAsB;AAE7D,SAASC,MAAM,QAA4B,cAAa;AAkDxD,OAAO,MAAMC,sBAAuDD;;IAClE,CAAA,OAAQ,CAAyB;IAEjCE,YACE,AAAmBC,SAAmB,EACtCC,OAAsB,CACtB;QACA,KAAK,CACHA,SACAC,OAAOC,MAAM,CAACH,WAAWI,GAAG,CAAC,CAACC,IAAMA,EAAEC,QAAQ,CAACC,IAAI;aALlCP,YAAAA;QAQnB,MAAMQ,UAAU,CAAC;QACjB,KAAK,MAAM,CAACC,YAAYC,QAAQ,IAAIR,OAAOS,OAAO,CAACX,WAAY;YAC7DU,QAAQJ,QAAQ,CAACM,UAAU;YAE3BJ,OAAO,CAACC,WAAW,GAAG,CAAC;YAEvB,IAAK,MAAMI,iBAAiBH,QAAQJ,QAAQ,CAACM,UAAU,CAAE;gBACvD,MAAM,EAAEE,KAAK,EAAEC,MAAM,EAAE,GAAGL,QAAQJ,QAAQ,CAACM,UAAU,CAACC,cAAc;gBAEpE,SAASG,aAAaC,IAAI;oBACxB,IAAIF,kBAAkBpB,WAAW,OAAOuB;oBACxC,MAAMC,WAAWT,QAAQS,QAAQ,CAACC,GAAG,CAACL;oBACtC,MAAMM,SAASF,SAASG,MAAM,CAACL;oBAC/B,IAAII,OAAOE,OAAO,EAAE;wBAClB,OAAOF,OAAOG,KAAK;oBACrB,OAAO;wBACLC,QAAQC,GAAG,CAACL,OAAOM,KAAK;wBACxB,MAAM,IAAIC,MAAM,2BAA2B;4BACzCC,OAAOR,OAAOM,KAAK;wBACrB;oBACF;gBACF;gBAEAnB,OAAO,CAACC,WAAW,CAACI,cAAc,GAAG,IAAI,CAACiB,YAAY,CACpDpB,QAAQJ,QAAQ,CAACC,IAAI,EACrBM,eACA;oBACEkB,SAASrB,QAAQJ,QAAQ,CAACyB,OAAO;oBACjCC,gBAAgB,CAACf;wBACf,IAAIH,iBAAiBnB,WAAW,OAAOuB;wBACvC,MAAMC,WAAWT,QAAQS,QAAQ,CAACC,GAAG,CAACN;wBACtC,MAAMO,SAASF,SAASc,MAAM,CAAChB;wBAC/B,IAAII,OAAOE,OAAO,EAAE;4BAClB,OAAOF,OAAOG,KAAK;wBACrB,OAAO;4BACLC,QAAQC,GAAG,CAACL,OAAOM,KAAK;4BACxB,MAAM,IAAIC,MAAM,0BAA0B;gCACxCC,OAAOR,OAAOM,KAAK;4BACrB;wBACF;oBACF;oBACAO,iBAAiB,CAACjB;wBAChB,IACEP,QAAQJ,QAAQ,CAACM,UAAU,CAACC,cAAc,CAACsB,IAAI,KAC/C,wBACA;4BACAlB,KAAKmB,OAAO,GAAGpB,aAAaC,KAAKmB,OAAO;4BACxC,OAAOnB;wBACT,OAAO;4BACL,OAAOD,aAAaC;wBACtB;oBACF;gBACF;YAEJ;QACF;QACA,IAAI,CAAC,CAAA,OAAQ,GAAGT;IAClB;IAEA,IAAI6B,OAAO;QACT,OAAO,IAAI,CAAC,CAAA,OAAQ;IACtB;IAEUC,eAAeC,SAA0B,EAAQ;QACzD,KAAK,MAAM,EAAEjC,QAAQ,EAAE,IAAIJ,OAAOC,MAAM,CAAC,IAAI,CAACH,SAAS,EAAG;YACxD,IAAI,CAACM,SAASkC,UAAU,CAACD,UAAUJ,IAAI,CAAC,EACtC,MAAM,IAAIP,MACR,CAAC,WAAW,EAAEW,UAAUJ,IAAI,CAAC,6BAA6B,EAAE7B,SAASC,IAAI,CAAC,CAAC,CAAC;QAElF;IACF;AACF;AAEA,OAAO,MAAMkC,kBAAkB,CAC7BnC;IAEA,MAAMa,WAAW,IAAIuB;IAErB,KAAK,MAAMC,aAAazC,OAAOC,MAAM,CAACG,SAASM,UAAU,EAAG;QAC1D,MAAM,EAAEE,KAAK,EAAEC,MAAM,EAAE,GAAG4B;QAC1B,IAAIA,UAAUR,IAAI,KAAK,wBAAwB;YAC7C,MAAM,EAAES,MAAM,EAAE,GAAGD;YACnB,KAAK,MAAME,SAAS3C,OAAOC,MAAM,CAACyC,QAA6B;gBAC7DzB,SAAS2B,GAAG,CAACD,MAAMT,OAAO,EAAExC,QAAQiD,MAAMT,OAAO;YACnD;QACF;QACAjB,SAAS2B,GAAG,CAAChC,OAAOlB,QAAQkB;QAC5BK,SAAS2B,GAAG,CAAC/B,QAAQnB,QAAQmB;IAC/B;IACA,KAAK,MAAM8B,SAAS3C,OAAOC,MAAM,CAACG,SAASsC,MAAM,EAAG;QAClDzB,SAAS2B,GAAG,CAACD,MAAMT,OAAO,EAAExC,QAAQiD,MAAMT,OAAO;IACnD;IAEA,OAAO;QACLjB;QACAb;IACF;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/client-static.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../lib/client-static.ts"],"sourcesContent":["import type { TServiceContract, TSubscriptionContract } from '@nmtjs/contract'\nimport type { NeverType, t } from '@nmtjs/type'\nimport { Client, type ClientOptions } from './client.ts'\nimport type { Subscription } from './subscription.ts'\nimport type { ClientCallOptions, InputType, OutputType } from './types.ts'\n\ntype ClientServices = Record<string, TServiceContract>\n\ntype ClientCallers<Services extends ClientServices> = {\n [K in keyof Services]: {\n [P in keyof Services[K]['procedures']]: (\n ...args: Services[K]['procedures'][P]['input'] extends NeverType\n ? [options?: ClientCallOptions]\n : [\n data: InputType<\n t.infer.encoded<Services[K]['procedures'][P]['input']>\n >,\n options?: ClientCallOptions,\n ]\n ) => Promise<\n Services[K]['procedures'][P] extends TSubscriptionContract\n ? {\n payload: Services[K]['procedures'][P]['output'] extends NeverType\n ? undefined\n : t.infer.encoded<Services[K]['procedures'][P]['output']>\n subscription: Subscription<{\n [KE in keyof Services[K]['procedures'][P]['events']]: [\n t.infer.encoded<\n Services[K]['procedures'][P]['events'][KE]['payload']\n >,\n ]\n }>\n }\n : Services[K]['procedures'][P]['output'] extends NeverType\n ? void\n : OutputType<t.infer.encoded<Services[K]['procedures'][P]['output']>>\n >\n }\n}\n\nexport class StaticClient<Services extends ClientServices> extends Client {\n #callers: ClientCallers<Services>\n\n constructor(\n services: { [K in keyof Services]: Services[K]['name'] },\n options: ClientOptions,\n ) {\n super(options, Object.values(services))\n\n const callers = {} as any\n\n for (const [serviceKey, serviceName] of Object.entries(services)) {\n callers[serviceKey] = new Proxy(Object(), {\n get: (target, prop, receiver) => {\n return this.createCaller(serviceName, prop as string)\n },\n })\n }\n\n this.#callers = callers\n }\n\n get call() {\n return this.#callers\n }\n}\n"],"names":["Client","StaticClient","constructor","services","options","Object","values","callers","serviceKey","serviceName","entries","Proxy","get","target","prop","receiver","createCaller","call"],"mappings":"AAEA,SAASA,MAAM,QAA4B,cAAa;AAsCxD,OAAO,MAAMC,qBAAsDD;IACjE,CAAA,OAAQ,CAAyB;IAEjCE,YACEC,QAAwD,EACxDC,OAAsB,CACtB;QACA,KAAK,CAACA,SAASC,OAAOC,MAAM,CAACH;QAE7B,MAAMI,UAAU,CAAC;QAEjB,KAAK,MAAM,CAACC,YAAYC,YAAY,IAAIJ,OAAOK,OAAO,CAACP,UAAW;YAChEI,OAAO,CAACC,WAAW,GAAG,IAAIG,MAAMN,UAAU;gBACxCO,KAAK,CAACC,QAAQC,MAAMC;oBAClB,OAAO,IAAI,CAACC,YAAY,CAACP,aAAaK;gBACxC;YACF;QACF;QAEA,IAAI,CAAC,CAAA,OAAQ,GAAGP;IAClB;IAEA,IAAIU,OAAO;QACT,OAAO,IAAI,CAAC,CAAA,OAAQ;IACtB;AACF"}
|
package/dist/lib/client.js
CHANGED
|
@@ -25,6 +25,7 @@ export class Client extends utils.EventEmitter {
|
|
|
25
25
|
format: this.format,
|
|
26
26
|
auth: this.auth
|
|
27
27
|
});
|
|
28
|
+
this.checkTransport(this.transport);
|
|
28
29
|
return this;
|
|
29
30
|
}
|
|
30
31
|
useFormat(format) {
|
|
@@ -41,6 +42,7 @@ export class Client extends utils.EventEmitter {
|
|
|
41
42
|
await this.disconnect();
|
|
42
43
|
await this.connect();
|
|
43
44
|
}
|
|
45
|
+
checkTransport(transport) {}
|
|
44
46
|
createCaller(service, procedure, { timeout = this.options.defaultTimeout, transformInput, transformOutput } = {}) {
|
|
45
47
|
return async (payload, options = {})=>{
|
|
46
48
|
const { signal } = options;
|
package/dist/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/client.ts"],"sourcesContent":["import { type BaseClientFormat, ErrorCode } from '@nmtjs/common'\n\nimport { ClientError } from './common.ts'\nimport type { ClientTransport } from './transport.ts'\nimport type { ClientCallOptions } from './types.ts'\nimport * as utils from './utils.ts'\n\nexport type ClientOptions = {\n defaultTimeout: number\n debug?: boolean\n}\n\nexport abstract class Client extends utils.EventEmitter {\n protected transport!: ClientTransport\n protected format!: BaseClientFormat\n\n auth?: string\n\n private ids = {\n call: 0,\n stream: 0,\n }\n\n constructor(\n protected readonly options: ClientOptions,\n protected services: string[],\n ) {\n super()\n if (!options.defaultTimeout) options.defaultTimeout = 15000\n }\n\n useTransport<T extends new (...args: any[]) => ClientTransport>(\n transportClass: T,\n ...options: ConstructorParameters<T>\n ) {\n this.transport = new transportClass(...options)\n this.transport.client = Object.freeze({\n services: this.services,\n format: this.format,\n auth: this.auth,\n })\n return this as Omit<this, 'useTransport'>\n }\n\n useFormat(format: BaseClientFormat) {\n this.format = format\n return this as Omit<this, 'useFormat'>\n }\n\n async connect() {\n await this.transport.connect()\n }\n\n async disconnect() {\n await this.transport.disconnect()\n }\n\n async reconnect() {\n await this.disconnect()\n await this.connect()\n }\n\n protected createCaller(\n service: string,\n procedure: string,\n {\n timeout = this.options.defaultTimeout,\n transformInput,\n transformOutput,\n }: {\n timeout?: number\n transformInput?: (input: any) => any\n transformOutput?: (output: any) => any\n } = {},\n ) {\n return async (payload: any, options: ClientCallOptions = {}) => {\n const { signal } = options\n\n const abortSignal = signal\n ? AbortSignal.any([signal, AbortSignal.timeout(timeout)])\n : AbortSignal.timeout(timeout)\n\n const callId = ++this.ids.call\n\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] ${service}/${procedure}`)\n console.log(payload)\n console.groupEnd()\n }\n\n const callExecution = this.transport\n .rpc({\n callId,\n service,\n procedure,\n payload: transformInput ? transformInput(payload) : payload,\n signal: abortSignal,\n })\n .then((result) => {\n if (result.success) return result.value\n throw new ClientError(\n result.error.code,\n result.error.message,\n result.error.data,\n )\n })\n\n const callTimeout = utils.forAborted(abortSignal).catch(() => {\n const error = new ClientError(ErrorCode.RequestTimeout)\n return Promise.reject(error)\n })\n\n try {\n const response = await Promise.race([callTimeout, callExecution])\n\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] Success`)\n console.log(response)\n console.groupEnd()\n }\n\n return transformOutput ? transformOutput(response) : response\n } catch (error) {\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] Error`)\n console.log(error)\n console.groupEnd()\n }\n\n throw error\n }\n }\n }\n}\n"],"names":["ErrorCode","ClientError","utils","Client","EventEmitter","transport","format","auth","ids","constructor","options","services","call","stream","defaultTimeout","useTransport","transportClass","client","Object","freeze","useFormat","connect","disconnect","reconnect","createCaller","service","procedure","timeout","transformInput","transformOutput","payload","signal","abortSignal","AbortSignal","any","callId","debug","console","groupCollapsed","log","groupEnd","callExecution","rpc","then","result","success","value","error","code","message","data","callTimeout","forAborted","catch","RequestTimeout","Promise","reject","response","race"],"mappings":"AAAA,SAAgCA,SAAS,QAAQ,gBAAe;AAEhE,SAASC,WAAW,QAAQ,cAAa;AAGzC,YAAYC,WAAW,aAAY;AAOnC,OAAO,MAAeC,eAAeD,MAAME,YAAY;;;IAC3CC,UAA2B;IAC3BC,OAAyB;IAEnCC,KAAa;IAELC,IAGP;IAEDC,YACE,AAAmBC,OAAsB,EACzC,AAAUC,QAAkB,CAC5B;QACA,KAAK;aAHcD,UAAAA;aACTC,WAAAA;aAPJH,MAAM;YACZI,MAAM;YACNC,QAAQ;QACV;QAOE,IAAI,CAACH,QAAQI,cAAc,EAAEJ,QAAQI,cAAc,GAAG;IACxD;IAEAC,aACEC,cAAiB,EACjB,GAAGN,OAAiC,EACpC;QACA,IAAI,CAACL,SAAS,GAAG,IAAIW,kBAAkBN;QACvC,IAAI,CAACL,SAAS,CAACY,MAAM,GAAGC,OAAOC,MAAM,CAAC;YACpCR,UAAU,IAAI,CAACA,QAAQ;YACvBL,QAAQ,IAAI,CAACA,MAAM;YACnBC,MAAM,IAAI,CAACA,IAAI;QACjB;QACA,OAAO,IAAI;IACb;
|
|
1
|
+
{"version":3,"sources":["../../../lib/client.ts"],"sourcesContent":["import { type BaseClientFormat, ErrorCode } from '@nmtjs/common'\n\nimport { ClientError } from './common.ts'\nimport type { ClientTransport } from './transport.ts'\nimport type { ClientCallOptions } from './types.ts'\nimport * as utils from './utils.ts'\n\nexport type ClientOptions = {\n defaultTimeout: number\n debug?: boolean\n}\n\nexport abstract class Client extends utils.EventEmitter {\n protected transport!: ClientTransport\n protected format!: BaseClientFormat\n\n auth?: string\n\n private ids = {\n call: 0,\n stream: 0,\n }\n\n constructor(\n protected readonly options: ClientOptions,\n protected services: string[],\n ) {\n super()\n if (!options.defaultTimeout) options.defaultTimeout = 15000\n }\n\n useTransport<T extends new (...args: any[]) => ClientTransport>(\n transportClass: T,\n ...options: ConstructorParameters<T>\n ) {\n this.transport = new transportClass(...options)\n this.transport.client = Object.freeze({\n services: this.services,\n format: this.format,\n auth: this.auth,\n })\n this.checkTransport(this.transport)\n return this as Omit<this, 'useTransport'>\n }\n\n useFormat(format: BaseClientFormat) {\n this.format = format\n return this as Omit<this, 'useFormat'>\n }\n\n async connect() {\n await this.transport.connect()\n }\n\n async disconnect() {\n await this.transport.disconnect()\n }\n\n async reconnect() {\n await this.disconnect()\n await this.connect()\n }\n\n protected checkTransport(transport: ClientTransport) {}\n\n protected createCaller(\n service: string,\n procedure: string,\n {\n timeout = this.options.defaultTimeout,\n transformInput,\n transformOutput,\n }: {\n timeout?: number\n transformInput?: (input: any) => any\n transformOutput?: (output: any) => any\n } = {},\n ) {\n return async (payload: any, options: ClientCallOptions = {}) => {\n const { signal } = options\n\n const abortSignal = signal\n ? AbortSignal.any([signal, AbortSignal.timeout(timeout)])\n : AbortSignal.timeout(timeout)\n\n const callId = ++this.ids.call\n\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] ${service}/${procedure}`)\n console.log(payload)\n console.groupEnd()\n }\n\n const callExecution = this.transport\n .rpc({\n callId,\n service,\n procedure,\n payload: transformInput ? transformInput(payload) : payload,\n signal: abortSignal,\n })\n .then((result) => {\n if (result.success) return result.value\n throw new ClientError(\n result.error.code,\n result.error.message,\n result.error.data,\n )\n })\n\n const callTimeout = utils.forAborted(abortSignal).catch(() => {\n const error = new ClientError(ErrorCode.RequestTimeout)\n return Promise.reject(error)\n })\n\n try {\n const response = await Promise.race([callTimeout, callExecution])\n\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] Success`)\n console.log(response)\n console.groupEnd()\n }\n\n return transformOutput ? transformOutput(response) : response\n } catch (error) {\n if (this.options.debug) {\n console.groupCollapsed(`RPC [${callId}] Error`)\n console.log(error)\n console.groupEnd()\n }\n\n throw error\n }\n }\n }\n}\n"],"names":["ErrorCode","ClientError","utils","Client","EventEmitter","transport","format","auth","ids","constructor","options","services","call","stream","defaultTimeout","useTransport","transportClass","client","Object","freeze","checkTransport","useFormat","connect","disconnect","reconnect","createCaller","service","procedure","timeout","transformInput","transformOutput","payload","signal","abortSignal","AbortSignal","any","callId","debug","console","groupCollapsed","log","groupEnd","callExecution","rpc","then","result","success","value","error","code","message","data","callTimeout","forAborted","catch","RequestTimeout","Promise","reject","response","race"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/subscription.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../lib/subscription.ts"],"sourcesContent":["import { EventEmitter, type EventMap } from './utils.ts'\n\nexport class Subscription<\n Events extends EventMap = EventMap,\n> extends EventEmitter<Events> {\n constructor(\n readonly key: string,\n readonly unsubscribe: () => void,\n ) {\n super()\n }\n}\n"],"names":["EventEmitter","Subscription","constructor","key","unsubscribe"],"mappings":"AAAA,SAASA,YAAY,QAAuB,aAAY;AAExD,OAAO,MAAMC,qBAEHD;;;IACRE,YACE,AAASC,GAAW,EACpB,AAASC,WAAuB,CAChC;QACA,KAAK;aAHID,MAAAA;aACAC,cAAAA;IAGX;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/transport.ts"],"sourcesContent":["import type { BaseClientFormat } from '@nmtjs/common'\nimport { EventEmitter, type EventMap } from './utils.ts'\n\nexport type ClientTransportRpcCall = {\n service: string\n procedure: string\n callId: number\n payload: any\n signal: AbortSignal\n}\n\nexport type ClientTransportRpcResult =\n | {\n success: false\n error: { code: string; message?: string; data?: any }\n }\n | {\n success: true\n value: any\n }\n\nexport abstract class ClientTransport<\n T extends EventMap =
|
|
1
|
+
{"version":3,"sources":["../../../lib/transport.ts"],"sourcesContent":["import type { BaseClientFormat } from '@nmtjs/common'\nimport { EventEmitter, type EventMap } from './utils.ts'\n\nexport type ClientTransportRpcCall = {\n service: string\n procedure: string\n callId: number\n payload: any\n signal: AbortSignal\n}\n\nexport type ClientTransportRpcResult =\n | {\n success: false\n error: { code: string; message?: string; data?: any }\n }\n | {\n success: true\n value: any\n }\n\nexport abstract class ClientTransport<\n T extends EventMap = EventMap,\n> extends EventEmitter<\n T & { event: [service: string, event: string, payload: any] }\n> {\n abstract type: string\n\n client!: {\n readonly services: string[]\n readonly format: BaseClientFormat\n readonly auth?: string\n }\n\n abstract connect(): Promise<void>\n abstract disconnect(): Promise<void>\n abstract rpc(\n params: ClientTransportRpcCall,\n ): Promise<ClientTransportRpcResult>\n}\n"],"names":["EventEmitter","ClientTransport","client"],"mappings":"AACA,SAASA,YAAY,QAAuB,aAAY;AAoBxD,OAAO,MAAeC,wBAEZD;IAKRE,OAIC;AAOH"}
|
package/lib/client-runtime.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
Decoded,
|
|
3
2
|
TEventContract,
|
|
4
|
-
TSchema,
|
|
5
3
|
TServiceContract,
|
|
6
4
|
TSubscriptionContract,
|
|
7
5
|
} from '@nmtjs/contract'
|
|
8
|
-
import { type
|
|
9
|
-
import {
|
|
6
|
+
import { type BaseType, NeverType, type t } from '@nmtjs/type'
|
|
7
|
+
import { type Compiled, compile } from '@nmtjs/type/compiler'
|
|
8
|
+
|
|
10
9
|
import { Client, type ClientOptions } from './client.ts'
|
|
11
10
|
import type { Subscription } from './subscription.ts'
|
|
11
|
+
import type { ClientTransport } from './transport.ts'
|
|
12
12
|
import type { ClientCallOptions, InputType, OutputType } from './types.ts'
|
|
13
13
|
|
|
14
14
|
type CompiledContract<T extends TServiceContract = TServiceContract> = {
|
|
15
|
-
compiled: Map<
|
|
15
|
+
compiled: Map<BaseType, Compiled>
|
|
16
16
|
contract: T
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -21,32 +21,36 @@ type ClientServices = Record<string, CompiledContract>
|
|
|
21
21
|
type ClientCallers<Services extends ClientServices> = {
|
|
22
22
|
[K in keyof Services]: {
|
|
23
23
|
[P in keyof Services[K]['contract']['procedures']]: (
|
|
24
|
-
...args:
|
|
25
|
-
Services[K]['contract']['procedures'][P]['input']
|
|
26
|
-
> extends never
|
|
24
|
+
...args: Services[K]['contract']['procedures'][P]['input'] extends NeverType
|
|
27
25
|
? [options?: ClientCallOptions]
|
|
28
26
|
: [
|
|
29
27
|
data: InputType<
|
|
30
|
-
|
|
28
|
+
t.infer.decoded<Services[K]['contract']['procedures'][P]['input']>
|
|
31
29
|
>,
|
|
32
30
|
options?: ClientCallOptions,
|
|
33
31
|
]
|
|
34
32
|
) => Promise<
|
|
35
33
|
Services[K]['contract']['procedures'][P] extends TSubscriptionContract
|
|
36
34
|
? {
|
|
37
|
-
payload:
|
|
38
|
-
Services[K]['contract']['procedures'][P]['output']
|
|
39
|
-
> extends never
|
|
35
|
+
payload: Services[K]['contract']['procedures'][P]['output'] extends NeverType
|
|
40
36
|
? undefined
|
|
41
|
-
:
|
|
42
|
-
|
|
37
|
+
: t.infer.decoded<
|
|
38
|
+
Services[K]['contract']['procedures'][P]['output']
|
|
39
|
+
>
|
|
40
|
+
subscription: Subscription<{
|
|
41
|
+
[KE in keyof Services[K]['contract']['procedures'][P]['events']]: [
|
|
42
|
+
t.infer.decoded<
|
|
43
|
+
Services[K]['contract']['procedures'][P]['events'][KE]['payload']
|
|
44
|
+
>,
|
|
45
|
+
]
|
|
46
|
+
}>
|
|
43
47
|
}
|
|
44
|
-
:
|
|
45
|
-
Services[K]['contract']['procedures'][P]['static']
|
|
46
|
-
> extends never
|
|
48
|
+
: Services[K]['contract']['procedures'][P]['output'] extends NeverType
|
|
47
49
|
? void
|
|
48
50
|
: OutputType<
|
|
49
|
-
|
|
51
|
+
t.infer.decoded<
|
|
52
|
+
Services[K]['contract']['procedures'][P]['output']
|
|
53
|
+
>
|
|
50
54
|
>
|
|
51
55
|
>
|
|
52
56
|
}
|
|
@@ -55,33 +59,46 @@ type ClientCallers<Services extends ClientServices> = {
|
|
|
55
59
|
export class RuntimeClient<Services extends ClientServices> extends Client {
|
|
56
60
|
#callers: ClientCallers<Services>
|
|
57
61
|
|
|
58
|
-
constructor(
|
|
62
|
+
constructor(
|
|
63
|
+
protected readonly contracts: Services,
|
|
64
|
+
options: ClientOptions,
|
|
65
|
+
) {
|
|
59
66
|
super(
|
|
60
67
|
options,
|
|
61
|
-
Object.values(
|
|
68
|
+
Object.values(contracts).map((s) => s.contract.name),
|
|
62
69
|
)
|
|
63
70
|
|
|
64
71
|
const callers = {} as any
|
|
65
|
-
for (const [serviceKey,
|
|
66
|
-
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Transport [${this.transport.type}] not supported for service [${serviceContract.contract.name}]`,
|
|
69
|
-
)
|
|
72
|
+
for (const [serviceKey, service] of Object.entries(contracts)) {
|
|
73
|
+
service.contract.procedures
|
|
70
74
|
|
|
71
75
|
callers[serviceKey] = {} as any
|
|
72
76
|
|
|
73
|
-
for (const procedureName in
|
|
74
|
-
const { input, output } =
|
|
75
|
-
|
|
77
|
+
for (const procedureName in service.contract.procedures) {
|
|
78
|
+
const { input, output } = service.contract.procedures[procedureName]
|
|
79
|
+
|
|
80
|
+
function decodeOutput(data) {
|
|
81
|
+
if (output instanceof NeverType) return undefined
|
|
82
|
+
const compiled = service.compiled.get(output)!
|
|
83
|
+
const result = compiled.decode(data)
|
|
84
|
+
if (result.success) {
|
|
85
|
+
return result.value
|
|
86
|
+
} else {
|
|
87
|
+
console.dir(result.error)
|
|
88
|
+
throw new Error('Failed to decode output', {
|
|
89
|
+
cause: result.error,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
}
|
|
76
93
|
|
|
77
94
|
callers[serviceKey][procedureName] = this.createCaller(
|
|
78
|
-
|
|
95
|
+
service.contract.name,
|
|
79
96
|
procedureName,
|
|
80
97
|
{
|
|
81
|
-
timeout:
|
|
98
|
+
timeout: service.contract.timeout,
|
|
82
99
|
transformInput: (data: any) => {
|
|
83
|
-
if (
|
|
84
|
-
const compiled =
|
|
100
|
+
if (input instanceof NeverType) return undefined
|
|
101
|
+
const compiled = service.compiled.get(input)!
|
|
85
102
|
const result = compiled.encode(data)
|
|
86
103
|
if (result.success) {
|
|
87
104
|
return result.value
|
|
@@ -93,16 +110,14 @@ export class RuntimeClient<Services extends ClientServices> extends Client {
|
|
|
93
110
|
}
|
|
94
111
|
},
|
|
95
112
|
transformOutput: (data: any) => {
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
if (
|
|
114
|
+
service.contract.procedures[procedureName].type ===
|
|
115
|
+
'neemata:subscription'
|
|
116
|
+
) {
|
|
117
|
+
data.payload = decodeOutput(data.payload)
|
|
118
|
+
return data
|
|
101
119
|
} else {
|
|
102
|
-
|
|
103
|
-
throw new Error('Failed to decode output', {
|
|
104
|
-
cause: result.error,
|
|
105
|
-
})
|
|
120
|
+
return decodeOutput(data)
|
|
106
121
|
}
|
|
107
122
|
},
|
|
108
123
|
},
|
|
@@ -115,24 +130,35 @@ export class RuntimeClient<Services extends ClientServices> extends Client {
|
|
|
115
130
|
get call() {
|
|
116
131
|
return this.#callers
|
|
117
132
|
}
|
|
133
|
+
|
|
134
|
+
protected checkTransport(transport: ClientTransport): void {
|
|
135
|
+
for (const { contract } of Object.values(this.contracts)) {
|
|
136
|
+
if (!contract.transports[transport.type])
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Transport [${transport.type}] not supported for service [${contract.name}]`,
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
export const compileContract = <T extends TServiceContract>(
|
|
121
145
|
contract: T,
|
|
122
146
|
): CompiledContract<T> => {
|
|
123
|
-
const compiled = new Map<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
147
|
+
const compiled = new Map<BaseType, Compiled>()
|
|
148
|
+
|
|
149
|
+
for (const procedure of Object.values(contract.procedures)) {
|
|
150
|
+
const { input, output } = procedure
|
|
151
|
+
if (procedure.type === 'neemata:subscription') {
|
|
152
|
+
const { events } = procedure
|
|
127
153
|
for (const event of Object.values(events) as TEventContract[]) {
|
|
128
|
-
compiled.set(event, compile(event))
|
|
154
|
+
compiled.set(event.payload, compile(event.payload))
|
|
129
155
|
}
|
|
130
156
|
}
|
|
131
157
|
compiled.set(input, compile(input))
|
|
132
158
|
compiled.set(output, compile(output))
|
|
133
159
|
}
|
|
134
|
-
for (const
|
|
135
|
-
compiled.set(
|
|
160
|
+
for (const event of Object.values(contract.events)) {
|
|
161
|
+
compiled.set(event.payload, compile(event.payload))
|
|
136
162
|
}
|
|
137
163
|
|
|
138
164
|
return {
|
package/lib/client-static.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
TServiceContract,
|
|
4
|
-
TSubscriptionContract,
|
|
5
|
-
} from '@nmtjs/contract'
|
|
1
|
+
import type { TServiceContract, TSubscriptionContract } from '@nmtjs/contract'
|
|
2
|
+
import type { NeverType, t } from '@nmtjs/type'
|
|
6
3
|
import { Client, type ClientOptions } from './client.ts'
|
|
7
4
|
import type { Subscription } from './subscription.ts'
|
|
8
5
|
import type { ClientCallOptions, InputType, OutputType } from './types.ts'
|
|
@@ -12,25 +9,31 @@ type ClientServices = Record<string, TServiceContract>
|
|
|
12
9
|
type ClientCallers<Services extends ClientServices> = {
|
|
13
10
|
[K in keyof Services]: {
|
|
14
11
|
[P in keyof Services[K]['procedures']]: (
|
|
15
|
-
...args:
|
|
12
|
+
...args: Services[K]['procedures'][P]['input'] extends NeverType
|
|
16
13
|
? [options?: ClientCallOptions]
|
|
17
14
|
: [
|
|
18
|
-
data: InputType<
|
|
15
|
+
data: InputType<
|
|
16
|
+
t.infer.encoded<Services[K]['procedures'][P]['input']>
|
|
17
|
+
>,
|
|
19
18
|
options?: ClientCallOptions,
|
|
20
19
|
]
|
|
21
20
|
) => Promise<
|
|
22
21
|
Services[K]['procedures'][P] extends TSubscriptionContract
|
|
23
22
|
? {
|
|
24
|
-
payload:
|
|
25
|
-
Services[K]['procedures'][P]['output']
|
|
26
|
-
> extends never
|
|
23
|
+
payload: Services[K]['procedures'][P]['output'] extends NeverType
|
|
27
24
|
? undefined
|
|
28
|
-
:
|
|
29
|
-
subscription: Subscription<
|
|
25
|
+
: t.infer.encoded<Services[K]['procedures'][P]['output']>
|
|
26
|
+
subscription: Subscription<{
|
|
27
|
+
[KE in keyof Services[K]['procedures'][P]['events']]: [
|
|
28
|
+
t.infer.encoded<
|
|
29
|
+
Services[K]['procedures'][P]['events'][KE]['payload']
|
|
30
|
+
>,
|
|
31
|
+
]
|
|
32
|
+
}>
|
|
30
33
|
}
|
|
31
|
-
:
|
|
34
|
+
: Services[K]['procedures'][P]['output'] extends NeverType
|
|
32
35
|
? void
|
|
33
|
-
: OutputType<
|
|
36
|
+
: OutputType<t.infer.encoded<Services[K]['procedures'][P]['output']>>
|
|
34
37
|
>
|
|
35
38
|
}
|
|
36
39
|
}
|
package/lib/client.ts
CHANGED
|
@@ -39,6 +39,7 @@ export abstract class Client extends utils.EventEmitter {
|
|
|
39
39
|
format: this.format,
|
|
40
40
|
auth: this.auth,
|
|
41
41
|
})
|
|
42
|
+
this.checkTransport(this.transport)
|
|
42
43
|
return this as Omit<this, 'useTransport'>
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -60,6 +61,8 @@ export abstract class Client extends utils.EventEmitter {
|
|
|
60
61
|
await this.connect()
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
protected checkTransport(transport: ClientTransport) {}
|
|
65
|
+
|
|
63
66
|
protected createCaller(
|
|
64
67
|
service: string,
|
|
65
68
|
procedure: string,
|
package/lib/subscription.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { EventEmitter } from './utils.ts'
|
|
1
|
+
import { EventEmitter, type EventMap } from './utils.ts'
|
|
3
2
|
|
|
4
3
|
export class Subscription<
|
|
5
|
-
|
|
6
|
-
> extends EventEmitter<{
|
|
7
|
-
[K in keyof Contact['events']]: [Contact['events'][K]['static']['payload']]
|
|
8
|
-
}> {
|
|
4
|
+
Events extends EventMap = EventMap,
|
|
5
|
+
> extends EventEmitter<Events> {
|
|
9
6
|
constructor(
|
|
10
7
|
readonly key: string,
|
|
11
8
|
readonly unsubscribe: () => void,
|
package/lib/transport.ts
CHANGED
package/package.json
CHANGED
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@nmtjs/
|
|
23
|
-
"@nmtjs/
|
|
22
|
+
"@nmtjs/type": "0.1.1",
|
|
23
|
+
"@nmtjs/contract": "0.1.1",
|
|
24
|
+
"@nmtjs/common": "0.1.1"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@nmtjs/
|
|
27
|
-
"@nmtjs/common": "0.
|
|
27
|
+
"@nmtjs/type": "0.1.1",
|
|
28
|
+
"@nmtjs/common": "0.1.1",
|
|
29
|
+
"@nmtjs/contract": "0.1.1"
|
|
28
30
|
},
|
|
29
31
|
"files": [
|
|
30
32
|
"index.ts",
|
|
@@ -34,7 +36,7 @@
|
|
|
34
36
|
"LICENSE.md",
|
|
35
37
|
"README.md"
|
|
36
38
|
],
|
|
37
|
-
"version": "0.
|
|
39
|
+
"version": "0.1.1",
|
|
38
40
|
"scripts": {
|
|
39
41
|
"build": "neemata-build -p neutral ./index.ts './lib/**/*.ts'",
|
|
40
42
|
"type-check": "tsc --noEmit"
|