@velajs/vela 1.8.8 → 1.10.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/CHANGELOG.md +20 -0
- package/dist/__tests__/workers-als/entry-als.d.ts +9 -0
- package/dist/application.d.ts +10 -0
- package/dist/application.js +25 -0
- package/dist/cache/cache.module.d.ts +5 -7
- package/dist/cache/cache.module.js +44 -66
- package/dist/cache/cache.types.d.ts +26 -0
- package/dist/cache/cache.types.js +1 -1
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/index.js +1 -0
- package/dist/cache/tiered-cache.store.d.ts +19 -0
- package/dist/cache/tiered-cache.store.js +40 -0
- package/dist/config/config.module.d.ts +6 -5
- package/dist/config/config.module.js +46 -49
- package/dist/container/container.d.ts +33 -0
- package/dist/container/container.js +156 -7
- package/dist/container/disposable.d.ts +5 -0
- package/dist/container/disposable.js +33 -0
- package/dist/container/types.d.ts +8 -0
- package/dist/factory/bootstrap.js +10 -0
- package/dist/fetch/fetch.module.d.ts +5 -6
- package/dist/fetch/fetch.module.js +9 -42
- package/dist/http/ambient.d.ts +17 -0
- package/dist/http/ambient.js +44 -0
- package/dist/http/execution-context.js +4 -1
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.js +1 -0
- package/dist/http/route.manager.d.ts +19 -0
- package/dist/http/route.manager.js +84 -0
- package/dist/i18n/deep-merge.d.ts +2 -0
- package/dist/i18n/deep-merge.js +15 -0
- package/dist/i18n/i18n.middleware.d.ts +15 -0
- package/dist/i18n/i18n.middleware.js +94 -0
- package/dist/i18n/i18n.module.d.ts +13 -0
- package/dist/i18n/i18n.module.js +61 -0
- package/dist/i18n/i18n.options.d.ts +30 -0
- package/dist/i18n/i18n.options.js +16 -0
- package/dist/i18n/i18n.service.d.ts +20 -0
- package/dist/i18n/i18n.service.js +49 -0
- package/dist/i18n/i18n.tokens.d.ts +6 -0
- package/dist/i18n/i18n.tokens.js +3 -0
- package/dist/i18n/i18n.types.d.ts +6 -0
- package/dist/i18n/i18n.types.js +1 -0
- package/dist/i18n/index.d.ts +10 -0
- package/dist/i18n/index.js +8 -0
- package/dist/i18n/message-loader.service.d.ts +21 -0
- package/dist/i18n/message-loader.service.js +90 -0
- package/dist/i18n/message-registry.d.ts +16 -0
- package/dist/i18n/message-registry.js +49 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +6 -2
- package/dist/module/configurable-module.builder.d.ts +44 -0
- package/dist/module/configurable-module.builder.js +177 -0
- package/dist/module/configurable-module.types.d.ts +93 -0
- package/dist/module/configurable-module.types.js +5 -0
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.js +1 -0
- package/dist/openapi/document.js +20 -2
- package/dist/openapi/types.d.ts +54 -0
- package/dist/pipeline/types.d.ts +21 -4
- package/dist/registry/metadata.registry.d.ts +16 -16
- package/dist/registry/metadata.registry.js +90 -32
- package/dist/seeder/index.d.ts +5 -0
- package/dist/seeder/index.js +4 -0
- package/dist/seeder/seeder.decorator.d.ts +7 -0
- package/dist/seeder/seeder.decorator.js +15 -0
- package/dist/seeder/seeder.module.d.ts +18 -0
- package/dist/seeder/seeder.module.js +40 -0
- package/dist/seeder/seeder.registry.d.ts +23 -0
- package/dist/seeder/seeder.registry.js +83 -0
- package/dist/seeder/seeder.tokens.d.ts +2 -0
- package/dist/seeder/seeder.tokens.js +1 -0
- package/dist/seeder/seeder.types.d.ts +20 -0
- package/dist/seeder/seeder.types.js +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/path-template.d.ts +9 -0
- package/dist/storage/path-template.js +20 -0
- package/dist/storage/signed-url.d.ts +12 -0
- package/dist/storage/signed-url.js +55 -0
- package/dist/storage/storage.types.d.ts +41 -0
- package/dist/storage/storage.types.js +5 -0
- package/dist/throttler/throttler.module.d.ts +5 -8
- package/dist/throttler/throttler.module.js +27 -55
- package/dist/websocket/index.d.ts +12 -0
- package/dist/websocket/index.js +16 -0
- package/dist/websocket/websocket.decorators.d.ts +33 -0
- package/dist/websocket/websocket.decorators.js +58 -0
- package/dist/websocket/websocket.module.d.ts +18 -0
- package/dist/websocket/websocket.module.js +52 -0
- package/dist/websocket/websocket.tokens.d.ts +22 -0
- package/dist/websocket/websocket.tokens.js +20 -0
- package/dist/websocket/websocket.types.d.ts +86 -0
- package/dist/websocket/websocket.types.js +4 -0
- package/dist/websocket/ws-argument-resolver.d.ts +13 -0
- package/dist/websocket/ws-argument-resolver.js +40 -0
- package/dist/websocket/ws-dispatcher.d.ts +33 -0
- package/dist/websocket/ws-dispatcher.js +253 -0
- package/dist/websocket/ws-exception.d.ts +16 -0
- package/dist/websocket/ws-exception.js +32 -0
- package/dist/websocket/ws-execution-context.d.ts +9 -0
- package/dist/websocket/ws-execution-context.js +24 -0
- package/dist/websocket/ws-server.d.ts +31 -0
- package/dist/websocket/ws-server.js +74 -0
- package/dist/websocket/ws-sync.d.ts +47 -0
- package/dist/websocket/ws-sync.js +74 -0
- package/dist/websocket-node/index.d.ts +4 -0
- package/dist/websocket-node/index.js +5 -0
- package/dist/websocket-node/node-ws-client.d.ts +24 -0
- package/dist/websocket-node/node-ws-client.js +49 -0
- package/dist/websocket-node/redis-sync.d.ts +33 -0
- package/dist/websocket-node/redis-sync.js +56 -0
- package/dist/websocket-node/register-gateways.d.ts +20 -0
- package/dist/websocket-node/register-gateways.js +61 -0
- package/package.json +31 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { InjectionToken } from "../container/types.js";
|
|
2
|
+
import { stableHash } from "./stable-hash.js";
|
|
3
|
+
/** Default extra: `isGlobal` toggles `DynamicModule.global`, hiding the naming split. */ const DEFAULT_EXTRAS = {
|
|
4
|
+
isGlobal: false
|
|
5
|
+
};
|
|
6
|
+
const DEFAULT_TRANSFORM = (def, extras)=>extras.isGlobal ? {
|
|
7
|
+
...def,
|
|
8
|
+
global: true
|
|
9
|
+
} : def;
|
|
10
|
+
/**
|
|
11
|
+
* NestJS-parity builder that generates `forRoot`/`forRootAsync` (and `key`,
|
|
12
|
+
* `global`, factory-param inference) from a tiny spec — so a module is just its
|
|
13
|
+
* tokens + options type + service + a `@Module({...})` bag, while vela keeps its
|
|
14
|
+
* encapsulation (`exports`/visibility) and multi-instance `key` dedup.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
|
|
19
|
+
* new ConfigurableModuleBuilder<FooOptions>({ moduleName: 'Foo' }).build();
|
|
20
|
+
*
|
|
21
|
+
* @Module({
|
|
22
|
+
* providers: [FooService], // derived providers inject MODULE_OPTIONS_TOKEN
|
|
23
|
+
* exports: [FooService],
|
|
24
|
+
* })
|
|
25
|
+
* export class FooModule extends ConfigurableModuleClass {}
|
|
26
|
+
* ```
|
|
27
|
+
*/ export class ConfigurableModuleBuilder {
|
|
28
|
+
options;
|
|
29
|
+
classMethodName = 'forRoot';
|
|
30
|
+
factoryMethodName = 'create';
|
|
31
|
+
extrasDefaults = DEFAULT_EXTRAS;
|
|
32
|
+
extrasTransform = DEFAULT_TRANSFORM;
|
|
33
|
+
constructor(options = {}){
|
|
34
|
+
this.options = options;
|
|
35
|
+
}
|
|
36
|
+
/** Declare extra call-site keys (e.g. `isGlobal`) + how they reshape the definition. */ setExtras(defaults, transform) {
|
|
37
|
+
this.extrasDefaults = defaults;
|
|
38
|
+
this.extrasTransform = transform;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/** Rename the sync static (default `forRoot`); the async static becomes `<name>Async`. */ setClassMethodName(name) {
|
|
42
|
+
this.classMethodName = name;
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
/** Rename the method a `useClass`/`useExisting` options factory must implement (default `create`). */ setFactoryMethodName(name) {
|
|
46
|
+
this.factoryMethodName = name;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
build() {
|
|
50
|
+
const moduleName = this.options.moduleName ?? 'ConfigurableModule';
|
|
51
|
+
const optionsToken = this.options.optionsInjectionToken ?? new InjectionToken(`${moduleName}_MODULE_OPTIONS`);
|
|
52
|
+
const syncName = this.classMethodName;
|
|
53
|
+
const asyncName = `${this.classMethodName}Async`;
|
|
54
|
+
const factoryMethodName = this.factoryMethodName;
|
|
55
|
+
const extrasDefaults = this.extrasDefaults;
|
|
56
|
+
const transform = this.extrasTransform;
|
|
57
|
+
let ConfigurableModuleClass = class ConfigurableModuleClass {
|
|
58
|
+
};
|
|
59
|
+
Object.defineProperty(ConfigurableModuleClass, syncName, {
|
|
60
|
+
configurable: true,
|
|
61
|
+
writable: true,
|
|
62
|
+
enumerable: false,
|
|
63
|
+
value (options = {}) {
|
|
64
|
+
const { key, ...rest } = options;
|
|
65
|
+
const definition = {
|
|
66
|
+
module: this,
|
|
67
|
+
key: key ?? stableHash(rest),
|
|
68
|
+
providers: [
|
|
69
|
+
{
|
|
70
|
+
provide: optionsToken,
|
|
71
|
+
useValue: rest
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
return transform(definition, {
|
|
76
|
+
...extrasDefaults,
|
|
77
|
+
...rest
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
Object.defineProperty(ConfigurableModuleClass, asyncName, {
|
|
82
|
+
configurable: true,
|
|
83
|
+
writable: true,
|
|
84
|
+
enumerable: false,
|
|
85
|
+
value (options = {}) {
|
|
86
|
+
const { key, imports, inject, useFactory, useClass, useExisting, ...restExtras } = options;
|
|
87
|
+
const definition = {
|
|
88
|
+
module: this,
|
|
89
|
+
// Include extras (e.g. isGlobal) in the key — like forRoot — so two
|
|
90
|
+
// async instances differing only in an extra don't wrongly dedup.
|
|
91
|
+
key: key ?? stableHash({
|
|
92
|
+
inject,
|
|
93
|
+
useFactory,
|
|
94
|
+
useClass,
|
|
95
|
+
useExisting,
|
|
96
|
+
...restExtras
|
|
97
|
+
}),
|
|
98
|
+
imports: imports ?? [],
|
|
99
|
+
providers: buildAsyncOptionsProviders(optionsToken, factoryMethodName, {
|
|
100
|
+
inject,
|
|
101
|
+
useFactory,
|
|
102
|
+
useClass,
|
|
103
|
+
useExisting
|
|
104
|
+
})
|
|
105
|
+
};
|
|
106
|
+
return transform(definition, {
|
|
107
|
+
...extrasDefaults,
|
|
108
|
+
...restExtras
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
ConfigurableModuleClass: ConfigurableModuleClass,
|
|
114
|
+
MODULE_OPTIONS_TOKEN: optionsToken,
|
|
115
|
+
// Type-only sentinels — never read at runtime.
|
|
116
|
+
OPTIONS_TYPE: undefined,
|
|
117
|
+
ASYNC_OPTIONS_TYPE: undefined
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Lower `useFactory`/`useClass`/`useExisting` async options into provider registrations. */ function buildAsyncOptionsProviders(optionsToken, factoryMethodName, async) {
|
|
122
|
+
if (async.useFactory) {
|
|
123
|
+
return [
|
|
124
|
+
{
|
|
125
|
+
provide: optionsToken,
|
|
126
|
+
useFactory: async.useFactory,
|
|
127
|
+
inject: async.inject ?? []
|
|
128
|
+
}
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
if (async.useClass) {
|
|
132
|
+
const factoryClass = async.useClass;
|
|
133
|
+
return [
|
|
134
|
+
factoryClass,
|
|
135
|
+
{
|
|
136
|
+
provide: optionsToken,
|
|
137
|
+
useFactory: (instance)=>instance[factoryMethodName](),
|
|
138
|
+
inject: [
|
|
139
|
+
factoryClass
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
if (async.useExisting) {
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
provide: optionsToken,
|
|
148
|
+
useFactory: (instance)=>instance[factoryMethodName](),
|
|
149
|
+
inject: [
|
|
150
|
+
async.useExisting
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
throw new Error('Async module options require one of `useFactory`, `useClass`, or `useExisting`.');
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Lower-level engine for cases a class-mixin can't express — chiefly a
|
|
159
|
+
* runtime-generated module class whose providers depend on a call-time arg
|
|
160
|
+
* (Cloudflare binding modules). Returns an object with a single static named by
|
|
161
|
+
* `spec.methodName` (default `forRoot`).
|
|
162
|
+
*/ export function defineConfigurableModule(spec) {
|
|
163
|
+
const methodName = spec.methodName ?? 'forRoot';
|
|
164
|
+
return {
|
|
165
|
+
[methodName] (args) {
|
|
166
|
+
const definition = {
|
|
167
|
+
module: spec.module,
|
|
168
|
+
key: spec.keyFrom(args),
|
|
169
|
+
providers: spec.providers(args)
|
|
170
|
+
};
|
|
171
|
+
if (spec.imports) definition.imports = spec.imports(args);
|
|
172
|
+
if (spec.exports) definition.exports = spec.exports;
|
|
173
|
+
if (spec.global) definition.global = true;
|
|
174
|
+
return definition;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { InferTokens, InjectionToken, Token, Type } from '../container/types';
|
|
2
|
+
import type { DynamicModule, ModuleImport } from '../registry/types';
|
|
3
|
+
/**
|
|
4
|
+
* Arbitrary extra keys a module accepts alongside its options bag (e.g.
|
|
5
|
+
* `isGlobal`). Kept separate from the options type so the extras-transform can
|
|
6
|
+
* reshape the generated {@link DynamicModule} without polluting `Opts`.
|
|
7
|
+
*/
|
|
8
|
+
export type ConfigurableModuleExtras = Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Reshape the generated definition based on the resolved extras. Runs after the
|
|
11
|
+
* options provider + `key` are computed; the return value is the final
|
|
12
|
+
* `DynamicModule`. Mirrors NestJS's `extras` transform.
|
|
13
|
+
*/
|
|
14
|
+
export type ConfigurableModuleExtrasTransform<E extends ConfigurableModuleExtras> = (definition: DynamicModule, extras: E) => DynamicModule;
|
|
15
|
+
/**
|
|
16
|
+
* The contract a `useClass`/`useExisting` async-options factory must satisfy:
|
|
17
|
+
* a single method (default name `create`) returning the module options.
|
|
18
|
+
*/
|
|
19
|
+
export type ConfigurableModuleOptionsFactory<Opts, MethodName extends string> = {
|
|
20
|
+
[K in MethodName]: () => Opts | Promise<Opts>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Async configuration accepted by the generated `<method>Async` static.
|
|
24
|
+
*
|
|
25
|
+
* Superset of `AsyncModuleOptions` (`registry/types.ts`): adds NestJS's
|
|
26
|
+
* `useClass`/`useExisting` while preserving the headline `const Inject` tuple
|
|
27
|
+
* inference for `useFactory` params (no `as const` needed at the call site).
|
|
28
|
+
*/
|
|
29
|
+
export interface ConfigurableModuleAsyncOptions<Opts, MethodName extends string = 'create', Inject extends readonly Token<unknown>[] = readonly Token<unknown>[]> {
|
|
30
|
+
imports?: ModuleImport[];
|
|
31
|
+
inject?: Inject;
|
|
32
|
+
useFactory?: (...args: InferTokens<Inject>) => Opts | Promise<Opts>;
|
|
33
|
+
useClass?: Type<ConfigurableModuleOptionsFactory<Opts, MethodName>>;
|
|
34
|
+
useExisting?: Token<ConfigurableModuleOptionsFactory<Opts, MethodName>>;
|
|
35
|
+
/** Explicit instance discriminator (see {@link DynamicModule.key}). */
|
|
36
|
+
key?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ConfigurableModuleBuilderOptions {
|
|
39
|
+
/** Names the generated base class + the auto-minted options token, and feeds diagnostics. */
|
|
40
|
+
moduleName?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Reuse an existing options token instead of minting one. **Critical for
|
|
43
|
+
* migrations** so the module's public token keeps its identity.
|
|
44
|
+
*/
|
|
45
|
+
optionsInjectionToken?: InjectionToken<unknown>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The generated base class type, carrying dynamically-named `<method>` and
|
|
49
|
+
* `<method>Async` statics. A module does `class Foo extends ConfigurableModuleClass {}`
|
|
50
|
+
* and gets `Foo.forRoot(...)` / `Foo.forRootAsync(...)` for free.
|
|
51
|
+
*/
|
|
52
|
+
export type ConfigurableModuleClassType<Opts, MethodKey extends string, FactoryMethodKey extends string, Extras extends ConfigurableModuleExtras> = (new () => object) & Record<MethodKey, (options: Opts & Partial<Extras> & {
|
|
53
|
+
key?: string;
|
|
54
|
+
}) => DynamicModule> & Record<`${MethodKey}Async`, <const Inject extends readonly Token<unknown>[]>(options: ConfigurableModuleAsyncOptions<Opts, FactoryMethodKey, Inject> & Partial<Extras> & {
|
|
55
|
+
key?: string;
|
|
56
|
+
}) => DynamicModule>;
|
|
57
|
+
export interface ConfigurableModuleHost<Opts, MethodKey extends string = 'forRoot', FactoryMethodKey extends string = 'create', Extras extends ConfigurableModuleExtras = {
|
|
58
|
+
isGlobal?: boolean;
|
|
59
|
+
}> {
|
|
60
|
+
/** Base class to `extends`. */
|
|
61
|
+
ConfigurableModuleClass: ConfigurableModuleClassType<Opts, MethodKey, FactoryMethodKey, Extras>;
|
|
62
|
+
/** The options token — inject it into derived providers (`inject: [MODULE_OPTIONS_TOKEN]`). */
|
|
63
|
+
MODULE_OPTIONS_TOKEN: InjectionToken<Opts>;
|
|
64
|
+
/** Type-only helper: the shape accepted by the sync `<method>` static. */
|
|
65
|
+
OPTIONS_TYPE: Opts & Partial<Extras> & {
|
|
66
|
+
key?: string;
|
|
67
|
+
};
|
|
68
|
+
/** Type-only helper: the shape accepted by the `<method>Async` static. */
|
|
69
|
+
ASYNC_OPTIONS_TYPE: ConfigurableModuleAsyncOptions<Opts, FactoryMethodKey> & Partial<Extras> & {
|
|
70
|
+
key?: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Low-level engine spec (see `defineConfigurableModule`). Used for the cases a
|
|
75
|
+
* class-mixin can't express — notably runtime-generated module classes whose
|
|
76
|
+
* providers depend on a call-time argument (e.g. Cloudflare binding modules).
|
|
77
|
+
*/
|
|
78
|
+
export interface DefineConfigurableModuleSpec<Args> {
|
|
79
|
+
/** The module class to reference in `{ module }`. */
|
|
80
|
+
module: Type;
|
|
81
|
+
/** Static method name to generate (e.g. `forRoot`). */
|
|
82
|
+
methodName?: string;
|
|
83
|
+
/** Derive the instance `key` from the call args. */
|
|
84
|
+
keyFrom: (args: Args) => string;
|
|
85
|
+
/** Build the provider list from the call args. */
|
|
86
|
+
providers: (args: Args) => DynamicModule['providers'];
|
|
87
|
+
/** Optional exports (usually prefer declaring these on `@Module`). */
|
|
88
|
+
exports?: DynamicModule['exports'];
|
|
89
|
+
/** Optional imports. */
|
|
90
|
+
imports?: (args: Args) => DynamicModule['imports'];
|
|
91
|
+
/** Mark the produced module global. */
|
|
92
|
+
global?: boolean;
|
|
93
|
+
}
|
package/dist/module/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { Global, Module, isModule, getModuleMetadata, defineDynamicModule, } from './decorators';
|
|
2
2
|
export { stableHash } from './stable-hash';
|
|
3
|
+
export { ConfigurableModuleBuilder, defineConfigurableModule, } from './configurable-module.builder';
|
|
4
|
+
export type { ConfigurableModuleAsyncOptions, ConfigurableModuleBuilderOptions, ConfigurableModuleClassType, ConfigurableModuleExtras, ConfigurableModuleExtrasTransform, ConfigurableModuleHost, ConfigurableModuleOptionsFactory, DefineConfigurableModuleSpec, } from './configurable-module.types';
|
|
3
5
|
export { ModuleLoader } from './module-loader';
|
|
4
6
|
export { MiddlewareBuilder } from './middleware';
|
|
5
7
|
export type { MiddlewareConsumer, MiddlewareConfigProxy, MiddlewareRouteDefinition, NestModule, RouteInfo, } from './middleware';
|
package/dist/module/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Global, Module, isModule, getModuleMetadata, defineDynamicModule } from "./decorators.js";
|
|
2
2
|
export { stableHash } from "./stable-hash.js";
|
|
3
|
+
export { ConfigurableModuleBuilder, defineConfigurableModule } from "./configurable-module.builder.js";
|
|
3
4
|
export { ModuleLoader } from "./module-loader.js";
|
|
4
5
|
export { MiddlewareBuilder } from "./middleware.js";
|
package/dist/openapi/document.js
CHANGED
|
@@ -278,14 +278,32 @@ export function createOpenApiDocument(rootModule, options = {}) {
|
|
|
278
278
|
description: options.info.description
|
|
279
279
|
} : {}
|
|
280
280
|
},
|
|
281
|
+
// servers sits between info and paths (OpenAPI convention). Omitted when
|
|
282
|
+
// the caller passes none, mirroring the components/tags handling below.
|
|
283
|
+
...options.servers?.length ? {
|
|
284
|
+
servers: options.servers
|
|
285
|
+
} : {},
|
|
281
286
|
paths
|
|
282
287
|
};
|
|
288
|
+
// components.schemas (generated from DTOs) and components.securitySchemes
|
|
289
|
+
// (caller-supplied) share the same `components` object — attach it when
|
|
290
|
+
// either is present so neither clobbers the other.
|
|
283
291
|
const schemas = registry.build();
|
|
284
|
-
if (schemas) {
|
|
292
|
+
if (schemas || options.securitySchemes) {
|
|
285
293
|
document.components = {
|
|
286
|
-
schemas
|
|
294
|
+
...schemas ? {
|
|
295
|
+
schemas
|
|
296
|
+
} : {},
|
|
297
|
+
...options.securitySchemes ? {
|
|
298
|
+
securitySchemes: options.securitySchemes
|
|
299
|
+
} : {}
|
|
287
300
|
};
|
|
288
301
|
}
|
|
302
|
+
// Document-level default security requirements (each operation may override).
|
|
303
|
+
// Omitted entirely when the caller passes none.
|
|
304
|
+
if (options.security?.length) {
|
|
305
|
+
document.security = options.security;
|
|
306
|
+
}
|
|
289
307
|
// Only attach `tags` when non-empty. Emitting `tags: []` on a tag-less
|
|
290
308
|
// spec is the exact symptom the consumer reported, so omit the key
|
|
291
309
|
// entirely in that case (mirrors the `components` handling above).
|
package/dist/openapi/types.d.ts
CHANGED
|
@@ -46,6 +46,13 @@ export interface OpenApiResponse {
|
|
|
46
46
|
schema: JsonSchema;
|
|
47
47
|
}>;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* A single security requirement: maps a securityScheme name to the scopes it
|
|
51
|
+
* requires (empty array for apiKey/http schemes). An operation- or document-
|
|
52
|
+
* level array is an OR of these objects. Kept as a plain record so callers can
|
|
53
|
+
* build them inline (`{ cookieAuth: [] }`).
|
|
54
|
+
*/
|
|
55
|
+
export type OpenApiSecurityRequirement = Record<string, string[]>;
|
|
49
56
|
export interface OpenApiOperation {
|
|
50
57
|
summary?: string;
|
|
51
58
|
description?: string;
|
|
@@ -55,6 +62,35 @@ export interface OpenApiOperation {
|
|
|
55
62
|
parameters?: OpenApiParameter[];
|
|
56
63
|
requestBody?: OpenApiRequestBody;
|
|
57
64
|
responses: Record<string, OpenApiResponse>;
|
|
65
|
+
/** Per-operation security requirements (overrides the document-level array). */
|
|
66
|
+
security?: OpenApiSecurityRequirement[];
|
|
67
|
+
}
|
|
68
|
+
/** An OpenAPI Server Object. Kept loose so callers can add `variables`. */
|
|
69
|
+
export interface OpenApiServer {
|
|
70
|
+
url: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
variables?: Record<string, {
|
|
73
|
+
enum?: string[];
|
|
74
|
+
default: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
}>;
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* An OpenAPI Security Scheme Object (apiKey / http / oauth2 / openIdConnect /
|
|
81
|
+
* mutualTLS). Index signature keeps it open so any valid scheme shape passes
|
|
82
|
+
* without fighting the types (mirrors JsonSchema above).
|
|
83
|
+
*/
|
|
84
|
+
export interface OpenApiSecurityScheme {
|
|
85
|
+
type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect' | 'mutualTLS';
|
|
86
|
+
description?: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
in?: 'query' | 'header' | 'cookie';
|
|
89
|
+
scheme?: string;
|
|
90
|
+
bearerFormat?: string;
|
|
91
|
+
flows?: Record<string, unknown>;
|
|
92
|
+
openIdConnectUrl?: string;
|
|
93
|
+
[key: string]: unknown;
|
|
58
94
|
}
|
|
59
95
|
export type HttpVerb = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options' | 'head';
|
|
60
96
|
export type OpenApiPathItem = {
|
|
@@ -63,10 +99,13 @@ export type OpenApiPathItem = {
|
|
|
63
99
|
export interface OpenApiDocument {
|
|
64
100
|
openapi: '3.1.0';
|
|
65
101
|
info: OpenApiInfo;
|
|
102
|
+
servers?: OpenApiServer[];
|
|
66
103
|
paths: Record<string, OpenApiPathItem>;
|
|
67
104
|
components?: {
|
|
68
105
|
schemas?: Record<string, JsonSchema>;
|
|
106
|
+
securitySchemes?: Record<string, OpenApiSecurityScheme>;
|
|
69
107
|
};
|
|
108
|
+
security?: OpenApiSecurityRequirement[];
|
|
70
109
|
tags?: Array<{
|
|
71
110
|
name: string;
|
|
72
111
|
description?: string;
|
|
@@ -101,6 +140,21 @@ export interface CreateOpenApiDocumentOptions {
|
|
|
101
140
|
name: string;
|
|
102
141
|
description?: string;
|
|
103
142
|
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Top-level `servers` array (base URLs the API is served from). Emitted
|
|
145
|
+
* verbatim between `info` and `paths` when non-empty; omitted otherwise.
|
|
146
|
+
*/
|
|
147
|
+
servers?: OpenApiServer[];
|
|
148
|
+
/**
|
|
149
|
+
* Named security schemes, emitted under `components.securitySchemes` (merged
|
|
150
|
+
* with generated `components.schemas`). Reference them from `security`.
|
|
151
|
+
*/
|
|
152
|
+
securitySchemes?: Record<string, OpenApiSecurityScheme>;
|
|
153
|
+
/**
|
|
154
|
+
* Document-level default security requirements (applies to every operation
|
|
155
|
+
* unless the operation overrides it). Emitted verbatim when non-empty.
|
|
156
|
+
*/
|
|
157
|
+
security?: OpenApiSecurityRequirement[];
|
|
104
158
|
}
|
|
105
159
|
export type OpenApiUi = 'swagger' | 'scalar' | 'redoc';
|
|
106
160
|
export interface MountOpenApiOptions {
|
package/dist/pipeline/types.d.ts
CHANGED
|
@@ -11,16 +11,33 @@ export interface HttpArgumentsHost {
|
|
|
11
11
|
getRequest<T = Request>(): T;
|
|
12
12
|
getResponse<T = Context>(): T;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* WebSocket-specific arguments host returned by `ExecutionContext.switchToWs()`.
|
|
16
|
+
* Populated by `@velajs/vela/websocket` when a gateway message is dispatched.
|
|
17
|
+
*
|
|
18
|
+
* - `getClient()` — the connected socket (`WsClient`)
|
|
19
|
+
* - `getData()` — the inbound message payload (the envelope's `data`)
|
|
20
|
+
* - `getPattern()` — the subscribed event name that matched
|
|
21
|
+
*/
|
|
22
|
+
export interface WsArgumentsHost {
|
|
23
|
+
getClient<T = unknown>(): T;
|
|
24
|
+
getData<T = unknown>(): T;
|
|
25
|
+
getPattern<T = string>(): T;
|
|
26
|
+
}
|
|
27
|
+
/** The transport a component is executing under. `'http'` for routes, `'ws'` for gateway messages. */
|
|
28
|
+
export type ContextType = 'http' | 'ws';
|
|
14
29
|
export interface ExecutionContext {
|
|
15
|
-
getType<T extends string =
|
|
30
|
+
getType<T extends string = ContextType>(): T;
|
|
16
31
|
getClass(): Type;
|
|
17
32
|
getHandler(): string | symbol;
|
|
18
|
-
/** Returns the Hono `Context` directly. */
|
|
33
|
+
/** Returns the Hono `Context` directly. Throws on a WebSocket context. */
|
|
19
34
|
getContext<T = Context>(): T;
|
|
20
|
-
/** Shorthand for `switchToHttp().getRequest()` — returns the Web `Request`. */
|
|
35
|
+
/** Shorthand for `switchToHttp().getRequest()` — returns the Web `Request`. Throws on a WebSocket context. */
|
|
21
36
|
getRequest(): Request;
|
|
22
|
-
/** Switch to the HTTP arguments host
|
|
37
|
+
/** Switch to the HTTP arguments host. Throws on a WebSocket context. */
|
|
23
38
|
switchToHttp(): HttpArgumentsHost;
|
|
39
|
+
/** Switch to the WebSocket arguments host. Throws on an HTTP context. */
|
|
40
|
+
switchToWs(): WsArgumentsHost;
|
|
24
41
|
}
|
|
25
42
|
export interface CanActivate {
|
|
26
43
|
canActivate(context: ExecutionContext): boolean | Promise<boolean>;
|
|
@@ -5,22 +5,22 @@ export interface ControllerOptions {
|
|
|
5
5
|
version?: number | number[];
|
|
6
6
|
}
|
|
7
7
|
export declare class MetadataRegistry {
|
|
8
|
-
private static
|
|
9
|
-
private static
|
|
10
|
-
private static
|
|
11
|
-
private static
|
|
12
|
-
private static
|
|
13
|
-
private static
|
|
14
|
-
private static
|
|
15
|
-
private static
|
|
16
|
-
private static
|
|
17
|
-
private static
|
|
18
|
-
private static
|
|
19
|
-
private static
|
|
20
|
-
private static
|
|
21
|
-
private static
|
|
22
|
-
private static
|
|
23
|
-
private static globalComponents;
|
|
8
|
+
private static get routes();
|
|
9
|
+
private static get controllers();
|
|
10
|
+
private static get controllerOptions();
|
|
11
|
+
private static get modules();
|
|
12
|
+
private static get parameters();
|
|
13
|
+
private static get injectables();
|
|
14
|
+
private static get scopes();
|
|
15
|
+
private static get injectTokens();
|
|
16
|
+
private static get handlerHttpMeta();
|
|
17
|
+
private static get catchTypes();
|
|
18
|
+
private static get routeVersions();
|
|
19
|
+
private static get classMeta();
|
|
20
|
+
private static get handlerMeta();
|
|
21
|
+
private static get controllerComponents();
|
|
22
|
+
private static get handlerComponents();
|
|
23
|
+
private static get globalComponents();
|
|
24
24
|
static getRoutes(controller: Constructor): RouteDefinition[];
|
|
25
25
|
static addRoute(controller: Constructor, route: RouteDefinition): void;
|
|
26
26
|
static getControllerPath(controller: Constructor): string;
|
|
@@ -17,37 +17,95 @@ function emptyComponentByOwner() {
|
|
|
17
17
|
filter: new Map()
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
guard: new Map(),
|
|
45
|
-
pipe: new Map(),
|
|
46
|
-
interceptor: new Map(),
|
|
47
|
-
filter: new Map()
|
|
20
|
+
function createRegistryState() {
|
|
21
|
+
return {
|
|
22
|
+
routes: new Map(),
|
|
23
|
+
controllers: new Map(),
|
|
24
|
+
controllerOptions: new Map(),
|
|
25
|
+
modules: new Map(),
|
|
26
|
+
parameters: new Map(),
|
|
27
|
+
injectables: new Set(),
|
|
28
|
+
scopes: new Map(),
|
|
29
|
+
injectTokens: new Map(),
|
|
30
|
+
handlerHttpMeta: new Map(),
|
|
31
|
+
catchTypes: new Map(),
|
|
32
|
+
routeVersions: new Map(),
|
|
33
|
+
classMeta: new Map(),
|
|
34
|
+
handlerMeta: new Map(),
|
|
35
|
+
controllerComponents: emptyComponentByOwner(),
|
|
36
|
+
handlerComponents: {
|
|
37
|
+
middleware: new Map(),
|
|
38
|
+
guard: new Map(),
|
|
39
|
+
pipe: new Map(),
|
|
40
|
+
interceptor: new Map(),
|
|
41
|
+
filter: new Map()
|
|
42
|
+
},
|
|
43
|
+
globalComponents: emptyComponentStore()
|
|
48
44
|
};
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
}
|
|
46
|
+
// HMR-safe: anchor ALL backing state on `globalThis` so a Vite dev re-eval of
|
|
47
|
+
// this module reuses the SAME maps that classes were already decorated against.
|
|
48
|
+
// Without this, re-eval creates fresh empty statics → split-brain (lost routes,
|
|
49
|
+
// spurious "not @Injectable" warnings, duplicated global components). The
|
|
50
|
+
// versioned symbol avoids collisions across framework major versions in one
|
|
51
|
+
// process. `globalThis` + `Symbol.for` exist on every target runtime; no node:*.
|
|
52
|
+
const REGISTRY_STATE_KEY = Symbol.for('vela:registry:v1');
|
|
53
|
+
function registryState() {
|
|
54
|
+
const g = globalThis;
|
|
55
|
+
return g[REGISTRY_STATE_KEY] ??= createRegistryState();
|
|
56
|
+
}
|
|
57
|
+
export class MetadataRegistry {
|
|
58
|
+
// Every field is a getter over the globalThis-anchored state (registryState).
|
|
59
|
+
// Method bodies keep using `this.<field>`; the getter returns the live map so
|
|
60
|
+
// `.set`/`.get`/`.clear` mutate the shared state.
|
|
61
|
+
static get routes() {
|
|
62
|
+
return registryState().routes;
|
|
63
|
+
}
|
|
64
|
+
static get controllers() {
|
|
65
|
+
return registryState().controllers;
|
|
66
|
+
}
|
|
67
|
+
static get controllerOptions() {
|
|
68
|
+
return registryState().controllerOptions;
|
|
69
|
+
}
|
|
70
|
+
static get modules() {
|
|
71
|
+
return registryState().modules;
|
|
72
|
+
}
|
|
73
|
+
static get parameters() {
|
|
74
|
+
return registryState().parameters;
|
|
75
|
+
}
|
|
76
|
+
static get injectables() {
|
|
77
|
+
return registryState().injectables;
|
|
78
|
+
}
|
|
79
|
+
static get scopes() {
|
|
80
|
+
return registryState().scopes;
|
|
81
|
+
}
|
|
82
|
+
static get injectTokens() {
|
|
83
|
+
return registryState().injectTokens;
|
|
84
|
+
}
|
|
85
|
+
static get handlerHttpMeta() {
|
|
86
|
+
return registryState().handlerHttpMeta;
|
|
87
|
+
}
|
|
88
|
+
static get catchTypes() {
|
|
89
|
+
return registryState().catchTypes;
|
|
90
|
+
}
|
|
91
|
+
static get routeVersions() {
|
|
92
|
+
return registryState().routeVersions;
|
|
93
|
+
}
|
|
94
|
+
static get classMeta() {
|
|
95
|
+
return registryState().classMeta;
|
|
96
|
+
}
|
|
97
|
+
static get handlerMeta() {
|
|
98
|
+
return registryState().handlerMeta;
|
|
99
|
+
}
|
|
100
|
+
static get controllerComponents() {
|
|
101
|
+
return registryState().controllerComponents;
|
|
102
|
+
}
|
|
103
|
+
static get handlerComponents() {
|
|
104
|
+
return registryState().handlerComponents;
|
|
105
|
+
}
|
|
106
|
+
static get globalComponents() {
|
|
107
|
+
return registryState().globalComponents;
|
|
108
|
+
}
|
|
51
109
|
// Routes
|
|
52
110
|
static getRoutes(controller) {
|
|
53
111
|
return this.routes.get(controller) ?? [];
|
|
@@ -237,7 +295,7 @@ export class MetadataRegistry {
|
|
|
237
295
|
// Clear app-time state. Decoration metadata persists — once a class is
|
|
238
296
|
// decorated, that fact is permanent for the lifetime of the process.
|
|
239
297
|
static clear() {
|
|
240
|
-
|
|
298
|
+
registryState().globalComponents = emptyComponentStore();
|
|
241
299
|
}
|
|
242
300
|
// Full reset, including decoration metadata. Used in framework-internal scenarios.
|
|
243
301
|
static reset() {
|
|
@@ -264,6 +322,6 @@ export class MetadataRegistry {
|
|
|
264
322
|
this.controllerComponents[type].clear();
|
|
265
323
|
this.handlerComponents[type].clear();
|
|
266
324
|
}
|
|
267
|
-
|
|
325
|
+
registryState().globalComponents = emptyComponentStore();
|
|
268
326
|
}
|
|
269
327
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Seeder } from './seeder.decorator';
|
|
2
|
+
export { SeederRegistry } from './seeder.registry';
|
|
3
|
+
export { SeederModule, runSeeders } from './seeder.module';
|
|
4
|
+
export { SEEDER_METADATA } from './seeder.tokens';
|
|
5
|
+
export type { Seeder as ISeeder, SeederMetadata, RegisteredSeeder, SeederResult, } from './seeder.types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SeederMetadata } from './seeder.types';
|
|
2
|
+
/**
|
|
3
|
+
* Mark a class as a seeder. Also marks it `@Injectable()` (singleton) so it only
|
|
4
|
+
* needs to be listed in a module's providers (or `SeederModule.forRoot({ seeders })`)
|
|
5
|
+
* to be discovered by {@link SeederRegistry} at bootstrap.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Seeder(options?: SeederMetadata): ClassDecorator;
|