@nmtjs/client 0.14.5 → 0.15.0-beta.10
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/LICENSE.md +1 -1
- package/README.md +1 -1
- package/dist/clients/runtime.d.ts +20 -0
- package/dist/clients/runtime.js +81 -0
- package/dist/clients/runtime.js.map +1 -0
- package/dist/clients/static.d.ts +13 -0
- package/dist/clients/static.js +27 -0
- package/dist/clients/static.js.map +1 -0
- package/dist/core.d.ts +71 -0
- package/dist/core.js +426 -0
- package/dist/core.js.map +1 -0
- package/dist/events.d.ts +16 -0
- package/dist/events.js +34 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/streams.d.ts +26 -0
- package/dist/streams.js +101 -0
- package/dist/streams.js.map +1 -0
- package/dist/transformers.d.ts +4 -0
- package/dist/transformers.js +9 -0
- package/dist/transformers.js.map +1 -0
- package/dist/transport.d.ts +53 -0
- package/dist/transport.js +2 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +41 -30
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -0
- package/package.json +17 -25
- package/src/clients/runtime.ts +133 -0
- package/src/clients/static.ts +77 -0
- package/src/core.ts +648 -0
- package/src/events.ts +70 -0
- package/src/index.ts +5 -0
- package/src/streams.ts +131 -0
- package/src/transformers.ts +8 -0
- package/src/transport.ts +71 -0
- package/src/types.ts +145 -0
- package/dist/common.d.ts +0 -38
- package/dist/common.js +0 -60
- package/dist/runtime.d.ts +0 -21
- package/dist/runtime.js +0 -105
- package/dist/static.d.ts +0 -9
- package/dist/static.js +0 -27
package/src/events.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Callback } from '@nmtjs/common'
|
|
2
|
+
|
|
3
|
+
export type EventMap = { [K: string]: any[] }
|
|
4
|
+
|
|
5
|
+
// TODO: add errors and promise rejections handling
|
|
6
|
+
/**
|
|
7
|
+
* Thin node-like event emitter wrapper around EventTarget
|
|
8
|
+
*/
|
|
9
|
+
export class EventEmitter<
|
|
10
|
+
Events extends EventMap = EventMap,
|
|
11
|
+
EventName extends Extract<keyof Events, string> = Extract<
|
|
12
|
+
keyof Events,
|
|
13
|
+
string
|
|
14
|
+
>,
|
|
15
|
+
> {
|
|
16
|
+
static once<
|
|
17
|
+
T extends EventEmitter,
|
|
18
|
+
E extends T extends EventEmitter<any, infer Event> ? Event : never,
|
|
19
|
+
>(ee: T, event: E) {
|
|
20
|
+
return new Promise((resolve) => ee.once(event, resolve))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#target = new EventTarget()
|
|
24
|
+
#listeners = new Map<Callback, Callback>()
|
|
25
|
+
|
|
26
|
+
on<E extends EventName>(
|
|
27
|
+
event: E | (Object & string),
|
|
28
|
+
listener: (...args: Events[E]) => void,
|
|
29
|
+
options?: AddEventListenerOptions,
|
|
30
|
+
) {
|
|
31
|
+
const wrapper = (event) => listener(...event.detail)
|
|
32
|
+
this.#listeners.set(listener, wrapper)
|
|
33
|
+
this.#target.addEventListener(event, wrapper, { ...options, once: false })
|
|
34
|
+
return () => this.#target.removeEventListener(event, wrapper)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
once<E extends EventName>(
|
|
38
|
+
event: E | (Object & string),
|
|
39
|
+
listener: (...args: Events[E]) => void,
|
|
40
|
+
options?: AddEventListenerOptions,
|
|
41
|
+
) {
|
|
42
|
+
return this.on(event, listener, { ...options, once: true })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
off(event: EventName | (Object & string), listener: Callback) {
|
|
46
|
+
const wrapper = this.#listeners.get(listener)
|
|
47
|
+
if (wrapper) this.#target.removeEventListener(event, wrapper)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
emit<E extends EventName | (Object & string)>(
|
|
51
|
+
event: E,
|
|
52
|
+
...args: E extends EventName ? Events[E] : any[]
|
|
53
|
+
) {
|
|
54
|
+
return this.#target.dispatchEvent(new CustomEvent(event, { detail: args }))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const once = <
|
|
59
|
+
T extends EventEmitter,
|
|
60
|
+
EventMap extends T extends EventEmitter<infer E, any> ? E : never,
|
|
61
|
+
EventName extends T extends EventEmitter<any, infer N> ? N : never,
|
|
62
|
+
>(
|
|
63
|
+
ee: T,
|
|
64
|
+
event: EventName,
|
|
65
|
+
signal?: AbortSignal,
|
|
66
|
+
) => {
|
|
67
|
+
return new Promise<EventMap[EventName]>((resolve) => {
|
|
68
|
+
ee.once(event, resolve, { signal })
|
|
69
|
+
})
|
|
70
|
+
}
|
package/src/index.ts
ADDED
package/src/streams.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { ProtocolBlobMetadata } from '@nmtjs/protocol'
|
|
2
|
+
import type { ProtocolServerStreamInterface } from '@nmtjs/protocol/client'
|
|
3
|
+
import { ProtocolClientBlobStream } from '@nmtjs/protocol/client'
|
|
4
|
+
|
|
5
|
+
export class ClientStreams {
|
|
6
|
+
readonly #collection = new Map<number, ProtocolClientBlobStream>()
|
|
7
|
+
|
|
8
|
+
get size() {
|
|
9
|
+
return this.#collection.size
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get(streamId: number) {
|
|
13
|
+
const stream = this.#collection.get(streamId)
|
|
14
|
+
if (!stream) throw new Error('Stream not found')
|
|
15
|
+
return stream
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
add(
|
|
19
|
+
source: ReadableStream,
|
|
20
|
+
streamId: number,
|
|
21
|
+
metadata: ProtocolBlobMetadata,
|
|
22
|
+
) {
|
|
23
|
+
const stream = new ProtocolClientBlobStream(source, streamId, metadata)
|
|
24
|
+
this.#collection.set(streamId, stream)
|
|
25
|
+
return stream
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
remove(streamId: number) {
|
|
29
|
+
this.#collection.delete(streamId)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async abort(streamId: number, reason?: string) {
|
|
33
|
+
const stream = this.#collection.get(streamId)
|
|
34
|
+
if (!stream) return // Stream already cleaned up
|
|
35
|
+
await stream.abort(reason)
|
|
36
|
+
this.remove(streamId)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
pull(streamId: number, size: number) {
|
|
40
|
+
const stream = this.get(streamId)
|
|
41
|
+
return stream.read(size)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async end(streamId: number) {
|
|
45
|
+
await this.get(streamId).end()
|
|
46
|
+
this.remove(streamId)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async clear(reason?: string) {
|
|
50
|
+
if (reason) {
|
|
51
|
+
const abortPromises = [...this.#collection.values()].map((stream) =>
|
|
52
|
+
stream.abort(reason),
|
|
53
|
+
)
|
|
54
|
+
await Promise.all(abortPromises)
|
|
55
|
+
}
|
|
56
|
+
this.#collection.clear()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class ServerStreams<
|
|
61
|
+
T extends ProtocolServerStreamInterface = ProtocolServerStreamInterface,
|
|
62
|
+
> {
|
|
63
|
+
readonly #collection = new Map<number, T>()
|
|
64
|
+
readonly #writers = new Map<number, WritableStreamDefaultWriter>()
|
|
65
|
+
|
|
66
|
+
get size() {
|
|
67
|
+
return this.#collection.size
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
has(streamId: number) {
|
|
71
|
+
return this.#collection.has(streamId)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get(streamId: number) {
|
|
75
|
+
const stream = this.#collection.get(streamId)
|
|
76
|
+
if (!stream) throw new Error('Stream not found')
|
|
77
|
+
return stream
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
add(streamId: number, stream: T) {
|
|
81
|
+
this.#collection.set(streamId, stream)
|
|
82
|
+
this.#writers.set(
|
|
83
|
+
streamId,
|
|
84
|
+
stream.writable.getWriter() as WritableStreamDefaultWriter,
|
|
85
|
+
)
|
|
86
|
+
return stream
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
remove(streamId: number) {
|
|
90
|
+
this.#collection.delete(streamId)
|
|
91
|
+
this.#writers.delete(streamId)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async abort(streamId: number) {
|
|
95
|
+
if (this.has(streamId)) {
|
|
96
|
+
const writer = this.#writers.get(streamId)
|
|
97
|
+
if (writer) {
|
|
98
|
+
await writer.abort()
|
|
99
|
+
writer.releaseLock()
|
|
100
|
+
}
|
|
101
|
+
this.remove(streamId)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async push(streamId: number, chunk: ArrayBufferView) {
|
|
106
|
+
const writer = this.#writers.get(streamId)
|
|
107
|
+
if (writer) {
|
|
108
|
+
return await writer.write(chunk)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async end(streamId: number) {
|
|
113
|
+
const writer = this.#writers.get(streamId)
|
|
114
|
+
if (writer) {
|
|
115
|
+
await writer.close()
|
|
116
|
+
writer.releaseLock()
|
|
117
|
+
}
|
|
118
|
+
this.remove(streamId)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async clear(reason?: string) {
|
|
122
|
+
if (reason) {
|
|
123
|
+
const abortPromises = [...this.#writers.values()].map((writer) =>
|
|
124
|
+
writer.abort(reason).finally(() => writer.releaseLock()),
|
|
125
|
+
)
|
|
126
|
+
await Promise.allSettled(abortPromises)
|
|
127
|
+
}
|
|
128
|
+
this.#collection.clear()
|
|
129
|
+
this.#writers.clear()
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/transport.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ConnectionType,
|
|
3
|
+
ProtocolBlobMetadata,
|
|
4
|
+
ProtocolVersion,
|
|
5
|
+
} from '@nmtjs/protocol'
|
|
6
|
+
import type { BaseClientFormat } from '@nmtjs/protocol/client'
|
|
7
|
+
|
|
8
|
+
export type ClientTransportMessageOptions = {
|
|
9
|
+
signal?: AbortSignal
|
|
10
|
+
_stream_response?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ClientTransportStartParams {
|
|
14
|
+
auth?: string
|
|
15
|
+
application?: string
|
|
16
|
+
onMessage: (message: ArrayBufferView) => any
|
|
17
|
+
onConnect: () => any
|
|
18
|
+
onDisconnect: (reason: 'client' | 'server' | (string & {})) => any
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ClientTransportRpcParams {
|
|
22
|
+
format: BaseClientFormat
|
|
23
|
+
auth?: string
|
|
24
|
+
application?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ClientCallResponse =
|
|
28
|
+
| { type: 'rpc'; result: ArrayBufferView }
|
|
29
|
+
| { type: 'rpc_stream'; stream: ReadableStream<ArrayBufferView> }
|
|
30
|
+
| {
|
|
31
|
+
type: 'blob'
|
|
32
|
+
metadata: ProtocolBlobMetadata
|
|
33
|
+
source: ReadableStream<ArrayBufferView>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type ClientTransport<T extends ConnectionType = ConnectionType> =
|
|
37
|
+
T extends ConnectionType.Bidirectional
|
|
38
|
+
? {
|
|
39
|
+
type: ConnectionType.Bidirectional
|
|
40
|
+
connect(params: ClientTransportStartParams): Promise<void>
|
|
41
|
+
disconnect(): Promise<void>
|
|
42
|
+
send(
|
|
43
|
+
message: ArrayBufferView,
|
|
44
|
+
options: ClientTransportMessageOptions,
|
|
45
|
+
): Promise<void>
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
type: ConnectionType.Unidirectional
|
|
49
|
+
connect?(params: ClientTransportStartParams): Promise<void>
|
|
50
|
+
disconnect?(): Promise<void>
|
|
51
|
+
call(
|
|
52
|
+
client: {
|
|
53
|
+
format: BaseClientFormat
|
|
54
|
+
auth?: string
|
|
55
|
+
application?: string
|
|
56
|
+
},
|
|
57
|
+
rpc: { callId: number; procedure: string; payload: any },
|
|
58
|
+
options: ClientTransportMessageOptions,
|
|
59
|
+
): Promise<ClientCallResponse>
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ClientTransportParams {
|
|
63
|
+
protocol: ProtocolVersion
|
|
64
|
+
format: BaseClientFormat
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type ClientTransportFactory<
|
|
68
|
+
Type extends ConnectionType,
|
|
69
|
+
Options = unknown,
|
|
70
|
+
Transport extends ClientTransport<Type> = ClientTransport<Type>,
|
|
71
|
+
> = (params: ClientTransportParams, options: Options) => Transport
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { CallTypeProvider, OneOf, TypeProvider } from '@nmtjs/common'
|
|
2
|
+
import type { TAnyProcedureContract, TAnyRouterContract } from '@nmtjs/contract'
|
|
3
|
+
import type { ProtocolBlobInterface } from '@nmtjs/protocol'
|
|
4
|
+
import type {
|
|
5
|
+
ProtocolError,
|
|
6
|
+
ProtocolServerBlobStream,
|
|
7
|
+
ProtocolServerStreamInterface,
|
|
8
|
+
} from '@nmtjs/protocol/client'
|
|
9
|
+
import type { BaseTypeAny, PlainType, t } from '@nmtjs/type'
|
|
10
|
+
|
|
11
|
+
export const ResolvedType: unique symbol = Symbol('ResolvedType')
|
|
12
|
+
export type ResolvedType = typeof ResolvedType
|
|
13
|
+
|
|
14
|
+
export type ClientCallOptions = {
|
|
15
|
+
timeout?: number
|
|
16
|
+
signal?: AbortSignal
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
_stream_response?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ClientOutputType<T> = T extends ProtocolBlobInterface
|
|
24
|
+
? (options?: { signal?: AbortSignal }) => ProtocolServerBlobStream
|
|
25
|
+
: T extends { [PlainType]?: true }
|
|
26
|
+
? { [K in keyof Omit<T, PlainType>]: ClientOutputType<T[K]> }
|
|
27
|
+
: T
|
|
28
|
+
|
|
29
|
+
export interface StaticInputContractTypeProvider extends TypeProvider {
|
|
30
|
+
output: this['input'] extends BaseTypeAny
|
|
31
|
+
? t.infer.decode.input<this['input']>
|
|
32
|
+
: never
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface RuntimeInputContractTypeProvider extends TypeProvider {
|
|
36
|
+
output: this['input'] extends BaseTypeAny
|
|
37
|
+
? t.infer.encode.input<this['input']>
|
|
38
|
+
: never
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface StaticOutputContractTypeProvider extends TypeProvider {
|
|
42
|
+
output: this['input'] extends BaseTypeAny
|
|
43
|
+
? ClientOutputType<t.infer.encodeRaw.output<this['input']>>
|
|
44
|
+
: never
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface RuntimeOutputContractTypeProvider extends TypeProvider {
|
|
48
|
+
output: this['input'] extends BaseTypeAny
|
|
49
|
+
? ClientOutputType<t.infer.decodeRaw.output<this['input']>>
|
|
50
|
+
: never
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type AnyResolvedContractProcedure = {
|
|
54
|
+
[ResolvedType]: 'procedure'
|
|
55
|
+
contract: TAnyProcedureContract
|
|
56
|
+
stream: boolean
|
|
57
|
+
input: any
|
|
58
|
+
output: any
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type AnyResolvedContractRouter = {
|
|
62
|
+
[ResolvedType]: 'router'
|
|
63
|
+
[key: string]:
|
|
64
|
+
| AnyResolvedContractProcedure
|
|
65
|
+
| { [ResolvedType]: 'router'; [key: string]: AnyResolvedContractProcedure }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type ResolveAPIRouterRoutes<
|
|
69
|
+
T extends TAnyRouterContract,
|
|
70
|
+
InputTypeProvider extends TypeProvider = TypeProvider,
|
|
71
|
+
OutputTypeProvider extends TypeProvider = TypeProvider,
|
|
72
|
+
> = { [ResolvedType]: 'router' } & {
|
|
73
|
+
[K in keyof T['routes']]: T['routes'][K] extends TAnyProcedureContract
|
|
74
|
+
? {
|
|
75
|
+
[ResolvedType]: 'procedure'
|
|
76
|
+
contract: T['routes'][K]
|
|
77
|
+
stream: T['routes'][K]['stream'] extends true ? true : false
|
|
78
|
+
input: CallTypeProvider<InputTypeProvider, T['routes'][K]['input']>
|
|
79
|
+
output: T['routes'][K]['stream'] extends true
|
|
80
|
+
? AsyncIterable<
|
|
81
|
+
CallTypeProvider<OutputTypeProvider, T['routes'][K]['output']>
|
|
82
|
+
>
|
|
83
|
+
: CallTypeProvider<OutputTypeProvider, T['routes'][K]['output']>
|
|
84
|
+
}
|
|
85
|
+
: T['routes'][K] extends TAnyRouterContract
|
|
86
|
+
? ResolveAPIRouterRoutes<
|
|
87
|
+
T['routes'][K],
|
|
88
|
+
InputTypeProvider,
|
|
89
|
+
OutputTypeProvider
|
|
90
|
+
>
|
|
91
|
+
: never
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type ResolveContract<
|
|
95
|
+
C extends TAnyRouterContract = TAnyRouterContract,
|
|
96
|
+
InputTypeProvider extends TypeProvider = TypeProvider,
|
|
97
|
+
OutputTypeProvider extends TypeProvider = TypeProvider,
|
|
98
|
+
> = ResolveAPIRouterRoutes<C, InputTypeProvider, OutputTypeProvider>
|
|
99
|
+
|
|
100
|
+
export type ClientCaller<
|
|
101
|
+
Procedure extends AnyResolvedContractProcedure,
|
|
102
|
+
SafeCall extends boolean,
|
|
103
|
+
> = (
|
|
104
|
+
...args: Procedure['input'] extends t.NeverType
|
|
105
|
+
? [data?: undefined, options?: Partial<ClientCallOptions>]
|
|
106
|
+
: undefined extends t.infer.encode.input<Procedure['contract']['input']>
|
|
107
|
+
? [data?: Procedure['input'], options?: Partial<ClientCallOptions>]
|
|
108
|
+
: [data: Procedure['input'], options?: Partial<ClientCallOptions>]
|
|
109
|
+
) => SafeCall extends true
|
|
110
|
+
? Promise<OneOf<[{ result: Procedure['output'] }, { error: ProtocolError }]>>
|
|
111
|
+
: Promise<Procedure['output']>
|
|
112
|
+
|
|
113
|
+
type OmitType<T extends object, E> = {
|
|
114
|
+
[K in keyof T as T[K] extends E ? never : K]: T[K]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// export type FilterResolvedContractRouter<
|
|
118
|
+
// Resolved extends AnyResolvedContractRouter,
|
|
119
|
+
// Stream extends boolean,
|
|
120
|
+
// > = {
|
|
121
|
+
// [K in keyof Resolved]: Resolved[K] extends AnyResolvedContractProcedure
|
|
122
|
+
// ? Resolved[K]['stream'] extends Stream
|
|
123
|
+
// ? Resolved[K]
|
|
124
|
+
// : never
|
|
125
|
+
// : Resolved[K] extends AnyResolvedContractRouter
|
|
126
|
+
// ? FilterResolvedContractRouter<Resolved[K], Stream>
|
|
127
|
+
// : never
|
|
128
|
+
// }
|
|
129
|
+
|
|
130
|
+
export type ClientCallers<
|
|
131
|
+
Resolved extends AnyResolvedContractRouter,
|
|
132
|
+
SafeCall extends boolean,
|
|
133
|
+
Stream extends boolean,
|
|
134
|
+
> = OmitType<
|
|
135
|
+
{
|
|
136
|
+
[K in keyof Resolved]: Resolved[K] extends AnyResolvedContractProcedure
|
|
137
|
+
? Stream extends (Resolved[K]['stream'] extends true ? true : false)
|
|
138
|
+
? ClientCaller<Resolved[K], SafeCall>
|
|
139
|
+
: never
|
|
140
|
+
: Resolved[K] extends AnyResolvedContractRouter
|
|
141
|
+
? ClientCallers<Resolved[K], SafeCall, Stream>
|
|
142
|
+
: never
|
|
143
|
+
},
|
|
144
|
+
never
|
|
145
|
+
>
|
package/dist/common.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { TypeProvider } from '@nmtjs/common';
|
|
2
|
-
import type { TAnyAPIContract } from '@nmtjs/contract';
|
|
3
|
-
import type { ProtocolBaseClientCallOptions, ProtocolBaseTransformer, ProtocolTransport } from '@nmtjs/protocol/client';
|
|
4
|
-
import { ProtocolError } from '@nmtjs/protocol/client';
|
|
5
|
-
import type { ClientCallers, ResolveAPIRouterRoutes } from './types.ts';
|
|
6
|
-
export { ErrorCode, ProtocolBlob, type ProtocolBlobMetadata, TransportType, } from '@nmtjs/protocol';
|
|
7
|
-
export * from './types.ts';
|
|
8
|
-
export declare class ClientError extends ProtocolError {
|
|
9
|
-
}
|
|
10
|
-
export interface BaseClientOptions<SafeCall extends boolean = false> {
|
|
11
|
-
timeout: number;
|
|
12
|
-
autoreconnect?: boolean;
|
|
13
|
-
safe?: SafeCall;
|
|
14
|
-
}
|
|
15
|
-
export declare abstract class BaseClient<APIContract extends TAnyAPIContract = TAnyAPIContract, SafeCall extends boolean = false, InputTypeProvider extends TypeProvider = TypeProvider, OutputTypeProvider extends TypeProvider = TypeProvider, Routes extends {
|
|
16
|
-
contract: APIContract['router'];
|
|
17
|
-
routes: ResolveAPIRouterRoutes<APIContract['router'], InputTypeProvider, OutputTypeProvider>;
|
|
18
|
-
} = {
|
|
19
|
-
contract: APIContract['router'];
|
|
20
|
-
routes: ResolveAPIRouterRoutes<APIContract['router'], InputTypeProvider, OutputTypeProvider>;
|
|
21
|
-
}> {
|
|
22
|
-
readonly transport: ProtocolTransport;
|
|
23
|
-
readonly options: BaseClientOptions<SafeCall>;
|
|
24
|
-
_: {
|
|
25
|
-
api: Routes;
|
|
26
|
-
safe: SafeCall;
|
|
27
|
-
};
|
|
28
|
-
protected abstract transformer: ProtocolBaseTransformer;
|
|
29
|
-
protected callers: ClientCallers<Routes, SafeCall>;
|
|
30
|
-
auth: any;
|
|
31
|
-
protected reconnectTimeout: number;
|
|
32
|
-
constructor(transport: ProtocolTransport, options: BaseClientOptions<SafeCall>);
|
|
33
|
-
protected _call(procedure: string, payload: any, options: ProtocolBaseClientCallOptions): Promise<any>;
|
|
34
|
-
get call(): ClientCallers<Routes, SafeCall>;
|
|
35
|
-
setAuth(auth: any): void;
|
|
36
|
-
connect(): Promise<void>;
|
|
37
|
-
disconnect(): Promise<void>;
|
|
38
|
-
}
|
package/dist/common.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { noopFn } from '@nmtjs/common';
|
|
2
|
-
import { ProtocolError } from '@nmtjs/protocol/client';
|
|
3
|
-
export { ErrorCode, ProtocolBlob, TransportType, } from '@nmtjs/protocol';
|
|
4
|
-
export * from "./types.js";
|
|
5
|
-
export class ClientError extends ProtocolError {
|
|
6
|
-
}
|
|
7
|
-
const DEFAULT_RECONNECT_TIMEOUT = 1000;
|
|
8
|
-
export class BaseClient {
|
|
9
|
-
transport;
|
|
10
|
-
options;
|
|
11
|
-
_;
|
|
12
|
-
callers;
|
|
13
|
-
auth;
|
|
14
|
-
reconnectTimeout = DEFAULT_RECONNECT_TIMEOUT;
|
|
15
|
-
constructor(transport, options) {
|
|
16
|
-
this.transport = transport;
|
|
17
|
-
this.options = options;
|
|
18
|
-
if (this.options.autoreconnect) {
|
|
19
|
-
this.transport.on('disconnected', async (reason) => {
|
|
20
|
-
if (reason === 'server') {
|
|
21
|
-
this.connect();
|
|
22
|
-
}
|
|
23
|
-
else if (reason === 'error') {
|
|
24
|
-
const timeout = new Promise((resolve) => setTimeout(resolve, this.reconnectTimeout));
|
|
25
|
-
const connected = new Promise((_, reject) => this.transport.once('connected', reject));
|
|
26
|
-
this.reconnectTimeout += DEFAULT_RECONNECT_TIMEOUT;
|
|
27
|
-
await Promise.race([timeout, connected]).then(this.connect.bind(this), noopFn);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
this.transport.on('connected', () => {
|
|
31
|
-
this.reconnectTimeout = DEFAULT_RECONNECT_TIMEOUT;
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
async _call(procedure, payload, options) {
|
|
36
|
-
const call = await this.transport.call(procedure, payload, options, this.transformer);
|
|
37
|
-
if (this.options.safe) {
|
|
38
|
-
return await call.promise
|
|
39
|
-
.then((result) => ({ result }))
|
|
40
|
-
.catch((error) => ({ error }));
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
return await call.promise.catch((error) => {
|
|
44
|
-
throw error;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
get call() {
|
|
49
|
-
return this.callers;
|
|
50
|
-
}
|
|
51
|
-
setAuth(auth) {
|
|
52
|
-
this.auth = auth;
|
|
53
|
-
}
|
|
54
|
-
connect() {
|
|
55
|
-
return this.transport.connect(this.auth, this.transformer);
|
|
56
|
-
}
|
|
57
|
-
disconnect() {
|
|
58
|
-
return this.transport.disconnect();
|
|
59
|
-
}
|
|
60
|
-
}
|
package/dist/runtime.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { TAnyAPIContract, TAnyProcedureContract, TAnyRouterContract } from '@nmtjs/contract';
|
|
2
|
-
import { ProtocolBaseTransformer } from '@nmtjs/protocol/client';
|
|
3
|
-
import type { RuntimeInputContractTypeProvider, RuntimeOutputContractTypeProvider } from './common.ts';
|
|
4
|
-
import { BaseClient } from './common.ts';
|
|
5
|
-
export declare class RuntimeContractTransformer extends ProtocolBaseTransformer {
|
|
6
|
-
protected procedures: Map<string, TAnyProcedureContract>;
|
|
7
|
-
constructor(procedures: Map<string, TAnyProcedureContract>);
|
|
8
|
-
decodeRPC(procedure: string, payload: any): any;
|
|
9
|
-
decodeRPCChunk(procedure: string, payload: any): unknown;
|
|
10
|
-
encodeRPC(procedure: string, payload: any): unknown;
|
|
11
|
-
protected getProcedureContract(procedure: string): TAnyProcedureContract;
|
|
12
|
-
protected build(router: TAnyRouterContract): void;
|
|
13
|
-
}
|
|
14
|
-
export declare class RuntimeClient<APIContract extends TAnyAPIContract, SafeCall extends boolean = false> extends BaseClient<APIContract, SafeCall, RuntimeInputContractTypeProvider, RuntimeOutputContractTypeProvider> {
|
|
15
|
-
contract: APIContract;
|
|
16
|
-
protected transformer: RuntimeContractTransformer;
|
|
17
|
-
protected procedures: Map<string, TAnyProcedureContract>;
|
|
18
|
-
constructor(contract: APIContract, ...args: ConstructorParameters<typeof BaseClient<APIContract, SafeCall>>);
|
|
19
|
-
protected resolveProcedures(router: TAnyRouterContract): void;
|
|
20
|
-
protected buildCallers(): any;
|
|
21
|
-
}
|
package/dist/runtime.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { IsProcedureContract, IsRouterContract } from '@nmtjs/contract';
|
|
2
|
-
import { ErrorCode } from '@nmtjs/protocol';
|
|
3
|
-
import { ProtocolBaseTransformer } from '@nmtjs/protocol/client';
|
|
4
|
-
import { NeemataTypeError, t } from '@nmtjs/type';
|
|
5
|
-
import { BaseClient, ClientError } from "./common.js";
|
|
6
|
-
export class RuntimeContractTransformer extends ProtocolBaseTransformer {
|
|
7
|
-
procedures;
|
|
8
|
-
constructor(procedures) {
|
|
9
|
-
super();
|
|
10
|
-
this.procedures = procedures;
|
|
11
|
-
}
|
|
12
|
-
decodeRPC(procedure, payload) {
|
|
13
|
-
const contract = this.getProcedureContract(procedure);
|
|
14
|
-
const type = contract.output;
|
|
15
|
-
if (type instanceof t.NeverType)
|
|
16
|
-
return undefined;
|
|
17
|
-
return payload;
|
|
18
|
-
}
|
|
19
|
-
decodeRPCChunk(procedure, payload) {
|
|
20
|
-
const contract = this.getProcedureContract(procedure);
|
|
21
|
-
const type = contract.stream;
|
|
22
|
-
if (!type || type instanceof t.NeverType)
|
|
23
|
-
return undefined;
|
|
24
|
-
return type.decode(payload);
|
|
25
|
-
}
|
|
26
|
-
encodeRPC(procedure, payload) {
|
|
27
|
-
const contract = this.getProcedureContract(procedure);
|
|
28
|
-
const type = contract.input;
|
|
29
|
-
if (type instanceof t.NeverType)
|
|
30
|
-
return undefined;
|
|
31
|
-
try {
|
|
32
|
-
return type.encode(payload);
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
35
|
-
if (error instanceof NeemataTypeError) {
|
|
36
|
-
throw new ClientError(ErrorCode.ValidationError, `Invalid payload for ${procedure}: ${error.message}`, error.issues);
|
|
37
|
-
}
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
getProcedureContract(procedure) {
|
|
42
|
-
const proc = this.procedures.get(procedure);
|
|
43
|
-
if (!proc) {
|
|
44
|
-
throw new ClientError(ErrorCode.NotFound, `Procedure contract not found for procedure: ${procedure}`);
|
|
45
|
-
}
|
|
46
|
-
return proc;
|
|
47
|
-
}
|
|
48
|
-
build(router) {
|
|
49
|
-
const routes = Object.values(router.routes);
|
|
50
|
-
for (const route of routes) {
|
|
51
|
-
if (IsRouterContract(route)) {
|
|
52
|
-
this.build(route);
|
|
53
|
-
}
|
|
54
|
-
else if (IsProcedureContract(route)) {
|
|
55
|
-
this.procedures.set(route.name, route);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
export class RuntimeClient extends BaseClient {
|
|
61
|
-
contract;
|
|
62
|
-
transformer;
|
|
63
|
-
procedures = new Map();
|
|
64
|
-
constructor(contract, ...args) {
|
|
65
|
-
super(...args);
|
|
66
|
-
this.contract = contract;
|
|
67
|
-
this.resolveProcedures(this.contract.router);
|
|
68
|
-
this.transformer = new RuntimeContractTransformer(this.procedures);
|
|
69
|
-
this.callers = this.buildCallers();
|
|
70
|
-
}
|
|
71
|
-
resolveProcedures(router) {
|
|
72
|
-
const routes = Object.values(router.routes);
|
|
73
|
-
for (const route of routes) {
|
|
74
|
-
if (IsRouterContract(route)) {
|
|
75
|
-
this.resolveProcedures(route);
|
|
76
|
-
}
|
|
77
|
-
else if (IsProcedureContract(route)) {
|
|
78
|
-
this.procedures.set(route.name, route);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
buildCallers() {
|
|
83
|
-
const callers = Object.create(null);
|
|
84
|
-
for (const [name, procedure] of this.procedures) {
|
|
85
|
-
const parts = name.split('/');
|
|
86
|
-
let current = callers;
|
|
87
|
-
for (let i = 0; i < parts.length; i++) {
|
|
88
|
-
const part = parts[i];
|
|
89
|
-
if (i === parts.length - 1) {
|
|
90
|
-
current[part] = (payload, options = {}) => this._call(name, payload, {
|
|
91
|
-
timeout: procedure.timeout || options.timeout || this.options.timeout,
|
|
92
|
-
...options,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
if (!current[part]) {
|
|
97
|
-
current[part] = {};
|
|
98
|
-
}
|
|
99
|
-
current = current[part];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return callers;
|
|
104
|
-
}
|
|
105
|
-
}
|
package/dist/static.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { TAnyAPIContract } from '@nmtjs/contract';
|
|
2
|
-
import { ProtocolBaseTransformer } from '@nmtjs/protocol/client';
|
|
3
|
-
import type { StaticInputContractTypeProvider, StaticOutputContractTypeProvider } from './common.ts';
|
|
4
|
-
import { BaseClient } from './common.ts';
|
|
5
|
-
export declare class StaticClient<APIContract extends TAnyAPIContract, SafeCall extends boolean = false> extends BaseClient<APIContract, SafeCall, StaticInputContractTypeProvider, StaticOutputContractTypeProvider> {
|
|
6
|
-
protected transformer: ProtocolBaseTransformer;
|
|
7
|
-
constructor(...args: ConstructorParameters<typeof BaseClient<APIContract, SafeCall>>);
|
|
8
|
-
protected createProxy(target: any, path?: string[]): any;
|
|
9
|
-
}
|