@nmtjs/client 0.15.0-beta.2 → 0.15.0-beta.20

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/package.json CHANGED
@@ -7,27 +7,28 @@
7
7
  "./static": "./dist/clients/static.js"
8
8
  },
9
9
  "peerDependencies": {
10
- "@nmtjs/type": "0.15.0-beta.2",
11
- "@nmtjs/contract": "0.15.0-beta.2",
12
- "@nmtjs/protocol": "0.15.0-beta.2",
13
- "@nmtjs/common": "0.15.0-beta.2"
10
+ "@nmtjs/type": "0.15.0-beta.20",
11
+ "@nmtjs/contract": "0.15.0-beta.20",
12
+ "@nmtjs/common": "0.15.0-beta.20",
13
+ "@nmtjs/protocol": "0.15.0-beta.20"
14
14
  },
15
15
  "devDependencies": {
16
- "@nmtjs/_tests": "0.15.0-beta.2",
17
- "@nmtjs/contract": "0.15.0-beta.2",
18
- "@nmtjs/common": "0.15.0-beta.2",
19
- "@nmtjs/type": "0.15.0-beta.2",
20
- "@nmtjs/protocol": "0.15.0-beta.2"
16
+ "@nmtjs/_tests": "0.15.0-beta.20",
17
+ "@nmtjs/type": "0.15.0-beta.20",
18
+ "@nmtjs/protocol": "0.15.0-beta.20",
19
+ "@nmtjs/common": "0.15.0-beta.20",
20
+ "@nmtjs/contract": "0.15.0-beta.20"
21
21
  },
22
22
  "files": [
23
23
  "dist",
24
+ "src",
24
25
  "LICENSE.md",
25
26
  "README.md"
26
27
  ],
27
- "version": "0.15.0-beta.2",
28
+ "version": "0.15.0-beta.20",
28
29
  "scripts": {
29
30
  "clean-build": "rm -rf ./dist",
30
- "build": "tsc",
31
+ "build": "tsc --declaration --sourcemap",
31
32
  "dev": "tsc --watch",
32
33
  "type-check": "tsc --noEmit"
33
34
  }
@@ -0,0 +1,133 @@
1
+ import type {
2
+ TAnyProcedureContract,
3
+ TAnyRouterContract,
4
+ TRouteContract,
5
+ } from '@nmtjs/contract'
6
+ import { IsProcedureContract, IsRouterContract } from '@nmtjs/contract'
7
+
8
+ import type { BaseClientOptions } from '../core.ts'
9
+ import type { ClientTransportFactory } from '../transport.ts'
10
+ import type {
11
+ ClientCallers,
12
+ ClientCallOptions,
13
+ RuntimeInputContractTypeProvider,
14
+ RuntimeOutputContractTypeProvider,
15
+ } from '../types.ts'
16
+ import { BaseClient } from '../core.ts'
17
+
18
+ export class RuntimeContractTransformer {
19
+ #procedures = new Map<string, TAnyProcedureContract>()
20
+
21
+ constructor(router: TAnyRouterContract) {
22
+ const registerProcedures = (r: TRouteContract, path: string[] = []) => {
23
+ if (IsRouterContract(r)) {
24
+ for (const [key, route] of Object.entries(r.routes)) {
25
+ registerProcedures(route, [...path, key])
26
+ }
27
+ } else if (IsProcedureContract(r)) {
28
+ const fullName = [...path].join('/')
29
+ this.#procedures.set(fullName, r)
30
+ }
31
+ }
32
+ registerProcedures(router)
33
+ }
34
+
35
+ encode(_procedure: string, payload: any) {
36
+ const procedure = this.#procedures.get(_procedure)
37
+ if (!procedure) throw new Error(`Procedure not found: ${_procedure}`)
38
+ return procedure.input.encode(payload)
39
+ }
40
+
41
+ decode(_procedure: string, payload: any) {
42
+ const procedure = this.#procedures.get(_procedure)
43
+ if (!procedure) throw new Error(`Procedure not found: ${_procedure}`)
44
+ return procedure.output.decode(payload)
45
+ }
46
+ }
47
+
48
+ export class RuntimeClient<
49
+ Transport extends ClientTransportFactory<any, any> = ClientTransportFactory<
50
+ any,
51
+ any
52
+ >,
53
+ RouterContract extends TAnyRouterContract = TAnyRouterContract,
54
+ SafeCall extends boolean = false,
55
+ > extends BaseClient<
56
+ Transport,
57
+ RouterContract,
58
+ SafeCall,
59
+ RuntimeInputContractTypeProvider,
60
+ RuntimeOutputContractTypeProvider
61
+ > {
62
+ protected readonly transformer: RuntimeContractTransformer
63
+
64
+ readonly #procedures = new Map<string, TAnyProcedureContract>()
65
+ readonly #callers!: ClientCallers<this['_']['routes'], SafeCall, boolean>
66
+
67
+ constructor(
68
+ options: BaseClientOptions<RouterContract, SafeCall>,
69
+ transport: Transport,
70
+ transportOptions: Transport extends ClientTransportFactory<
71
+ any,
72
+ infer Options
73
+ >
74
+ ? Options
75
+ : never,
76
+ ) {
77
+ super(options, transport, transportOptions)
78
+
79
+ this.resolveProcedures(this.options.contract)
80
+ this.transformer = new RuntimeContractTransformer(this.options.contract)
81
+ this.#callers = this.buildCallers()
82
+ }
83
+
84
+ override get call() {
85
+ return this.#callers as ClientCallers<this['_']['routes'], SafeCall, false>
86
+ }
87
+
88
+ override get stream() {
89
+ return this.#callers as ClientCallers<this['_']['routes'], SafeCall, true>
90
+ }
91
+
92
+ protected resolveProcedures(router: TAnyRouterContract, path: string[] = []) {
93
+ for (const [key, route] of Object.entries(router.routes)) {
94
+ if (IsRouterContract(route)) {
95
+ this.resolveProcedures(route, [...path, key])
96
+ } else if (IsProcedureContract(route)) {
97
+ const fullName = [...path, key].join('/')
98
+ this.#procedures.set(fullName, route)
99
+ }
100
+ }
101
+ }
102
+
103
+ protected buildCallers(): ClientCallers<
104
+ this['_']['routes'],
105
+ SafeCall,
106
+ boolean
107
+ > {
108
+ const callers: Record<string, any> = Object.create(null)
109
+
110
+ for (const [name, { stream }] of this.#procedures) {
111
+ const parts = name.split('/')
112
+ let current = callers
113
+ for (let i = 0; i < parts.length; i++) {
114
+ const part = parts[i]
115
+ if (i === parts.length - 1) {
116
+ current[part] = (
117
+ payload?: unknown,
118
+ options?: Partial<ClientCallOptions>,
119
+ ) =>
120
+ this._call(name, payload, {
121
+ ...options,
122
+ _stream_response: !!stream,
123
+ })
124
+ } else {
125
+ current[part] = current[part] ?? Object.create(null)
126
+ current = current[part]
127
+ }
128
+ }
129
+ }
130
+
131
+ return callers as ClientCallers<this['_']['routes'], SafeCall, boolean>
132
+ }
133
+ }
@@ -0,0 +1,77 @@
1
+ import type { TAnyRouterContract } from '@nmtjs/contract'
2
+
3
+ import type { BaseClientOptions } from '../core.ts'
4
+ import type { ClientTransportFactory } from '../transport.ts'
5
+ import type {
6
+ ClientCallers,
7
+ ClientCallOptions,
8
+ StaticInputContractTypeProvider,
9
+ StaticOutputContractTypeProvider,
10
+ } from '../types.ts'
11
+ import { BaseClient } from '../core.ts'
12
+ import { BaseClientTransformer } from '../transformers.ts'
13
+
14
+ export class StaticClient<
15
+ Transport extends ClientTransportFactory<any, any> = ClientTransportFactory<
16
+ any,
17
+ any
18
+ >,
19
+ RouterContract extends TAnyRouterContract = TAnyRouterContract,
20
+ SafeCall extends boolean = false,
21
+ > extends BaseClient<
22
+ Transport,
23
+ RouterContract,
24
+ SafeCall,
25
+ StaticInputContractTypeProvider,
26
+ StaticOutputContractTypeProvider
27
+ > {
28
+ protected readonly transformer: BaseClientTransformer
29
+
30
+ constructor(
31
+ options: BaseClientOptions<RouterContract, SafeCall>,
32
+ transport: Transport,
33
+ transportOptions: Transport extends ClientTransportFactory<
34
+ any,
35
+ infer Options
36
+ >
37
+ ? Options
38
+ : never,
39
+ ) {
40
+ super(options, transport, transportOptions)
41
+ this.transformer = new BaseClientTransformer()
42
+ }
43
+
44
+ override get call() {
45
+ return this.createProxy(Object.create(null), false) as ClientCallers<
46
+ this['_']['routes'],
47
+ SafeCall,
48
+ false
49
+ >
50
+ }
51
+
52
+ override get stream() {
53
+ return this.createProxy(Object.create(null), true) as ClientCallers<
54
+ this['_']['routes'],
55
+ SafeCall,
56
+ true
57
+ >
58
+ }
59
+
60
+ protected createProxy<T>(
61
+ target: Record<string, unknown>,
62
+ isStream: boolean,
63
+ path: string[] = [],
64
+ ) {
65
+ return new Proxy(target, {
66
+ get: (obj, prop) => {
67
+ if (prop === 'then') return obj
68
+ const newPath = [...path, String(prop)]
69
+ const caller = (
70
+ payload?: unknown,
71
+ options?: Partial<ClientCallOptions>,
72
+ ) => this._call(newPath.join('/'), payload, options)
73
+ return this.createProxy(caller as any, isStream, newPath)
74
+ },
75
+ }) as T
76
+ }
77
+ }