nmtjs 0.15.0-beta.2 → 0.15.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -0
- package/dist/entrypoints/cli.d.ts +1 -0
- package/dist/entrypoints/cli.js +1 -0
- package/dist/entrypoints/cli.js.map +1 -0
- package/dist/entrypoints/main.d.ts +5 -0
- package/dist/entrypoints/main.js +83 -15
- package/dist/entrypoints/main.js.map +1 -0
- package/dist/entrypoints/thread.d.ts +14 -0
- package/dist/entrypoints/thread.js +130 -24
- package/dist/entrypoints/thread.js.map +1 -0
- package/dist/entrypoints/worker.d.ts +3 -0
- package/dist/entrypoints/worker.js +4 -3
- package/dist/entrypoints/worker.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/{_exports/index.js → index.js} +9 -5
- package/dist/index.js.map +1 -0
- package/dist/resolver.d.ts +2 -0
- package/dist/resolver.js +1 -0
- package/dist/resolver.js.map +1 -0
- package/dist/runtime/application/api/api.d.ts +49 -0
- package/dist/runtime/application/api/api.js +193 -0
- package/dist/runtime/application/api/api.js.map +1 -0
- package/dist/runtime/application/api/constants.d.ts +14 -0
- package/dist/runtime/application/api/constants.js +8 -0
- package/dist/runtime/application/api/constants.js.map +1 -0
- package/dist/runtime/application/api/filters.d.ts +14 -0
- package/dist/runtime/application/api/filters.js +11 -0
- package/dist/runtime/application/api/filters.js.map +1 -0
- package/dist/runtime/application/api/guards.d.ts +13 -0
- package/dist/runtime/application/api/guards.js +8 -0
- package/dist/runtime/application/api/guards.js.map +1 -0
- package/dist/runtime/application/api/index.d.ts +8 -0
- package/dist/runtime/application/api/index.js +9 -0
- package/dist/runtime/application/api/index.js.map +1 -0
- package/dist/runtime/application/api/middlewares.d.ts +14 -0
- package/dist/runtime/application/api/middlewares.js +12 -0
- package/dist/runtime/application/api/middlewares.js.map +1 -0
- package/dist/runtime/application/api/procedure.d.ts +67 -0
- package/dist/runtime/application/api/procedure.js +50 -0
- package/dist/runtime/application/api/procedure.js.map +1 -0
- package/dist/runtime/application/api/router.d.ts +71 -0
- package/dist/runtime/application/api/router.js +51 -0
- package/dist/runtime/application/api/router.js.map +1 -0
- package/dist/runtime/application/api/types.d.ts +32 -0
- package/dist/runtime/application/api/types.js +2 -0
- package/dist/runtime/application/api/types.js.map +1 -0
- package/dist/runtime/application/config.d.ts +26 -0
- package/dist/runtime/application/config.js +21 -0
- package/dist/runtime/application/config.js.map +1 -0
- package/dist/runtime/application/constants.d.ts +2 -0
- package/dist/runtime/application/constants.js +2 -0
- package/dist/runtime/application/constants.js.map +1 -0
- package/dist/runtime/application/hook.d.ts +19 -0
- package/dist/runtime/application/hook.js +11 -0
- package/dist/runtime/application/hook.js.map +1 -0
- package/dist/runtime/application/hooks.d.ts +3 -0
- package/dist/runtime/application/hooks.js +4 -0
- package/dist/runtime/application/hooks.js.map +1 -0
- package/dist/runtime/application/index.d.ts +5 -0
- package/dist/runtime/application/index.js +6 -0
- package/dist/runtime/application/index.js.map +1 -0
- package/dist/runtime/constants.d.ts +8 -0
- package/dist/runtime/constants.js +5 -0
- package/dist/runtime/constants.js.map +1 -0
- package/dist/runtime/core/hooks.d.ts +4 -0
- package/dist/runtime/core/hooks.js +4 -0
- package/dist/runtime/core/hooks.js.map +1 -0
- package/dist/runtime/core/plugin.d.ts +8 -0
- package/dist/runtime/core/plugin.js +4 -0
- package/dist/runtime/core/plugin.js.map +1 -0
- package/dist/runtime/core/runtime.d.ts +27 -0
- package/dist/runtime/core/runtime.js +81 -0
- package/dist/runtime/core/runtime.js.map +1 -0
- package/dist/runtime/enums.d.ts +21 -0
- package/dist/runtime/enums.js +26 -0
- package/dist/runtime/enums.js.map +1 -0
- package/dist/runtime/index.d.ts +21 -0
- package/dist/runtime/index.js +22 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/injectables.d.ts +23 -0
- package/dist/runtime/injectables.js +20 -0
- package/dist/runtime/injectables.js.map +1 -0
- package/dist/runtime/jobs/job.d.ts +132 -0
- package/dist/runtime/jobs/job.js +68 -0
- package/dist/runtime/jobs/job.js.map +1 -0
- package/dist/runtime/jobs/manager.d.ts +113 -0
- package/dist/runtime/jobs/manager.js +210 -0
- package/dist/runtime/jobs/manager.js.map +1 -0
- package/dist/runtime/jobs/router.d.ts +266 -0
- package/dist/runtime/jobs/router.js +432 -0
- package/dist/runtime/jobs/router.js.map +1 -0
- package/dist/runtime/jobs/runner.d.ts +64 -0
- package/dist/runtime/jobs/runner.js +256 -0
- package/dist/runtime/jobs/runner.js.map +1 -0
- package/dist/runtime/jobs/step.d.ts +23 -0
- package/dist/runtime/jobs/step.js +18 -0
- package/dist/runtime/jobs/step.js.map +1 -0
- package/dist/runtime/jobs/ui.d.ts +3 -0
- package/dist/runtime/jobs/ui.js +17 -0
- package/dist/runtime/jobs/ui.js.map +1 -0
- package/dist/runtime/pubsub/manager.d.ts +48 -0
- package/dist/runtime/pubsub/manager.js +119 -0
- package/dist/runtime/pubsub/manager.js.map +1 -0
- package/dist/runtime/pubsub/redis.d.ts +16 -0
- package/dist/runtime/pubsub/redis.js +98 -0
- package/dist/runtime/pubsub/redis.js.map +1 -0
- package/dist/runtime/scheduler/index.d.ts +22 -0
- package/dist/runtime/scheduler/index.js +20 -0
- package/dist/runtime/scheduler/index.js.map +1 -0
- package/dist/runtime/server/applications.d.ts +52 -0
- package/dist/runtime/server/applications.js +133 -0
- package/dist/runtime/server/applications.js.map +1 -0
- package/dist/runtime/server/config.d.ts +121 -0
- package/dist/runtime/server/config.js +33 -0
- package/dist/runtime/server/config.js.map +1 -0
- package/dist/runtime/server/jobs.d.ts +41 -0
- package/dist/runtime/server/jobs.js +181 -0
- package/dist/runtime/server/jobs.js.map +1 -0
- package/dist/runtime/server/pool.d.ts +54 -0
- package/dist/runtime/server/pool.js +194 -0
- package/dist/runtime/server/pool.js.map +1 -0
- package/dist/runtime/server/proxy.d.ts +21 -0
- package/dist/runtime/server/proxy.js +79 -0
- package/dist/runtime/server/proxy.js.map +1 -0
- package/dist/runtime/server/server.d.ts +53 -0
- package/dist/runtime/server/server.js +90 -0
- package/dist/runtime/server/server.js.map +1 -0
- package/dist/runtime/store/index.d.ts +3 -0
- package/dist/runtime/store/index.js +23 -0
- package/dist/runtime/store/index.js.map +1 -0
- package/dist/runtime/types.d.ts +103 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/workers/application.d.ts +47 -0
- package/dist/runtime/workers/application.js +162 -0
- package/dist/runtime/workers/application.js.map +1 -0
- package/dist/runtime/workers/base.d.ts +16 -0
- package/dist/runtime/workers/base.js +46 -0
- package/dist/runtime/workers/base.js.map +1 -0
- package/dist/runtime/workers/cli.d.ts +1 -0
- package/dist/runtime/workers/cli.js +2 -0
- package/dist/runtime/workers/cli.js.map +1 -0
- package/dist/runtime/workers/job.d.ts +20 -0
- package/dist/runtime/workers/job.js +172 -0
- package/dist/runtime/workers/job.js.map +1 -0
- package/dist/typings.d.ts +5 -0
- package/dist/typings.js +4 -3
- package/dist/typings.js.map +1 -0
- package/dist/vite/builder.d.ts +5 -0
- package/dist/vite/builder.js +5 -1
- package/dist/vite/builder.js.map +1 -0
- package/dist/vite/config.d.ts +28 -0
- package/dist/vite/config.js +1 -0
- package/dist/vite/config.js.map +1 -0
- package/dist/vite/plugins.d.ts +2 -0
- package/dist/vite/plugins.js +1 -0
- package/dist/vite/plugins.js.map +1 -0
- package/dist/vite/runners/worker.d.ts +4 -0
- package/dist/vite/runners/worker.js +1 -0
- package/dist/vite/runners/worker.js.map +1 -0
- package/dist/vite/server.d.ts +3 -0
- package/dist/vite/server.js +6 -1
- package/dist/vite/server.js.map +1 -0
- package/dist/vite/servers/main.d.ts +8 -0
- package/dist/vite/servers/main.js +1 -0
- package/dist/vite/servers/main.js.map +1 -0
- package/dist/vite/servers/worker.d.ts +11 -0
- package/dist/vite/servers/worker.js +28 -0
- package/dist/vite/servers/worker.js.map +1 -0
- package/package.json +31 -18
- package/src/cli.ts +144 -0
- package/src/config.ts +64 -0
- package/src/entrypoints/cli.ts +13 -0
- package/src/entrypoints/main.ts +200 -0
- package/src/entrypoints/thread.ts +184 -0
- package/src/entrypoints/worker.ts +48 -0
- package/src/index.ts +82 -0
- package/src/resolver.ts +16 -0
- package/src/runtime/application/api/api.ts +265 -0
- package/src/runtime/application/api/constants.ts +22 -0
- package/src/runtime/application/api/filters.ts +39 -0
- package/src/runtime/application/api/guards.ts +29 -0
- package/src/runtime/application/api/index.ts +8 -0
- package/src/runtime/application/api/middlewares.ts +37 -0
- package/src/runtime/application/api/procedure.ts +229 -0
- package/src/runtime/application/api/router.ts +193 -0
- package/src/runtime/application/api/types.ts +124 -0
- package/src/runtime/application/config.ts +69 -0
- package/src/runtime/application/constants.ts +4 -0
- package/src/runtime/application/hook.ts +51 -0
- package/src/runtime/application/hooks.ts +3 -0
- package/src/runtime/application/index.ts +5 -0
- package/src/runtime/constants.ts +13 -0
- package/src/runtime/core/hooks.ts +5 -0
- package/src/runtime/core/plugin.ts +13 -0
- package/src/runtime/core/runtime.ts +109 -0
- package/src/runtime/enums.ts +24 -0
- package/src/runtime/index.ts +21 -0
- package/src/runtime/injectables.ts +61 -0
- package/src/runtime/jobs/job.ts +370 -0
- package/src/runtime/jobs/manager.ts +348 -0
- package/src/runtime/jobs/router.ts +896 -0
- package/src/runtime/jobs/runner.ts +320 -0
- package/src/runtime/jobs/step.ts +66 -0
- package/src/runtime/jobs/ui.ts +21 -0
- package/src/runtime/pubsub/manager.ts +211 -0
- package/src/runtime/pubsub/redis.ts +108 -0
- package/src/runtime/scheduler/index.ts +39 -0
- package/src/runtime/server/applications.ts +210 -0
- package/src/runtime/server/config.ts +158 -0
- package/src/runtime/server/jobs.ts +250 -0
- package/src/runtime/server/pool.ts +260 -0
- package/src/runtime/server/proxy.ts +118 -0
- package/src/runtime/server/server.ts +155 -0
- package/src/runtime/store/index.ts +30 -0
- package/src/runtime/types.ts +93 -0
- package/src/runtime/workers/application.ts +209 -0
- package/src/runtime/workers/base.ts +68 -0
- package/src/runtime/workers/cli.ts +0 -0
- package/src/runtime/workers/job.ts +153 -0
- package/src/typings.ts +30 -0
- package/src/vite/builder.ts +122 -0
- package/src/vite/config.ts +45 -0
- package/src/vite/plugins.ts +26 -0
- package/src/vite/runners/worker.ts +57 -0
- package/src/vite/server.ts +39 -0
- package/src/vite/servers/main.ts +34 -0
- package/src/vite/servers/worker.ts +143 -0
- package/dist/_exports/application.js +0 -1
- package/dist/_exports/common.js +0 -1
- package/dist/_exports/contract.js +0 -2
- package/dist/_exports/core.js +0 -1
- package/dist/_exports/gateway.js +0 -1
- package/dist/_exports/http-transport/bun.js +0 -1
- package/dist/_exports/http-transport/deno.js +0 -1
- package/dist/_exports/http-transport/node.js +0 -1
- package/dist/_exports/http-transport.js +0 -1
- package/dist/_exports/json-format.js +0 -1
- package/dist/_exports/protocol/client.js +0 -1
- package/dist/_exports/protocol/server.js +0 -1
- package/dist/_exports/protocol.js +0 -1
- package/dist/_exports/runtime/types.js +0 -1
- package/dist/_exports/runtime.js +0 -1
- package/dist/_exports/type.js +0 -2
- package/dist/_exports/ws-transport/bun.js +0 -1
- package/dist/_exports/ws-transport/deno.js +0 -1
- package/dist/_exports/ws-transport/node.js +0 -1
- package/dist/_exports/ws-transport.js +0 -1
- package/dist/command.js +0 -30
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CoreInjectables,
|
|
3
|
+
createConsolePrettyDestination,
|
|
4
|
+
createFactoryInjectable,
|
|
5
|
+
createLazyInjectable,
|
|
6
|
+
createValueInjectable,
|
|
7
|
+
} from '@nmtjs/core'
|
|
8
|
+
import { createTransport, GatewayInjectables } from '@nmtjs/gateway'
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createContractProcedure,
|
|
12
|
+
createContractRouter,
|
|
13
|
+
createFilter,
|
|
14
|
+
createGuard,
|
|
15
|
+
createHook,
|
|
16
|
+
createJob,
|
|
17
|
+
createJobsRouter,
|
|
18
|
+
createMiddleware,
|
|
19
|
+
createPlugin,
|
|
20
|
+
createProcedure,
|
|
21
|
+
createRootRouter,
|
|
22
|
+
createRouter,
|
|
23
|
+
createStep,
|
|
24
|
+
defineApplication,
|
|
25
|
+
defineServer,
|
|
26
|
+
jobOperation,
|
|
27
|
+
RuntimeInjectables,
|
|
28
|
+
} from './runtime/index.ts'
|
|
29
|
+
|
|
30
|
+
export const neemata = {
|
|
31
|
+
app: defineApplication,
|
|
32
|
+
server: defineServer,
|
|
33
|
+
injectables: {
|
|
34
|
+
...CoreInjectables,
|
|
35
|
+
...GatewayInjectables,
|
|
36
|
+
...(RuntimeInjectables as typeof RuntimeInjectables),
|
|
37
|
+
},
|
|
38
|
+
transport: createTransport,
|
|
39
|
+
plugin: createPlugin,
|
|
40
|
+
logging: {
|
|
41
|
+
console:
|
|
42
|
+
// TODO: TSC wants it
|
|
43
|
+
createConsolePrettyDestination as typeof createConsolePrettyDestination,
|
|
44
|
+
},
|
|
45
|
+
value: createValueInjectable,
|
|
46
|
+
lazy: createLazyInjectable,
|
|
47
|
+
factory: createFactoryInjectable,
|
|
48
|
+
rootRouter: createRootRouter,
|
|
49
|
+
router: createRouter,
|
|
50
|
+
contractRouter: createContractRouter,
|
|
51
|
+
procedure: createProcedure,
|
|
52
|
+
contractProcedure: createContractProcedure,
|
|
53
|
+
middleware: createMiddleware,
|
|
54
|
+
guard: createGuard,
|
|
55
|
+
filter: createFilter,
|
|
56
|
+
job: createJob,
|
|
57
|
+
step: createStep,
|
|
58
|
+
hook: createHook,
|
|
59
|
+
jobRouter: Object.assign(createJobsRouter, { operation: jobOperation }),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { c } from '@nmtjs/contract'
|
|
63
|
+
export { Scope } from '@nmtjs/core'
|
|
64
|
+
export {
|
|
65
|
+
type ConnectionIdentityType,
|
|
66
|
+
GatewayHook,
|
|
67
|
+
ProxyableTransportType,
|
|
68
|
+
} from '@nmtjs/gateway'
|
|
69
|
+
export { ConnectionType, ErrorCode, ProtocolBlob } from '@nmtjs/protocol'
|
|
70
|
+
export { t } from '@nmtjs/type'
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
ApiError,
|
|
74
|
+
defineApplication,
|
|
75
|
+
JobWorkerPool,
|
|
76
|
+
LifecycleHook,
|
|
77
|
+
StoreType,
|
|
78
|
+
WorkerType,
|
|
79
|
+
} from './runtime/index.ts'
|
|
80
|
+
|
|
81
|
+
export { neemata as n }
|
|
82
|
+
export default neemata
|
package/src/resolver.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ResolverFactory } from 'oxc-resolver'
|
|
2
|
+
|
|
3
|
+
const fallback: Record<string, [string]> = {}
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
// oxc-resolver fails to resolve uWebSockets.js for some reason
|
|
7
|
+
const mdl = 'uWebSockets.js'
|
|
8
|
+
const path = import.meta.resolve(mdl)
|
|
9
|
+
fallback[mdl] = [path]
|
|
10
|
+
} catch {}
|
|
11
|
+
|
|
12
|
+
export const resolver = new ResolverFactory({
|
|
13
|
+
tsconfig: 'auto',
|
|
14
|
+
extensions: ['.ts', '.js', '.mjs', '.mts', '.json', '.node'],
|
|
15
|
+
fallback,
|
|
16
|
+
})
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { inspect } from 'node:util'
|
|
3
|
+
|
|
4
|
+
import type { Container, Logger } from '@nmtjs/core'
|
|
5
|
+
import type {
|
|
6
|
+
GatewayApi,
|
|
7
|
+
GatewayApiCallOptions,
|
|
8
|
+
GatewayApiCallResult,
|
|
9
|
+
GatewayConnection,
|
|
10
|
+
} from '@nmtjs/gateway'
|
|
11
|
+
import { withTimeout } from '@nmtjs/common'
|
|
12
|
+
import { IsStreamProcedureContract } from '@nmtjs/contract'
|
|
13
|
+
import { Scope } from '@nmtjs/core'
|
|
14
|
+
import { isAsyncIterable, rpcStreamAbortSignal } from '@nmtjs/gateway'
|
|
15
|
+
import { ErrorCode } from '@nmtjs/protocol'
|
|
16
|
+
import { ProtocolError } from '@nmtjs/protocol/server'
|
|
17
|
+
import { NeemataTypeError, registerDefaultLocale, type } from '@nmtjs/type'
|
|
18
|
+
import { prettifyError } from 'zod/mini'
|
|
19
|
+
|
|
20
|
+
import type { kDefaultProcedure as kDefaultProcedureKey } from './constants.ts'
|
|
21
|
+
import type { AnyFilter } from './filters.ts'
|
|
22
|
+
import type { AnyGuard } from './guards.ts'
|
|
23
|
+
import type { AnyMiddleware } from './middlewares.ts'
|
|
24
|
+
import type { AnyProcedure } from './procedure.ts'
|
|
25
|
+
import type { AnyRouter } from './router.ts'
|
|
26
|
+
import type { ApiCallContext } from './types.ts'
|
|
27
|
+
import { kDefaultProcedure } from './constants.ts'
|
|
28
|
+
|
|
29
|
+
registerDefaultLocale()
|
|
30
|
+
|
|
31
|
+
export type ApiCallOptions<T extends AnyProcedure = AnyProcedure> = Readonly<{
|
|
32
|
+
connection: GatewayConnection
|
|
33
|
+
path: AnyRouter[]
|
|
34
|
+
procedure: T
|
|
35
|
+
container: Container
|
|
36
|
+
payload: any
|
|
37
|
+
signal: AbortSignal
|
|
38
|
+
}>
|
|
39
|
+
|
|
40
|
+
export type ApiOptions = {
|
|
41
|
+
timeout?: number
|
|
42
|
+
container: Container
|
|
43
|
+
logger: Logger
|
|
44
|
+
procedures: Map<
|
|
45
|
+
string | kDefaultProcedureKey,
|
|
46
|
+
{ procedure: AnyProcedure; path: AnyRouter[] }
|
|
47
|
+
>
|
|
48
|
+
guards: Set<AnyGuard>
|
|
49
|
+
middlewares: Set<AnyMiddleware>
|
|
50
|
+
filters: Set<AnyFilter>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class ApiError extends ProtocolError {
|
|
54
|
+
toString() {
|
|
55
|
+
return `${this.code} ${this.message}: \n${inspect(this.data, true, 10, false)}`
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const NotFound = () => new ApiError(ErrorCode.NotFound, 'Procedure not found')
|
|
60
|
+
|
|
61
|
+
export class ApplicationApi implements GatewayApi {
|
|
62
|
+
constructor(public options: ApiOptions) {}
|
|
63
|
+
|
|
64
|
+
find(procedureName: string) {
|
|
65
|
+
const procedure = this.options.procedures.get(procedureName)
|
|
66
|
+
if (procedure) return procedure
|
|
67
|
+
|
|
68
|
+
const fallback = this.options.procedures.get(kDefaultProcedure)
|
|
69
|
+
if (fallback) return fallback
|
|
70
|
+
|
|
71
|
+
throw NotFound()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async call(options: GatewayApiCallOptions): Promise<GatewayApiCallResult> {
|
|
75
|
+
const { payload, container, signal, connection } = options
|
|
76
|
+
|
|
77
|
+
const { procedure, path } = this.find(options.procedure)
|
|
78
|
+
|
|
79
|
+
options.metadata?.(procedure.metadata)
|
|
80
|
+
|
|
81
|
+
const callOptions = Object.freeze({
|
|
82
|
+
payload,
|
|
83
|
+
container,
|
|
84
|
+
signal,
|
|
85
|
+
connection,
|
|
86
|
+
procedure,
|
|
87
|
+
path,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
assert(
|
|
91
|
+
container.scope === Scope.Call,
|
|
92
|
+
'Invalid container scope, expected to be Scope.Call',
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const timeout = procedure.contract.timeout ?? this.options.timeout
|
|
96
|
+
const isIterableProcedure = IsStreamProcedureContract(procedure.contract)
|
|
97
|
+
const streamTimeoutSignal = procedure.streamTimeout
|
|
98
|
+
? AbortSignal.timeout(procedure.streamTimeout)
|
|
99
|
+
: undefined
|
|
100
|
+
|
|
101
|
+
if (streamTimeoutSignal) {
|
|
102
|
+
container.provide(rpcStreamAbortSignal, streamTimeoutSignal)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const handle = await this.createProcedureHandler(callOptions)
|
|
107
|
+
const result = timeout
|
|
108
|
+
? await this.withTimeout(handle(payload), timeout)
|
|
109
|
+
: await handle(payload)
|
|
110
|
+
if (isIterableProcedure) {
|
|
111
|
+
return this.handleIterableOutput(procedure, result)
|
|
112
|
+
} else {
|
|
113
|
+
return this.handleOutput(procedure, result)
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const handled = await this.handleFilters(callOptions, error)
|
|
117
|
+
if (handled === error && error instanceof ProtocolError === false) {
|
|
118
|
+
const logError = new Error('Unhandled error', { cause: error })
|
|
119
|
+
this.options.logger.debug(logError)
|
|
120
|
+
throw new ApiError(
|
|
121
|
+
ErrorCode.InternalServerError,
|
|
122
|
+
'Internal Server Error',
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
throw handled
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private async createProcedureHandler(callOptions: ApiCallOptions) {
|
|
130
|
+
const { connection, procedure, container, path } = callOptions
|
|
131
|
+
|
|
132
|
+
const callCtx: ApiCallContext = Object.freeze({
|
|
133
|
+
connection,
|
|
134
|
+
container,
|
|
135
|
+
path,
|
|
136
|
+
procedure,
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const middlewares = await this.resolveMiddlewares(callOptions)
|
|
140
|
+
|
|
141
|
+
const handleProcedure = async (payload: any) => {
|
|
142
|
+
const middleware = middlewares.next().value
|
|
143
|
+
if (middleware) {
|
|
144
|
+
const next = (...args: any[]) =>
|
|
145
|
+
handleProcedure(args.length === 0 ? payload : args[0])
|
|
146
|
+
return middleware.handle(middleware.ctx, callCtx, next, payload)
|
|
147
|
+
} else {
|
|
148
|
+
await this.handleGuards(callOptions, callCtx)
|
|
149
|
+
const { dependencies } = procedure
|
|
150
|
+
const context = await container.createContext(dependencies)
|
|
151
|
+
const input = this.handleInput(procedure, payload)
|
|
152
|
+
const result = await procedure.handler(context, input)
|
|
153
|
+
return result
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return handleProcedure
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private async resolveMiddlewares(callOptions: ApiCallOptions) {
|
|
161
|
+
const { path, procedure, container } = callOptions
|
|
162
|
+
const middlewares = [
|
|
163
|
+
...this.options.middlewares,
|
|
164
|
+
...path.flatMap((router) => [...router.middlewares]),
|
|
165
|
+
...procedure.middlewares,
|
|
166
|
+
]
|
|
167
|
+
const result = await Promise.all(
|
|
168
|
+
middlewares.map(async (middleware) => {
|
|
169
|
+
const ctx = await container.createContext(middleware.dependencies)
|
|
170
|
+
return { handle: middleware.handle, ctx }
|
|
171
|
+
}),
|
|
172
|
+
)
|
|
173
|
+
return result[Symbol.iterator]()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private withTimeout(response: any, timeout: number): unknown {
|
|
177
|
+
const applyTimeout = response instanceof Promise && timeout > 0
|
|
178
|
+
if (!applyTimeout) return response
|
|
179
|
+
return withTimeout(
|
|
180
|
+
response,
|
|
181
|
+
timeout,
|
|
182
|
+
new ApiError(ErrorCode.RequestTimeout, 'Request Timeout'),
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private async handleGuards(
|
|
187
|
+
callOptions: ApiCallOptions,
|
|
188
|
+
callCtx: ApiCallContext,
|
|
189
|
+
) {
|
|
190
|
+
const { path, procedure, container } = callOptions
|
|
191
|
+
const guards = [
|
|
192
|
+
...this.options.guards,
|
|
193
|
+
...path.flatMap((router) => [...router.guards]),
|
|
194
|
+
...procedure.guards,
|
|
195
|
+
]
|
|
196
|
+
for (const guard of guards) {
|
|
197
|
+
const ctx = await container.createContext(guard.dependencies)
|
|
198
|
+
const result = await guard.can(ctx, callCtx)
|
|
199
|
+
if (result === false) throw new ApiError(ErrorCode.Forbidden)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private async handleFilters({ container }: ApiCallOptions, error: any) {
|
|
204
|
+
if (this.options.filters.size) {
|
|
205
|
+
for (const filter of this.options.filters) {
|
|
206
|
+
if (error instanceof filter.errorClass) {
|
|
207
|
+
const ctx = await container.createContext(filter.dependencies)
|
|
208
|
+
const handledError = await filter.catch(ctx, error)
|
|
209
|
+
if (!handledError || handledError instanceof ApiError === false)
|
|
210
|
+
continue
|
|
211
|
+
return handledError
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return error
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private handleInput(procedure: AnyProcedure, payload: any) {
|
|
219
|
+
if (procedure.contract.input instanceof type.NeverType === false) {
|
|
220
|
+
const type = procedure.contract.input
|
|
221
|
+
try {
|
|
222
|
+
return type.decode(payload)
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (error instanceof NeemataTypeError)
|
|
225
|
+
throw new ApiError(
|
|
226
|
+
ErrorCode.ValidationError,
|
|
227
|
+
`Input validation error: \n${prettifyError(error)}`,
|
|
228
|
+
error.issues,
|
|
229
|
+
)
|
|
230
|
+
throw error
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private handleIterableOutput(procedure: AnyProcedure, response: any) {
|
|
236
|
+
if (!isAsyncIterable(response))
|
|
237
|
+
throw new Error('Response is an async iterable')
|
|
238
|
+
const chunkType = procedure.contract.output
|
|
239
|
+
if (chunkType instanceof type.NeverType)
|
|
240
|
+
throw new Error('Stream procedure must have a defined output type')
|
|
241
|
+
|
|
242
|
+
return async function* (onDone?: () => void) {
|
|
243
|
+
try {
|
|
244
|
+
if (chunkType instanceof type.AnyType === false) {
|
|
245
|
+
for await (const chunk of response) {
|
|
246
|
+
const encoded = chunkType.encode(chunk)
|
|
247
|
+
yield encoded
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
yield* response
|
|
251
|
+
}
|
|
252
|
+
} finally {
|
|
253
|
+
onDone?.()
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private handleOutput(procedure: AnyProcedure, response: any) {
|
|
259
|
+
if (procedure.contract.output instanceof type.NeverType === false) {
|
|
260
|
+
const type = procedure.contract.output
|
|
261
|
+
return type.encode(response)
|
|
262
|
+
}
|
|
263
|
+
return undefined
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const kProcedure: unique symbol = Symbol.for('neemata:ProcedureKey')
|
|
2
|
+
export type kProcedure = typeof kProcedure
|
|
3
|
+
|
|
4
|
+
export const kDefaultProcedure: unique symbol = Symbol.for(
|
|
5
|
+
'neemata:DefaultProcedureKey',
|
|
6
|
+
)
|
|
7
|
+
export type kDefaultProcedure = typeof kDefaultProcedure
|
|
8
|
+
|
|
9
|
+
export const kRouter: unique symbol = Symbol.for('neemata:RouterKey')
|
|
10
|
+
export type kRouter = typeof kRouter
|
|
11
|
+
|
|
12
|
+
export const kRootRouter: unique symbol = Symbol.for('neemata:RootRouterKey')
|
|
13
|
+
export type kRootRouter = typeof kRootRouter
|
|
14
|
+
|
|
15
|
+
export const kMiddleware: unique symbol = Symbol.for('neemata:MiddlewareKey')
|
|
16
|
+
export type kMiddleware = typeof kMiddleware
|
|
17
|
+
|
|
18
|
+
export const kGuard: unique symbol = Symbol.for('neemata:GuardKey')
|
|
19
|
+
export type kGuard = typeof kGuard
|
|
20
|
+
|
|
21
|
+
export const kFilter: unique symbol = Symbol.for('neemata:FilterKey')
|
|
22
|
+
export type kFilter = typeof kFilter
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ErrorClass, MaybePromise } from '@nmtjs/common'
|
|
2
|
+
import type { Dependant, Dependencies, DependencyContext } from '@nmtjs/core'
|
|
3
|
+
|
|
4
|
+
import { kFilter } from './constants.ts'
|
|
5
|
+
|
|
6
|
+
export interface Filter<
|
|
7
|
+
FilterError extends ErrorClass = ErrorClass,
|
|
8
|
+
Deps extends Dependencies = Dependencies,
|
|
9
|
+
> extends Dependant<Deps> {
|
|
10
|
+
[kFilter]: true
|
|
11
|
+
errorClass: FilterError
|
|
12
|
+
catch: (
|
|
13
|
+
ctx: DependencyContext<Deps>,
|
|
14
|
+
error: InstanceType<FilterError>,
|
|
15
|
+
) => MaybePromise<Error>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type AnyFilter<Error extends ErrorClass = ErrorClass> = Filter<
|
|
19
|
+
Error,
|
|
20
|
+
any
|
|
21
|
+
>
|
|
22
|
+
|
|
23
|
+
export function createFilter<
|
|
24
|
+
FilterError extends ErrorClass,
|
|
25
|
+
Deps extends Dependencies = {},
|
|
26
|
+
>(params: {
|
|
27
|
+
errorClass: FilterError
|
|
28
|
+
dependencies?: Deps
|
|
29
|
+
catch: Filter<FilterError, Deps>['catch']
|
|
30
|
+
}): Filter<FilterError, Deps> {
|
|
31
|
+
const { errorClass, catch: handler, dependencies = {} as Deps } = params
|
|
32
|
+
|
|
33
|
+
return Object.freeze({
|
|
34
|
+
errorClass,
|
|
35
|
+
dependencies,
|
|
36
|
+
catch: handler,
|
|
37
|
+
[kFilter]: true,
|
|
38
|
+
}) as Filter<FilterError, Deps>
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { MaybePromise } from '@nmtjs/common'
|
|
2
|
+
import type { Dependant, Dependencies, DependencyContext } from '@nmtjs/core'
|
|
3
|
+
|
|
4
|
+
import type { ApiCallContext } from './types.ts'
|
|
5
|
+
import { kGuard } from './constants.ts'
|
|
6
|
+
|
|
7
|
+
export interface Guard<Deps extends Dependencies = Dependencies>
|
|
8
|
+
extends Dependant<Deps> {
|
|
9
|
+
[kGuard]: true
|
|
10
|
+
can: (
|
|
11
|
+
ctx: DependencyContext<Deps>,
|
|
12
|
+
call: ApiCallContext,
|
|
13
|
+
) => MaybePromise<boolean>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type AnyGuard = Guard<any>
|
|
17
|
+
|
|
18
|
+
export function createGuard<Deps extends Dependencies = {}>(
|
|
19
|
+
paramsOrHandler:
|
|
20
|
+
| { dependencies?: Deps; can: Guard<Deps>['can'] }
|
|
21
|
+
| Guard<Deps>['can'],
|
|
22
|
+
): Guard<Deps> {
|
|
23
|
+
const { dependencies = {} as Deps, can } =
|
|
24
|
+
typeof paramsOrHandler === 'function'
|
|
25
|
+
? { can: paramsOrHandler }
|
|
26
|
+
: paramsOrHandler
|
|
27
|
+
|
|
28
|
+
return Object.freeze({ dependencies, can, [kGuard]: true }) as Guard<Deps>
|
|
29
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { MaybePromise } from '@nmtjs/common'
|
|
2
|
+
import type { Dependant, Dependencies, DependencyContext } from '@nmtjs/core'
|
|
3
|
+
|
|
4
|
+
import type { ApiCallContext } from './types.ts'
|
|
5
|
+
import { kMiddleware } from './constants.ts'
|
|
6
|
+
|
|
7
|
+
export type MiddlewareNext = (payload?: any) => any
|
|
8
|
+
|
|
9
|
+
export interface Middleware<Deps extends Dependencies = Dependencies>
|
|
10
|
+
extends Dependant<Deps> {
|
|
11
|
+
[kMiddleware]: true
|
|
12
|
+
handle: (
|
|
13
|
+
ctx: DependencyContext<Deps>,
|
|
14
|
+
call: ApiCallContext,
|
|
15
|
+
next: MiddlewareNext,
|
|
16
|
+
payload: any,
|
|
17
|
+
) => MaybePromise<any>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type AnyMiddleware = Middleware<any>
|
|
21
|
+
|
|
22
|
+
export function createMiddleware<Deps extends Dependencies = {}>(
|
|
23
|
+
paramsOrHandler:
|
|
24
|
+
| { dependencies?: Deps; handle: Middleware<Deps>['handle'] }
|
|
25
|
+
| Middleware<Deps>['handle'],
|
|
26
|
+
): Middleware<Deps> {
|
|
27
|
+
const { dependencies = {} as Deps, handle } =
|
|
28
|
+
typeof paramsOrHandler === 'function'
|
|
29
|
+
? { handle: paramsOrHandler }
|
|
30
|
+
: paramsOrHandler
|
|
31
|
+
|
|
32
|
+
return Object.freeze({
|
|
33
|
+
dependencies,
|
|
34
|
+
handle,
|
|
35
|
+
[kMiddleware]: true,
|
|
36
|
+
}) as Middleware<Deps>
|
|
37
|
+
}
|