@nmtjs/client 0.5.3 → 0.6.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/common.js ADDED
@@ -0,0 +1,5 @@
1
+ import { ProtocolError } from '@nmtjs/protocol/client';
2
+ export * from "./types.js";
3
+ export class ClientError extends ProtocolError {
4
+ }
5
+ export { ProtocolBlob, ErrorCode, TransportType } from '@nmtjs/protocol/common';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../lib/common.ts"],"sourcesContent":["import { ProtocolError } from '@nmtjs/protocol/client'\n\nexport * from './types.ts'\n\nexport class ClientError extends ProtocolError {}\n\nexport {\n ProtocolBlob,\n ErrorCode,\n TransportType,\n type ProtocolBlobMetadata,\n} from '@nmtjs/protocol/common'\n"],"names":["ProtocolError","ClientError","ProtocolBlob","ErrorCode","TransportType"],"mappings":"AAAA,SAASA,aAAa,QAAQ,yBAAwB;AAEtD,cAAc,aAAY;AAE1B,OAAO,MAAMC,oBAAoBD;AAAe;AAEhD,SACEE,YAAY,EACZC,SAAS,EACTC,aAAa,QAER,yBAAwB"}
@@ -0,0 +1,92 @@
1
+ import { ProtocolBaseClient, ProtocolBaseTransformer } from '@nmtjs/protocol/client';
2
+ import { ErrorCode } from '@nmtjs/protocol/common';
3
+ import { NeverType } from '@nmtjs/type';
4
+ import { compile } from '@nmtjs/type/compiler';
5
+ import { ClientError } from "./common.js";
6
+ export class RuntimeContractTransformer extends ProtocolBaseTransformer {
7
+ #contract;
8
+ #types = new Set();
9
+ #compiled = new Map();
10
+ constructor(contract){
11
+ super();
12
+ this.#contract = contract;
13
+ for (const namespace of Object.values(contract.namespaces)){
14
+ for (const procedure of Object.values(namespace.procedures)){
15
+ const { input, output, stream } = procedure;
16
+ this.#registerType(input);
17
+ this.#registerType(output);
18
+ this.#registerType(stream);
19
+ }
20
+ for (const subscription of Object.values(namespace.subscriptions)){
21
+ const { input, output } = subscription;
22
+ this.#registerType(input);
23
+ this.#registerType(output);
24
+ for (const event of Object.values(subscription.events)){
25
+ this.#registerType(event.payload);
26
+ }
27
+ }
28
+ for (const event of Object.values(namespace.events)){
29
+ this.#registerType(event.payload);
30
+ }
31
+ }
32
+ this.#compile();
33
+ }
34
+ decodeEvent(namespace, event, payload) {
35
+ const type = this.#contract.namespaces[namespace].events[event].payload;
36
+ if (type instanceof NeverType) return undefined;
37
+ const compiled = this.#compiled.get(type);
38
+ return compiled.decode(payload);
39
+ }
40
+ decodeRPC(namespace, procedure, payload) {
41
+ const type = this.#contract.namespaces[namespace].procedures[procedure].output;
42
+ if (type instanceof NeverType) return undefined;
43
+ const compiled = this.#compiled.get(type);
44
+ return compiled.decode(payload);
45
+ }
46
+ decodeRPCChunk(namespace, procedure, payload) {
47
+ const type = this.#contract.namespaces[namespace].procedures[procedure].stream;
48
+ if (type instanceof NeverType) return undefined;
49
+ const compiled = this.#compiled.get(type);
50
+ return compiled.decode(payload);
51
+ }
52
+ encodeRPC(namespace, procedure, payload) {
53
+ const type = this.#contract.namespaces[namespace].procedures[procedure].input;
54
+ if (type instanceof NeverType) return undefined;
55
+ const compiled = this.#compiled.get(type);
56
+ if (!compiled.check(payload)) {
57
+ const errors = compiled.errors(payload);
58
+ throw new ClientError(ErrorCode.ValidationError, 'Invalid RPC payload', errors);
59
+ }
60
+ return compiled.encode(payload);
61
+ }
62
+ #registerType(type) {
63
+ this.#types.add(type);
64
+ }
65
+ #compile() {
66
+ for (const type of this.#types){
67
+ this.#compiled.set(type, compile(type));
68
+ }
69
+ }
70
+ }
71
+ export class RuntimeClient extends ProtocolBaseClient {
72
+ _;
73
+ #callers = {};
74
+ constructor(contract, transport, format){
75
+ super(transport, format, new RuntimeContractTransformer(contract));
76
+ const callers = {};
77
+ for (const [namespaceKey, namespace] of Object.entries(contract.namespaces)){
78
+ namespace.procedures;
79
+ callers[namespaceKey] = {};
80
+ for (const [procedureKey, procedure] of Object.entries(namespace.procedures)){
81
+ callers[namespaceKey][procedureKey] = (payload, options)=>this._call(namespace.name, procedure.name, payload, {
82
+ timeout: namespace.timeout,
83
+ ...options
84
+ });
85
+ }
86
+ }
87
+ this.#callers = callers;
88
+ }
89
+ get call() {
90
+ return this.#callers;
91
+ }
92
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../lib/runtime.ts"],"sourcesContent":["import type { TAnyAPIContract } from '@nmtjs/contract'\nimport {\n ProtocolBaseClient,\n ProtocolBaseTransformer,\n type ProtocolTransport,\n} from '@nmtjs/protocol/client'\nimport type { BaseClientFormat } from '@nmtjs/protocol/client'\nimport { ErrorCode } from '@nmtjs/protocol/common'\nimport { type BaseTypeAny, NeverType } from '@nmtjs/type'\nimport { type Compiled, compile } from '@nmtjs/type/compiler'\nimport { ClientError } from './common.ts'\nimport type {\n ClientCallers,\n ResolveAPIContract,\n ResolveClientEvents,\n RuntimeContractTypeProvider,\n} from './types.ts'\n\nexport class RuntimeContractTransformer extends ProtocolBaseTransformer {\n #contract: TAnyAPIContract\n #types = new Set<BaseTypeAny>()\n #compiled = new Map<BaseTypeAny, Compiled>()\n\n constructor(contract: TAnyAPIContract) {\n super()\n\n this.#contract = contract\n\n for (const namespace of Object.values(contract.namespaces)) {\n for (const procedure of Object.values(namespace.procedures)) {\n const { input, output, stream } = procedure\n this.#registerType(input)\n this.#registerType(output)\n this.#registerType(stream)\n }\n\n for (const subscription of Object.values(namespace.subscriptions)) {\n const { input, output } = subscription\n this.#registerType(input)\n this.#registerType(output)\n\n for (const event of Object.values(subscription.events)) {\n this.#registerType(event.payload)\n }\n }\n\n for (const event of Object.values(namespace.events)) {\n this.#registerType(event.payload)\n }\n }\n\n this.#compile()\n }\n\n decodeEvent(namespace: string, event: string, payload: any) {\n const type = this.#contract.namespaces[namespace].events[event].payload\n if (type instanceof NeverType) return undefined\n const compiled = this.#compiled.get(type)!\n return compiled.decode(payload)\n }\n\n decodeRPC(namespace: string, procedure: string, payload: any) {\n const type =\n this.#contract.namespaces[namespace].procedures[procedure].output\n if (type instanceof NeverType) return undefined\n const compiled = this.#compiled.get(type)!\n return compiled.decode(payload)\n }\n\n decodeRPCChunk(namespace: string, procedure: string, payload: any) {\n const type =\n this.#contract.namespaces[namespace].procedures[procedure].stream\n if (type instanceof NeverType) return undefined\n\n const compiled = this.#compiled.get(type)!\n return compiled.decode(payload)\n }\n\n encodeRPC(namespace: string, procedure: string, payload: any) {\n const type =\n this.#contract.namespaces[namespace].procedures[procedure].input\n if (type instanceof NeverType) return undefined\n\n const compiled = this.#compiled.get(type)!\n if (!compiled.check(payload)) {\n const errors = compiled.errors(payload)\n throw new ClientError(\n ErrorCode.ValidationError,\n 'Invalid RPC payload',\n errors,\n )\n }\n\n return compiled.encode(payload)\n }\n\n #registerType(type: BaseTypeAny) {\n this.#types.add(type)\n }\n\n #compile() {\n for (const type of this.#types) {\n this.#compiled.set(type, compile(type))\n }\n }\n}\n\nexport class RuntimeClient<\n APIContract extends TAnyAPIContract,\n ResolvedAPIContract extends ResolveAPIContract<\n APIContract,\n RuntimeContractTypeProvider\n > = ResolveAPIContract<APIContract, RuntimeContractTypeProvider>,\n> extends ProtocolBaseClient<ResolveClientEvents<ResolvedAPIContract>> {\n _!: ResolvedAPIContract\n #callers = {} as ClientCallers<ResolvedAPIContract>\n\n constructor(\n contract: APIContract,\n transport: ProtocolTransport,\n format: BaseClientFormat,\n ) {\n super(transport, format, new RuntimeContractTransformer(contract))\n\n const callers = {} as any\n\n for (const [namespaceKey, namespace] of Object.entries(\n contract.namespaces,\n )) {\n namespace.procedures\n\n callers[namespaceKey] = {} as any\n\n for (const [procedureKey, procedure] of Object.entries(\n namespace.procedures,\n )) {\n callers[namespaceKey][procedureKey] = (payload, options) =>\n this._call(namespace.name, procedure.name, payload, {\n timeout: namespace.timeout,\n ...options,\n })\n }\n }\n this.#callers = callers\n }\n\n get call() {\n return this.#callers\n }\n}\n"],"names":["ProtocolBaseClient","ProtocolBaseTransformer","ErrorCode","NeverType","compile","ClientError","RuntimeContractTransformer","Set","Map","constructor","contract","namespace","Object","values","namespaces","procedure","procedures","input","output","stream","subscription","subscriptions","event","events","payload","decodeEvent","type","undefined","compiled","get","decode","decodeRPC","decodeRPCChunk","encodeRPC","check","errors","ValidationError","encode","add","set","RuntimeClient","_","transport","format","callers","namespaceKey","entries","procedureKey","options","_call","name","timeout","call"],"mappings":"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"}
package/dist/static.js ADDED
@@ -0,0 +1,22 @@
1
+ import { ProtocolBaseClient } from '@nmtjs/protocol/client';
2
+ export class StaticClient extends ProtocolBaseClient {
3
+ _;
4
+ #callers;
5
+ constructor(transport, format){
6
+ super(transport, format);
7
+ this.#callers = new Proxy(Object(), {
8
+ get: (target, namespaceProp, receiver)=>{
9
+ if (namespaceProp === 'then') return target;
10
+ return new Proxy(Object(), {
11
+ get: (target, procedureProp, receiver)=>{
12
+ if (procedureProp === 'then') return target;
13
+ return (payload, options)=>this._call(namespaceProp, procedureProp, payload);
14
+ }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ get call() {
20
+ return this.#callers;
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../lib/static.ts"],"sourcesContent":["import type { TAnyAPIContract } from '@nmtjs/contract'\nimport {\n type BaseClientFormat,\n ProtocolBaseClient,\n type ProtocolTransport,\n} from '@nmtjs/protocol/client'\n\nimport type {\n ClientCallers,\n ResolveAPIContract,\n ResolveClientEvents,\n StaticContractTypeProvider,\n} from './types.ts'\n\nexport class StaticClient<\n APIContract extends TAnyAPIContract,\n ResolvedAPIContract extends ResolveAPIContract<\n APIContract,\n StaticContractTypeProvider\n > = ResolveAPIContract<APIContract, StaticContractTypeProvider>,\n> extends ProtocolBaseClient<ResolveClientEvents<ResolvedAPIContract>> {\n _!: ResolvedAPIContract\n\n #callers: ClientCallers<ResolvedAPIContract>\n\n constructor(transport: ProtocolTransport, format: BaseClientFormat) {\n super(transport, format)\n\n this.#callers = new Proxy(Object(), {\n get: (target, namespaceProp, receiver) => {\n // `await client.call.namespaceName` or `await client.call.namespaceName.procedureName`\n // without explicitly calling a function implicitly calls .then() on target\n // FIXME: this basically makes \"then\" a reserved word\n if (namespaceProp === 'then') return target\n return new Proxy(Object(), {\n get: (target, procedureProp, receiver) => {\n // `await client.call.namespaceName` or `await client.call.namespaceName.procedureName`\n // without explicitly calling a function implicitly calls .then() on target\n // FIXME: this basically makes \"then\" a reserved word\n if (procedureProp === 'then') return target\n return (payload, options) =>\n this._call(\n namespaceProp as string,\n procedureProp as string,\n payload,\n )\n },\n })\n },\n })\n }\n\n get call() {\n return this.#callers\n }\n}\n"],"names":["ProtocolBaseClient","StaticClient","_","constructor","transport","format","Proxy","Object","get","target","namespaceProp","receiver","procedureProp","payload","options","_call","call"],"mappings":"AACA,SAEEA,kBAAkB,QAEb,yBAAwB;AAS/B,OAAO,MAAMC,qBAMHD;IACRE,EAAuB;IAEvB,CAAA,OAAQ,CAAoC;IAE5CC,YAAYC,SAA4B,EAAEC,MAAwB,CAAE;QAClE,KAAK,CAACD,WAAWC;QAEjB,IAAI,CAAC,CAAA,OAAQ,GAAG,IAAIC,MAAMC,UAAU;YAClCC,KAAK,CAACC,QAAQC,eAAeC;gBAI3B,IAAID,kBAAkB,QAAQ,OAAOD;gBACrC,OAAO,IAAIH,MAAMC,UAAU;oBACzBC,KAAK,CAACC,QAAQG,eAAeD;wBAI3B,IAAIC,kBAAkB,QAAQ,OAAOH;wBACrC,OAAO,CAACI,SAASC,UACf,IAAI,CAACC,KAAK,CACRL,eACAE,eACAC;oBAEN;gBACF;YACF;QACF;IACF;IAEA,IAAIG,OAAO;QACT,OAAO,IAAI,CAAC,CAAA,OAAQ;IACtB;AACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../lib/types.ts"],"sourcesContent":["import type { CallTypeProvider, TypeProvider } from '@nmtjs/common'\nimport type { TAnyAPIContract } from '@nmtjs/contract'\nimport type { ProtocolServerStream } from '@nmtjs/protocol/client'\nimport type { InputType, OutputType } from '@nmtjs/protocol/common'\nimport type { BaseTypeAny, NeverType, t } from '@nmtjs/type'\n\nexport interface StaticContractTypeProvider extends TypeProvider {\n output: this['input'] extends BaseTypeAny\n ? t.infer.input.decoded<this['input']>\n : never\n}\n\nexport interface RuntimeContractTypeProvider extends TypeProvider {\n output: this['input'] extends BaseTypeAny\n ? t.infer.decoded<this['input']>\n : never\n}\n\nexport type ResolveAPIContract<\n C extends TAnyAPIContract = TAnyAPIContract,\n T extends TypeProvider = TypeProvider,\n> = {\n [N in keyof C['namespaces'] as C['namespaces'][N]['name']]: {\n procedures: {\n [P in keyof C['namespaces'][N]['procedures'] as C['namespaces'][N]['procedures'][P]['name']]: {\n contract: C['namespaces'][N]['procedures'][P]\n input: InputType<\n CallTypeProvider<T, C['namespaces'][N]['procedures'][P]['input']>\n >\n output: C['namespaces'][N]['procedures'][P]['stream'] extends NeverType\n ? OutputType<\n CallTypeProvider<T, C['namespaces'][N]['procedures'][P]['output']>\n >\n : [\n result: OutputType<\n CallTypeProvider<\n T,\n C['namespaces'][N]['procedures'][P]['output']\n >\n >,\n stream: ProtocolServerStream<\n CallTypeProvider<\n T,\n C['namespaces'][N]['procedures'][P]['stream']\n >\n >,\n ]\n }\n }\n events: {\n [KE in keyof C['namespaces'][N]['events'] as C['namespaces'][N]['events'][KE]['name']]: {\n payload: OutputType<\n CallTypeProvider<T, C['namespaces'][N]['events'][KE]['payload']>\n >\n }\n }\n }\n}\n\nexport type ResolveClientEvents<\n C extends ResolveAPIContract = ResolveAPIContract,\n> = {\n [N in keyof C]: {\n [KE in keyof C[N]['events']]: C[N]['events'][KE]['payload']\n }\n}\n\nexport type ClientCallOptions = {\n signal?: AbortSignal\n}\n\nexport type ClientCallers<Resolved extends ResolveAPIContract> = {\n [N in keyof Resolved]: {\n [P in keyof Resolved[N]['procedures']]: (\n ...args: Resolved[N]['procedures'][P]['input'] extends NeverType\n ? [options?: ClientCallOptions]\n : t.infer.input.encoded<\n Resolved[N]['procedures'][P]['contract']['input']\n > extends undefined\n ? [\n data?: Resolved[N]['procedures'][P]['input'],\n options?: ClientCallOptions,\n ]\n : [\n data: Resolved[N]['procedures'][P]['input'],\n options?: ClientCallOptions,\n ]\n ) => Promise<Resolved[N]['procedures'][P]['output']>\n }\n}\n"],"names":[],"mappings":"AAuEA,WAkBC"}
package/lib/common.ts CHANGED
@@ -1,9 +1,12 @@
1
- export class ClientError extends Error {
2
- constructor(
3
- public code: string,
4
- message?: string,
5
- public data?: any,
6
- ) {
7
- super(message)
8
- }
9
- }
1
+ import { ProtocolError } from '@nmtjs/protocol/client'
2
+
3
+ export * from './types.ts'
4
+
5
+ export class ClientError extends ProtocolError {}
6
+
7
+ export {
8
+ ProtocolBlob,
9
+ ErrorCode,
10
+ TransportType,
11
+ type ProtocolBlobMetadata,
12
+ } from '@nmtjs/protocol/common'
package/lib/runtime.ts ADDED
@@ -0,0 +1,150 @@
1
+ import type { TAnyAPIContract } from '@nmtjs/contract'
2
+ import {
3
+ ProtocolBaseClient,
4
+ ProtocolBaseTransformer,
5
+ type ProtocolTransport,
6
+ } from '@nmtjs/protocol/client'
7
+ import type { BaseClientFormat } from '@nmtjs/protocol/client'
8
+ import { ErrorCode } from '@nmtjs/protocol/common'
9
+ import { type BaseTypeAny, NeverType } from '@nmtjs/type'
10
+ import { type Compiled, compile } from '@nmtjs/type/compiler'
11
+ import { ClientError } from './common.ts'
12
+ import type {
13
+ ClientCallers,
14
+ ResolveAPIContract,
15
+ ResolveClientEvents,
16
+ RuntimeContractTypeProvider,
17
+ } from './types.ts'
18
+
19
+ export class RuntimeContractTransformer extends ProtocolBaseTransformer {
20
+ #contract: TAnyAPIContract
21
+ #types = new Set<BaseTypeAny>()
22
+ #compiled = new Map<BaseTypeAny, Compiled>()
23
+
24
+ constructor(contract: TAnyAPIContract) {
25
+ super()
26
+
27
+ this.#contract = contract
28
+
29
+ for (const namespace of Object.values(contract.namespaces)) {
30
+ for (const procedure of Object.values(namespace.procedures)) {
31
+ const { input, output, stream } = procedure
32
+ this.#registerType(input)
33
+ this.#registerType(output)
34
+ this.#registerType(stream)
35
+ }
36
+
37
+ for (const subscription of Object.values(namespace.subscriptions)) {
38
+ const { input, output } = subscription
39
+ this.#registerType(input)
40
+ this.#registerType(output)
41
+
42
+ for (const event of Object.values(subscription.events)) {
43
+ this.#registerType(event.payload)
44
+ }
45
+ }
46
+
47
+ for (const event of Object.values(namespace.events)) {
48
+ this.#registerType(event.payload)
49
+ }
50
+ }
51
+
52
+ this.#compile()
53
+ }
54
+
55
+ decodeEvent(namespace: string, event: string, payload: any) {
56
+ const type = this.#contract.namespaces[namespace].events[event].payload
57
+ if (type instanceof NeverType) return undefined
58
+ const compiled = this.#compiled.get(type)!
59
+ return compiled.decode(payload)
60
+ }
61
+
62
+ decodeRPC(namespace: string, procedure: string, payload: any) {
63
+ const type =
64
+ this.#contract.namespaces[namespace].procedures[procedure].output
65
+ if (type instanceof NeverType) return undefined
66
+ const compiled = this.#compiled.get(type)!
67
+ return compiled.decode(payload)
68
+ }
69
+
70
+ decodeRPCChunk(namespace: string, procedure: string, payload: any) {
71
+ const type =
72
+ this.#contract.namespaces[namespace].procedures[procedure].stream
73
+ if (type instanceof NeverType) return undefined
74
+
75
+ const compiled = this.#compiled.get(type)!
76
+ return compiled.decode(payload)
77
+ }
78
+
79
+ encodeRPC(namespace: string, procedure: string, payload: any) {
80
+ const type =
81
+ this.#contract.namespaces[namespace].procedures[procedure].input
82
+ if (type instanceof NeverType) return undefined
83
+
84
+ const compiled = this.#compiled.get(type)!
85
+ if (!compiled.check(payload)) {
86
+ const errors = compiled.errors(payload)
87
+ throw new ClientError(
88
+ ErrorCode.ValidationError,
89
+ 'Invalid RPC payload',
90
+ errors,
91
+ )
92
+ }
93
+
94
+ return compiled.encode(payload)
95
+ }
96
+
97
+ #registerType(type: BaseTypeAny) {
98
+ this.#types.add(type)
99
+ }
100
+
101
+ #compile() {
102
+ for (const type of this.#types) {
103
+ this.#compiled.set(type, compile(type))
104
+ }
105
+ }
106
+ }
107
+
108
+ export class RuntimeClient<
109
+ APIContract extends TAnyAPIContract,
110
+ ResolvedAPIContract extends ResolveAPIContract<
111
+ APIContract,
112
+ RuntimeContractTypeProvider
113
+ > = ResolveAPIContract<APIContract, RuntimeContractTypeProvider>,
114
+ > extends ProtocolBaseClient<ResolveClientEvents<ResolvedAPIContract>> {
115
+ _!: ResolvedAPIContract
116
+ #callers = {} as ClientCallers<ResolvedAPIContract>
117
+
118
+ constructor(
119
+ contract: APIContract,
120
+ transport: ProtocolTransport,
121
+ format: BaseClientFormat,
122
+ ) {
123
+ super(transport, format, new RuntimeContractTransformer(contract))
124
+
125
+ const callers = {} as any
126
+
127
+ for (const [namespaceKey, namespace] of Object.entries(
128
+ contract.namespaces,
129
+ )) {
130
+ namespace.procedures
131
+
132
+ callers[namespaceKey] = {} as any
133
+
134
+ for (const [procedureKey, procedure] of Object.entries(
135
+ namespace.procedures,
136
+ )) {
137
+ callers[namespaceKey][procedureKey] = (payload, options) =>
138
+ this._call(namespace.name, procedure.name, payload, {
139
+ timeout: namespace.timeout,
140
+ ...options,
141
+ })
142
+ }
143
+ }
144
+ this.#callers = callers
145
+ }
146
+
147
+ get call() {
148
+ return this.#callers
149
+ }
150
+ }
package/lib/static.ts ADDED
@@ -0,0 +1,56 @@
1
+ import type { TAnyAPIContract } from '@nmtjs/contract'
2
+ import {
3
+ type BaseClientFormat,
4
+ ProtocolBaseClient,
5
+ type ProtocolTransport,
6
+ } from '@nmtjs/protocol/client'
7
+
8
+ import type {
9
+ ClientCallers,
10
+ ResolveAPIContract,
11
+ ResolveClientEvents,
12
+ StaticContractTypeProvider,
13
+ } from './types.ts'
14
+
15
+ export class StaticClient<
16
+ APIContract extends TAnyAPIContract,
17
+ ResolvedAPIContract extends ResolveAPIContract<
18
+ APIContract,
19
+ StaticContractTypeProvider
20
+ > = ResolveAPIContract<APIContract, StaticContractTypeProvider>,
21
+ > extends ProtocolBaseClient<ResolveClientEvents<ResolvedAPIContract>> {
22
+ _!: ResolvedAPIContract
23
+
24
+ #callers: ClientCallers<ResolvedAPIContract>
25
+
26
+ constructor(transport: ProtocolTransport, format: BaseClientFormat) {
27
+ super(transport, format)
28
+
29
+ this.#callers = new Proxy(Object(), {
30
+ get: (target, namespaceProp, receiver) => {
31
+ // `await client.call.namespaceName` or `await client.call.namespaceName.procedureName`
32
+ // without explicitly calling a function implicitly calls .then() on target
33
+ // FIXME: this basically makes "then" a reserved word
34
+ if (namespaceProp === 'then') return target
35
+ return new Proxy(Object(), {
36
+ get: (target, procedureProp, receiver) => {
37
+ // `await client.call.namespaceName` or `await client.call.namespaceName.procedureName`
38
+ // without explicitly calling a function implicitly calls .then() on target
39
+ // FIXME: this basically makes "then" a reserved word
40
+ if (procedureProp === 'then') return target
41
+ return (payload, options) =>
42
+ this._call(
43
+ namespaceProp as string,
44
+ procedureProp as string,
45
+ payload,
46
+ )
47
+ },
48
+ })
49
+ },
50
+ })
51
+ }
52
+
53
+ get call() {
54
+ return this.#callers
55
+ }
56
+ }
package/lib/types.ts CHANGED
@@ -1,22 +1,90 @@
1
- import type { ApiBlob, ApiBlobInterface } from '@nmtjs/common'
2
- import type { ClientDownStreamBlob } from './stream.ts'
1
+ import type { CallTypeProvider, TypeProvider } from '@nmtjs/common'
2
+ import type { TAnyAPIContract } from '@nmtjs/contract'
3
+ import type { ProtocolServerStream } from '@nmtjs/protocol/client'
4
+ import type { InputType, OutputType } from '@nmtjs/protocol/common'
5
+ import type { BaseTypeAny, NeverType, t } from '@nmtjs/type'
6
+
7
+ export interface StaticContractTypeProvider extends TypeProvider {
8
+ output: this['input'] extends BaseTypeAny
9
+ ? t.infer.input.decoded<this['input']>
10
+ : never
11
+ }
12
+
13
+ export interface RuntimeContractTypeProvider extends TypeProvider {
14
+ output: this['input'] extends BaseTypeAny
15
+ ? t.infer.decoded<this['input']>
16
+ : never
17
+ }
18
+
19
+ export type ResolveAPIContract<
20
+ C extends TAnyAPIContract = TAnyAPIContract,
21
+ T extends TypeProvider = TypeProvider,
22
+ > = {
23
+ [N in keyof C['namespaces'] as C['namespaces'][N]['name']]: {
24
+ procedures: {
25
+ [P in keyof C['namespaces'][N]['procedures'] as C['namespaces'][N]['procedures'][P]['name']]: {
26
+ contract: C['namespaces'][N]['procedures'][P]
27
+ input: InputType<
28
+ CallTypeProvider<T, C['namespaces'][N]['procedures'][P]['input']>
29
+ >
30
+ output: C['namespaces'][N]['procedures'][P]['stream'] extends NeverType
31
+ ? OutputType<
32
+ CallTypeProvider<T, C['namespaces'][N]['procedures'][P]['output']>
33
+ >
34
+ : [
35
+ result: OutputType<
36
+ CallTypeProvider<
37
+ T,
38
+ C['namespaces'][N]['procedures'][P]['output']
39
+ >
40
+ >,
41
+ stream: ProtocolServerStream<
42
+ CallTypeProvider<
43
+ T,
44
+ C['namespaces'][N]['procedures'][P]['stream']
45
+ >
46
+ >,
47
+ ]
48
+ }
49
+ }
50
+ events: {
51
+ [KE in keyof C['namespaces'][N]['events'] as C['namespaces'][N]['events'][KE]['name']]: {
52
+ payload: OutputType<
53
+ CallTypeProvider<T, C['namespaces'][N]['events'][KE]['payload']>
54
+ >
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ export type ResolveClientEvents<
61
+ C extends ResolveAPIContract = ResolveAPIContract,
62
+ > = {
63
+ [N in keyof C]: {
64
+ [KE in keyof C[N]['events']]: C[N]['events'][KE]['payload']
65
+ }
66
+ }
3
67
 
4
68
  export type ClientCallOptions = {
5
69
  signal?: AbortSignal
6
70
  }
7
71
 
8
- export type InputType<T> = T extends any[]
9
- ? InputType<T[number]>[]
10
- : T extends ApiBlobInterface
11
- ? ApiBlob
12
- : T extends object
13
- ? { [K in keyof T]: InputType<T[K]> }
14
- : T
15
-
16
- export type OutputType<T> = T extends any[]
17
- ? OutputType<T[number]>[]
18
- : T extends ApiBlobInterface
19
- ? ClientDownStreamBlob
20
- : T extends object
21
- ? { [K in keyof T]: OutputType<T[K]> }
22
- : T
72
+ export type ClientCallers<Resolved extends ResolveAPIContract> = {
73
+ [N in keyof Resolved]: {
74
+ [P in keyof Resolved[N]['procedures']]: (
75
+ ...args: Resolved[N]['procedures'][P]['input'] extends NeverType
76
+ ? [options?: ClientCallOptions]
77
+ : t.infer.input.encoded<
78
+ Resolved[N]['procedures'][P]['contract']['input']
79
+ > extends undefined
80
+ ? [
81
+ data?: Resolved[N]['procedures'][P]['input'],
82
+ options?: ClientCallOptions,
83
+ ]
84
+ : [
85
+ data: Resolved[N]['procedures'][P]['input'],
86
+ options?: ClientCallOptions,
87
+ ]
88
+ ) => Promise<Resolved[N]['procedures'][P]['output']>
89
+ }
90
+ }
package/package.json CHANGED
@@ -3,25 +3,26 @@
3
3
  "type": "module",
4
4
  "exports": {
5
5
  ".": {
6
- "bun": "./index.ts",
7
- "default": "./dist/index.js",
8
- "types": "./index.ts"
6
+ "bun": "./lib/common.ts",
7
+ "default": "./dist/common.js",
8
+ "types": "./lib/common.ts"
9
9
  },
10
10
  "./runtime": {
11
- "bun": "./lib/client-runtime.ts",
12
- "default": "./dist/lib/client-runtime.js",
13
- "types": "./lib/client-runtime.ts"
11
+ "bun": "./lib/runtime.ts",
12
+ "default": "./dist/runtime.js",
13
+ "types": "./lib/runtime.ts"
14
14
  },
15
15
  "./static": {
16
- "bun": "./lib/client-static.ts",
17
- "default": "./dist/lib/client-static.js",
18
- "types": "./lib/client-static.ts"
16
+ "bun": "./lib/static.ts",
17
+ "default": "./dist/static.js",
18
+ "types": "./lib/static.ts"
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@nmtjs/type": "0.5.3",
23
- "@nmtjs/common": "0.5.3",
24
- "@nmtjs/contract": "0.5.3"
22
+ "@nmtjs/contract": "0.6.0",
23
+ "@nmtjs/common": "0.6.0",
24
+ "@nmtjs/type": "0.6.0",
25
+ "@nmtjs/protocol": "0.6.0"
25
26
  },
26
27
  "files": [
27
28
  "index.ts",
@@ -31,9 +32,9 @@
31
32
  "LICENSE.md",
32
33
  "README.md"
33
34
  ],
34
- "version": "0.5.3",
35
+ "version": "0.6.0",
35
36
  "scripts": {
36
- "build": "neemata-build -p neutral ./index.ts './lib/**/*.ts'",
37
+ "build": "neemata-build -p neutral --root=./lib './**/*.ts'",
37
38
  "type-check": "tsc --noEmit"
38
39
  }
39
40
  }
package/dist/index.js DELETED
@@ -1,6 +0,0 @@
1
- export * from "./lib/client.js";
2
- export * from "./lib/common.js";
3
- export * from "./lib/stream.js";
4
- export * from "./lib/subscription.js";
5
- export * from "./lib/transport.js";
6
- export * from "./lib/utils.js";
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../index.ts"],"sourcesContent":["export * from './lib/client.ts'\nexport * from './lib/common.ts'\nexport * from './lib/stream.ts'\nexport * from './lib/subscription.ts'\nexport * from './lib/transport.ts'\nexport * from './lib/utils.ts'\n"],"names":[],"mappings":"AAAA,cAAc,kBAAiB;AAC/B,cAAc,kBAAiB;AAC/B,cAAc,kBAAiB;AAC/B,cAAc,wBAAuB;AACrC,cAAc,qBAAoB;AAClC,cAAc,iBAAgB"}
@@ -1,87 +0,0 @@
1
- import { NeverType } from '@nmtjs/type';
2
- import { compile } from '@nmtjs/type/compiler';
3
- import { Client } from "./client.js";
4
- export class RuntimeClient extends Client {
5
- contracts;
6
- $types;
7
- #callers;
8
- constructor(contracts, options){
9
- super(options, Object.values(contracts).map((s)=>s.contract.name));
10
- this.contracts = contracts;
11
- const callers = {};
12
- for (const [serviceKey, service] of Object.entries(contracts)){
13
- service.contract.procedures;
14
- callers[serviceKey] = {};
15
- for(const procedureName in service.contract.procedures){
16
- const { input, output } = service.contract.procedures[procedureName];
17
- function decodeOutput(data) {
18
- if (output instanceof NeverType) return undefined;
19
- const compiled = service.compiled.get(output);
20
- const result = compiled.decodeSafe(data);
21
- if (result.success) {
22
- return result.value;
23
- } else {
24
- console.dir(result.error);
25
- throw new Error('Failed to decode output', {
26
- cause: result.error
27
- });
28
- }
29
- }
30
- callers[serviceKey][procedureName] = this.createCaller(service.contract.name, procedureName, {
31
- timeout: service.contract.timeout,
32
- transformInput: (data)=>{
33
- if (input instanceof NeverType) return undefined;
34
- const compiled = service.compiled.get(input);
35
- const result = compiled.encodeSafe(data);
36
- if (result.success) {
37
- return result.value;
38
- } else {
39
- console.dir(result.error);
40
- throw new Error('Failed to encode input', {
41
- cause: result.error
42
- });
43
- }
44
- },
45
- transformOutput: (data)=>{
46
- if (service.contract.procedures[procedureName].type === 'neemata:subscription') {
47
- data.payload = decodeOutput(data.payload);
48
- return data;
49
- } else {
50
- return decodeOutput(data);
51
- }
52
- }
53
- });
54
- }
55
- }
56
- this.#callers = callers;
57
- }
58
- get call() {
59
- return this.#callers;
60
- }
61
- checkTransport(transport) {
62
- for (const { contract } of Object.values(this.contracts)){
63
- if (!contract.transports[transport.type]) throw new Error(`Transport [${transport.type}] not supported for service [${contract.name}]`);
64
- }
65
- }
66
- }
67
- export const compileContract = (contract)=>{
68
- const compiled = new Map();
69
- for (const procedure of Object.values(contract.procedures)){
70
- const { input, output } = procedure;
71
- if (procedure.type === 'neemata:subscription') {
72
- const { events } = procedure;
73
- for (const event of Object.values(events)){
74
- compiled.set(event.payload, compile(event.payload));
75
- }
76
- }
77
- compiled.set(input, compile(input));
78
- compiled.set(output, compile(output));
79
- }
80
- for (const event of Object.values(contract.events)){
81
- compiled.set(event.payload, compile(event.payload));
82
- }
83
- return {
84
- compiled,
85
- contract
86
- };
87
- };