@fluojs/runtime 1.0.0-beta.1 → 1.0.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.
Files changed (52) hide show
  1. package/README.ko.md +39 -3
  2. package/README.md +39 -3
  3. package/dist/adapters/request-response-factory.d.ts +9 -0
  4. package/dist/adapters/request-response-factory.d.ts.map +1 -1
  5. package/dist/adapters/request-response-factory.js +14 -0
  6. package/dist/bootstrap.d.ts.map +1 -1
  7. package/dist/bootstrap.js +327 -60
  8. package/dist/health/diagnostics.d.ts +38 -0
  9. package/dist/health/diagnostics.d.ts.map +1 -1
  10. package/dist/health/diagnostics.js +48 -0
  11. package/dist/health/health.d.ts +21 -0
  12. package/dist/health/health.d.ts.map +1 -1
  13. package/dist/health/health.js +27 -0
  14. package/dist/index.d.ts +2 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/logging/json-logger.d.ts +5 -0
  18. package/dist/logging/json-logger.d.ts.map +1 -1
  19. package/dist/logging/json-logger.js +6 -0
  20. package/dist/logging/logger.d.ts +26 -1
  21. package/dist/logging/logger.d.ts.map +1 -1
  22. package/dist/logging/logger.js +54 -5
  23. package/dist/module-graph.d.ts +16 -0
  24. package/dist/module-graph.d.ts.map +1 -1
  25. package/dist/module-graph.js +304 -8
  26. package/dist/node/internal-node-compression.d.ts +15 -0
  27. package/dist/node/internal-node-compression.d.ts.map +1 -1
  28. package/dist/node/internal-node-compression.js +16 -0
  29. package/dist/node/internal-node-request.d.ts +128 -0
  30. package/dist/node/internal-node-request.d.ts.map +1 -1
  31. package/dist/node/internal-node-request.js +321 -40
  32. package/dist/node/internal-node-response.d.ts +21 -1
  33. package/dist/node/internal-node-response.d.ts.map +1 -1
  34. package/dist/node/internal-node-response.js +42 -3
  35. package/dist/node/internal-node.d.ts +43 -6
  36. package/dist/node/internal-node.d.ts.map +1 -1
  37. package/dist/node/internal-node.js +65 -9
  38. package/dist/node/node-request.d.ts +1 -1
  39. package/dist/node/node-request.d.ts.map +1 -1
  40. package/dist/node/node-request.js +1 -1
  41. package/dist/platform-shell.d.ts +4 -0
  42. package/dist/platform-shell.d.ts.map +1 -1
  43. package/dist/platform-shell.js +72 -20
  44. package/dist/request-transaction.d.ts +28 -0
  45. package/dist/request-transaction.d.ts.map +1 -1
  46. package/dist/request-transaction.js +33 -0
  47. package/dist/types.d.ts +29 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/web.d.ts +9 -1
  50. package/dist/web.d.ts.map +1 -1
  51. package/dist/web.js +207 -56
  52. package/package.json +6 -6
@@ -1,4 +1,4 @@
1
- import { getClassDiMetadata, getModuleMetadata, getOwnClassDiMetadata } from '@fluojs/core/internal';
1
+ import { getClassDiMetadata, getClassDiMetadataVersion, getModuleMetadata, getModuleMetadataVersion, getOwnClassDiMetadata } from '@fluojs/core/internal';
2
2
  import { ModuleGraphError, ModuleInjectionMetadataError, ModuleVisibilityError } from './errors.js';
3
3
  /**
4
4
  * Returns the public token represented by a provider declaration.
@@ -12,6 +12,280 @@ export function providerToken(provider) {
12
12
  }
13
13
  return provider.provide;
14
14
  }
15
+ const objectTokenIds = new WeakMap();
16
+ const symbolTokenIds = new Map();
17
+ let nextTokenId = 0;
18
+ const MODULE_GRAPH_COMPILE_ALGORITHM_VERSION = 1;
19
+ const moduleGraphCompileCache = new Map();
20
+
21
+ /** Clears the process-local module graph compile cache for isolated regression tests. */
22
+ export function clearModuleGraphCompileCacheForTesting() {
23
+ moduleGraphCompileCache.clear();
24
+ }
25
+
26
+ /**
27
+ * Reads the current process-local module graph compile cache size for tests.
28
+ *
29
+ * @returns Number of successful compile snapshots currently retained in the cache.
30
+ */
31
+ export function getModuleGraphCompileCacheSizeForTesting() {
32
+ return moduleGraphCompileCache.size;
33
+ }
34
+ function getFunctionTokenId(token) {
35
+ const existing = objectTokenIds.get(token);
36
+ if (existing !== undefined) {
37
+ return existing;
38
+ }
39
+ nextTokenId += 1;
40
+ objectTokenIds.set(token, nextTokenId);
41
+ return nextTokenId;
42
+ }
43
+ function getSymbolTokenId(token) {
44
+ const existing = symbolTokenIds.get(token);
45
+ if (existing !== undefined) {
46
+ return existing;
47
+ }
48
+ nextTokenId += 1;
49
+ symbolTokenIds.set(token, nextTokenId);
50
+ return nextTokenId;
51
+ }
52
+ function describeTokenForCacheKey(token) {
53
+ if (typeof token === 'function') {
54
+ return `fn:${getFunctionTokenId(token)}`;
55
+ }
56
+ if (typeof token === 'symbol') {
57
+ return `sym:${getSymbolTokenId(token)}`;
58
+ }
59
+ return `str:${JSON.stringify(token)}`;
60
+ }
61
+ function describeInjectionTokenForCacheKey(token) {
62
+ if (isForwardRef(token)) {
63
+ return `forward:${describeTokenForCacheKey(token.forwardRef())}`;
64
+ }
65
+ if (isOptionalToken(token)) {
66
+ return `optional:${describeTokenForCacheKey(token.token)}`;
67
+ }
68
+ return describeTokenForCacheKey(token);
69
+ }
70
+ function describeProviderForCacheKey(provider) {
71
+ if (typeof provider === 'function') {
72
+ return `class:${describeTokenForCacheKey(provider)}`;
73
+ }
74
+ const provide = describeTokenForCacheKey(provider.provide);
75
+ const multi = 'multi' in provider && provider.multi === true ? 'multi' : 'single';
76
+ if ('useClass' in provider) {
77
+ const inject = provider.inject?.map(describeInjectionTokenForCacheKey).join(',') ?? '';
78
+ return `useClass:${provide}:${describeTokenForCacheKey(provider.useClass)}:${provider.scope ?? ''}:${multi}:${inject}`;
79
+ }
80
+ if ('useFactory' in provider) {
81
+ const inject = provider.inject?.map(describeInjectionTokenForCacheKey).join(',') ?? '';
82
+ const resolverClass = provider.resolverClass ? describeTokenForCacheKey(provider.resolverClass) : '';
83
+ return `useFactory:${provide}:${getFunctionTokenId(provider.useFactory)}:${resolverClass}:${provider.scope ?? ''}:${multi}:${inject}`;
84
+ }
85
+ if ('useExisting' in provider) {
86
+ return `useExisting:${provide}:${describeTokenForCacheKey(provider.useExisting)}`;
87
+ }
88
+ return `useValue:${provide}:${multi}`;
89
+ }
90
+
91
+ /**
92
+ * Builds the key used for opt-in module graph compile caching.
93
+ *
94
+ * @param rootModule Root module that would be compiled.
95
+ * @param options Bootstrap options that influence graph validation.
96
+ * @returns Process-local key that changes when metadata or runtime validation inputs change.
97
+ */
98
+ export function createModuleGraphCacheKey(rootModule, options = {}) {
99
+ const runtimeProviders = (options.providers ?? []).map(describeProviderForCacheKey).join('|');
100
+ const validationTokens = (options.validationTokens ?? []).map(describeTokenForCacheKey).join('|');
101
+ return [`root:${describeTokenForCacheKey(rootModule)}`, `module:${getModuleMetadataVersion()}`, `class-di:${getClassDiMetadataVersion()}`, `algorithm:${MODULE_GRAPH_COMPILE_ALGORITHM_VERSION}`, `runtime:${runtimeProviders}`, `validation:${validationTokens}`].join(';');
102
+ }
103
+ function cloneModuleDefinition(definition) {
104
+ return {
105
+ global: definition.global,
106
+ imports: definition.imports ? [...definition.imports] : undefined,
107
+ providers: definition.providers ? definition.providers.map(provider => cloneProvider(provider)) : undefined,
108
+ controllers: definition.controllers ? [...definition.controllers] : undefined,
109
+ exports: definition.exports ? [...definition.exports] : undefined,
110
+ middleware: definition.middleware ? definition.middleware.map(middleware => cloneMutableValue(middleware)) : undefined
111
+ };
112
+ }
113
+ function cloneMutableValue(value, clones = new WeakMap()) {
114
+ if (typeof value !== 'object' || value === null) {
115
+ return value;
116
+ }
117
+ const existing = clones.get(value);
118
+ if (existing !== undefined) {
119
+ return existing;
120
+ }
121
+ if (value instanceof Date) {
122
+ return new Date(value);
123
+ }
124
+ if (value instanceof RegExp) {
125
+ return new RegExp(value);
126
+ }
127
+ if (Array.isArray(value)) {
128
+ const clonedArray = [];
129
+ clones.set(value, clonedArray);
130
+ for (const item of value) {
131
+ clonedArray.push(cloneMutableValue(item, clones));
132
+ }
133
+ return clonedArray;
134
+ }
135
+ if (value instanceof Map) {
136
+ const clonedMap = new Map();
137
+ clones.set(value, clonedMap);
138
+ for (const [key, entryValue] of value) {
139
+ clonedMap.set(cloneMutableValue(key, clones), cloneMutableValue(entryValue, clones));
140
+ }
141
+ return clonedMap;
142
+ }
143
+ if (value instanceof Set) {
144
+ const clonedSet = new Set();
145
+ clones.set(value, clonedSet);
146
+ for (const entryValue of value) {
147
+ clonedSet.add(cloneMutableValue(entryValue, clones));
148
+ }
149
+ return clonedSet;
150
+ }
151
+ const source = value;
152
+ const prototype = Object.getPrototypeOf(value);
153
+ const clonedObject = Object.create(prototype);
154
+ clones.set(value, clonedObject);
155
+ for (const key of Reflect.ownKeys(source)) {
156
+ clonedObject[key] = cloneMutableValue(source[key], clones);
157
+ }
158
+ return clonedObject;
159
+ }
160
+ function cloneInjectionToken(token) {
161
+ if (isForwardRef(token)) {
162
+ return {
163
+ __forwardRef__: true,
164
+ forwardRef: token.forwardRef
165
+ };
166
+ }
167
+ if (isOptionalToken(token)) {
168
+ return {
169
+ __optional__: true,
170
+ token: token.token
171
+ };
172
+ }
173
+ return token;
174
+ }
175
+ function cloneProvider(provider) {
176
+ if (typeof provider === 'function') {
177
+ return provider;
178
+ }
179
+ if ('useClass' in provider) {
180
+ return {
181
+ ...provider,
182
+ ...(provider.inject ? {
183
+ inject: provider.inject.map(token => cloneInjectionToken(token))
184
+ } : {})
185
+ };
186
+ }
187
+ if ('useFactory' in provider) {
188
+ return {
189
+ ...provider,
190
+ ...(provider.inject ? {
191
+ inject: provider.inject.map(token => cloneInjectionToken(token))
192
+ } : {})
193
+ };
194
+ }
195
+ if ('useValue' in provider) {
196
+ return {
197
+ ...provider,
198
+ useValue: cloneMutableValue(provider.useValue)
199
+ };
200
+ }
201
+ return {
202
+ ...provider
203
+ };
204
+ }
205
+ function cloneCompiledModule(compiledModule) {
206
+ return {
207
+ type: compiledModule.type,
208
+ definition: cloneModuleDefinition(compiledModule.definition),
209
+ accessibleTokens: new Set(compiledModule.accessibleTokens),
210
+ exportedTokens: new Set(compiledModule.exportedTokens),
211
+ importedExportedTokens: new Set(compiledModule.importedExportedTokens),
212
+ providerTokens: new Set(compiledModule.providerTokens)
213
+ };
214
+ }
215
+ function cloneCompiledModules(modules) {
216
+ return modules.map(compiledModule => cloneCompiledModule(compiledModule));
217
+ }
218
+ function freezeInjectionToken(token) {
219
+ if (isForwardRef(token) || isOptionalToken(token)) {
220
+ Object.freeze(token);
221
+ }
222
+ return token;
223
+ }
224
+ function freezeMutableValue(value, frozen = new WeakSet()) {
225
+ if (typeof value !== 'object' || value === null || frozen.has(value)) {
226
+ return value;
227
+ }
228
+ frozen.add(value);
229
+ if (value instanceof Map) {
230
+ for (const [key, entryValue] of value) {
231
+ freezeMutableValue(key, frozen);
232
+ freezeMutableValue(entryValue, frozen);
233
+ }
234
+ } else if (value instanceof Set) {
235
+ for (const entryValue of value) {
236
+ freezeMutableValue(entryValue, frozen);
237
+ }
238
+ } else {
239
+ const source = value;
240
+ for (const key of Reflect.ownKeys(source)) {
241
+ freezeMutableValue(source[key], frozen);
242
+ }
243
+ }
244
+ Object.freeze(value);
245
+ return value;
246
+ }
247
+ function freezeProvider(provider) {
248
+ if (typeof provider === 'function') {
249
+ return provider;
250
+ }
251
+ if ('inject' in provider && provider.inject) {
252
+ for (const token of provider.inject) {
253
+ freezeInjectionToken(token);
254
+ }
255
+ Object.freeze(provider.inject);
256
+ }
257
+ if ('useValue' in provider) {
258
+ freezeMutableValue(provider.useValue);
259
+ }
260
+ return Object.freeze(provider);
261
+ }
262
+ function freezeMiddleware(middleware) {
263
+ if (typeof middleware === 'object' && middleware !== null) {
264
+ freezeMutableValue(middleware);
265
+ }
266
+ return middleware;
267
+ }
268
+ function freezeModuleDefinition(definition) {
269
+ definition.imports && Object.freeze(definition.imports);
270
+ for (const provider of definition.providers ?? []) {
271
+ freezeProvider(provider);
272
+ }
273
+ definition.providers && Object.freeze(definition.providers);
274
+ definition.controllers && Object.freeze(definition.controllers);
275
+ definition.exports && Object.freeze(definition.exports);
276
+ for (const middleware of definition.middleware ?? []) {
277
+ freezeMiddleware(middleware);
278
+ }
279
+ definition.middleware && Object.freeze(definition.middleware);
280
+ return Object.freeze(definition);
281
+ }
282
+ function freezeCompiledModule(compiledModule) {
283
+ freezeModuleDefinition(compiledModule.definition);
284
+ return Object.freeze(compiledModule);
285
+ }
286
+ function createModuleGraphCacheSnapshot(modules) {
287
+ return Object.freeze(cloneCompiledModules(modules).map(compiledModule => freezeCompiledModule(compiledModule)));
288
+ }
15
289
  function getEffectiveClassDiMetadata(target) {
16
290
  const metadata = getClassDiMetadata(target);
17
291
  if (!metadata) {
@@ -132,7 +406,9 @@ function compileModule(moduleType, runtimeProviderTokens, compiled = new Map(),
132
406
  const compiledModule = {
133
407
  type: moduleType,
134
408
  definition,
409
+ accessibleTokens: new Set(),
135
410
  exportedTokens: new Set(),
411
+ importedExportedTokens: new Set(),
136
412
  providerTokens
137
413
  };
138
414
  compiled.set(moduleType, compiledModule);
@@ -154,11 +430,21 @@ function resolveImportedModules(compiledModule, compiledByType) {
154
430
  });
155
431
  }
156
432
  function createImportedExportedTokenSet(importedModules) {
157
- return new Set(importedModules.flatMap(imported => Array.from(imported.exportedTokens)));
433
+ const importedExportedTokens = new Set();
434
+ for (const importedModule of importedModules) {
435
+ for (const token of importedModule.exportedTokens) {
436
+ importedExportedTokens.add(token);
437
+ }
438
+ }
439
+ return importedExportedTokens;
158
440
  }
159
441
  function createAccessibleTokenSet(runtimeProviderTokens, moduleProviderTokens, importedExportedTokens, globalExportedTokens) {
160
442
  return new Set([...runtimeProviderTokens, ...moduleProviderTokens, ...importedExportedTokens, ...globalExportedTokens]);
161
443
  }
444
+ function memoizeAccessibleTokenSet(compiledModule, importedModules, runtimeProviderTokens, globalExportedTokens) {
445
+ compiledModule.importedExportedTokens = createImportedExportedTokenSet(importedModules);
446
+ compiledModule.accessibleTokens = createAccessibleTokenSet(runtimeProviderTokens, compiledModule.providerTokens, compiledModule.importedExportedTokens, globalExportedTokens);
447
+ }
162
448
  function validateProviderVisibility(compiledModule, scope, accessibleTokens) {
163
449
  for (const provider of compiledModule.definition.providers ?? []) {
164
450
  validateProviderInjectionMetadata(provider, scope);
@@ -222,12 +508,10 @@ function validateCompiledModules(modules, runtimeProviders, runtimeProviderToken
222
508
  }
223
509
  for (const compiledModule of modules) {
224
510
  const scope = `module ${compiledModule.type.name}`;
225
- const importedModules = resolveImportedModules(compiledModule, compiledByType);
226
- const importedExportedTokens = createImportedExportedTokenSet(importedModules);
227
- const accessibleTokens = createAccessibleTokenSet(runtimeProviderTokens, compiledModule.providerTokens, importedExportedTokens, globalExportedTokens);
228
- validateProviderVisibility(compiledModule, scope, accessibleTokens);
229
- validateControllerVisibility(compiledModule, scope, accessibleTokens);
230
- compiledModule.exportedTokens = createExportedTokenSet(compiledModule, importedExportedTokens);
511
+ memoizeAccessibleTokenSet(compiledModule, resolveImportedModules(compiledModule, compiledByType), runtimeProviderTokens, globalExportedTokens);
512
+ validateProviderVisibility(compiledModule, scope, compiledModule.accessibleTokens);
513
+ validateControllerVisibility(compiledModule, scope, compiledModule.accessibleTokens);
514
+ compiledModule.exportedTokens = createExportedTokenSet(compiledModule, compiledModule.importedExportedTokens);
231
515
  }
232
516
  }
233
517
 
@@ -239,10 +523,22 @@ function validateCompiledModules(modules, runtimeProviders, runtimeProviderToken
239
523
  * @returns Compiled modules in dependency order after visibility and injection validation succeed.
240
524
  */
241
525
  export function compileModuleGraph(rootModule, options = {}) {
526
+ const cacheKey = options.moduleGraphCache === true ? createModuleGraphCacheKey(rootModule, options) : undefined;
527
+ if (cacheKey !== undefined) {
528
+ const cachedModules = moduleGraphCompileCache.get(cacheKey);
529
+ if (cachedModules !== undefined) {
530
+ return cloneCompiledModules(cachedModules);
531
+ }
532
+ }
242
533
  const ordered = [];
243
534
  const runtimeProviders = options.providers ?? [];
244
535
  const runtimeProviderTokens = mergeRuntimeTokenSets(runtimeProviders, options.validationTokens ?? []);
245
536
  compileModule(rootModule, runtimeProviderTokens, new Map(), new Set(), ordered);
246
537
  validateCompiledModules(ordered, runtimeProviders, runtimeProviderTokens);
538
+ if (cacheKey !== undefined) {
539
+ const cacheSnapshot = createModuleGraphCacheSnapshot(ordered);
540
+ moduleGraphCompileCache.set(cacheKey, cacheSnapshot);
541
+ return cloneCompiledModules(cacheSnapshot);
542
+ }
247
543
  return ordered;
248
544
  }
@@ -1,7 +1,22 @@
1
1
  import type { ServerResponse } from 'node:http';
2
2
  import type { FrameworkResponseCompression } from '@fluojs/http';
3
3
  type Encoding = 'br' | 'gzip' | 'identity';
4
+ /**
5
+ * Create node response compression.
6
+ *
7
+ * @param response The response.
8
+ * @param acceptEncoding The accept encoding.
9
+ * @returns The create node response compression result.
10
+ */
4
11
  export declare function createNodeResponseCompression(response: ServerResponse, acceptEncoding: string | undefined): FrameworkResponseCompression | undefined;
12
+ /**
13
+ * Compress node response.
14
+ *
15
+ * @param response The response.
16
+ * @param body The body.
17
+ * @param encoding The encoding.
18
+ * @returns The compress node response result.
19
+ */
5
20
  export declare function compressNodeResponse(response: ServerResponse, body: Uint8Array, encoding: Exclude<Encoding, 'identity'>): Promise<void>;
6
21
  export {};
7
22
  //# sourceMappingURL=internal-node-compression.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal-node-compression.d.ts","sourceRoot":"","sources":["../../src/node/internal-node-compression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,EACV,4BAA4B,EAE7B,MAAM,cAAc,CAAC;AAiBtB,KAAK,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAE3C,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,cAAc,EACxB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,4BAA4B,GAAG,SAAS,CAqB1C;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf"}
1
+ {"version":3,"file":"internal-node-compression.d.ts","sourceRoot":"","sources":["../../src/node/internal-node-compression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,EACV,4BAA4B,EAE7B,MAAM,cAAc,CAAC;AAiBtB,KAAK,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,cAAc,EACxB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,4BAA4B,GAAG,SAAS,CAqB1C;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -1,6 +1,13 @@
1
1
  import { createBrotliCompress, createGzip } from 'node:zlib';
2
2
  const COMPRESS_THRESHOLD = 1024;
3
3
  const SKIP_CONTENT_TYPES = new Set(['image/', 'audio/', 'video/', 'application/zip', 'application/gzip', 'application/x-bzip', 'application/x-bzip2', 'application/x-xz', 'application/zstd', 'application/octet-stream']);
4
+ /**
5
+ * Create node response compression.
6
+ *
7
+ * @param response The response.
8
+ * @param acceptEncoding The accept encoding.
9
+ * @returns The create node response compression result.
10
+ */
4
11
  export function createNodeResponseCompression(response, acceptEncoding) {
5
12
  if (!acceptEncoding) {
6
13
  return undefined;
@@ -19,6 +26,15 @@ export function createNodeResponseCompression(response, acceptEncoding) {
19
26
  }
20
27
  };
21
28
  }
29
+
30
+ /**
31
+ * Compress node response.
32
+ *
33
+ * @param response The response.
34
+ * @param body The body.
35
+ * @param encoding The encoding.
36
+ * @returns The compress node response result.
37
+ */
22
38
  export function compressNodeResponse(response, body, encoding) {
23
39
  const stream = encoding === 'br' ? createBrotliCompress() : createGzip();
24
40
  response.setHeader('Content-Encoding', encoding);
@@ -1,6 +1,28 @@
1
1
  import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
2
2
  import { PayloadTooLargeException, type FrameworkRequest } from '@fluojs/http';
3
3
  import { type MultipartOptions } from '../multipart.js';
4
+ type MemoizedValue<T> = () => T;
5
+ type QueryRecord = Record<string, string | string[] | undefined>;
6
+ /**
7
+ * Options for creating a deferred framework request shell from a Node-backed adapter.
8
+ */
9
+ export interface DeferredFrameworkRequestShellOptions<RawRequest> {
10
+ cookieHeader?: string | string[] | undefined;
11
+ headers?: FrameworkRequest['headers'];
12
+ headersFactory?: () => FrameworkRequest['headers'];
13
+ materializeBody?: () => Promise<void>;
14
+ method?: string;
15
+ path: string;
16
+ query?: QueryRecord;
17
+ queryFactory?: () => QueryRecord;
18
+ raw: RawRequest;
19
+ requestId?: string;
20
+ signal: AbortSignal | (() => AbortSignal);
21
+ url: string;
22
+ }
23
+ /**
24
+ * HTTP payload-size error that closes the underlying Node request stream after the response commits.
25
+ */
4
26
  export declare class NodeRequestPayloadTooLargeException extends PayloadTooLargeException {
5
27
  private readonly request;
6
28
  constructor(request: IncomingMessage);
@@ -17,6 +39,45 @@ export declare class NodeRequestPayloadTooLargeException extends PayloadTooLarge
17
39
  * @returns The normalized framework request used by the dispatcher.
18
40
  */
19
41
  export declare function createFrameworkRequest(request: IncomingMessage, signal: AbortSignal, multipartOptions?: MultipartOptions, maxBodySize?: number, preserveRawBody?: boolean): Promise<FrameworkRequest>;
42
+ /**
43
+ * Creates the cheap Node framework request shell before consuming the body stream.
44
+ *
45
+ * @param request - Raw Node request carrying headers, URL, and body stream.
46
+ * @param signal - Abort signal tied to the response lifecycle.
47
+ * @param multipartOptions - Multipart parser options applied when materializing multipart requests.
48
+ * @param maxBodySize - Maximum allowed non-multipart body size in bytes.
49
+ * @param preserveRawBody - Whether materialization should retain raw request body bytes.
50
+ * @returns The framework request shell with metadata snapshotted and body materialization deferred.
51
+ */
52
+ export declare function createDeferredFrameworkRequest(request: IncomingMessage, signal: AbortSignal, multipartOptions?: MultipartOptions, maxBodySize?: number, preserveRawBody?: boolean): FrameworkRequest;
53
+ /**
54
+ * Creates a framework request shell from already-snapshotted Node adapter metadata.
55
+ *
56
+ * @param options - Raw request, metadata factories, and deferred body materialization hooks.
57
+ * @returns A framework request with lazy headers, cookies, query values, and optional body materialization.
58
+ */
59
+ export declare function createDeferredFrameworkRequestShell<RawRequest>({ cookieHeader, headers, headersFactory, materializeBody, method, path, query, queryFactory, raw, requestId, signal, url, }: DeferredFrameworkRequestShellOptions<RawRequest>): FrameworkRequest;
60
+ /**
61
+ * Materializes a deferred Node framework request body exactly once.
62
+ *
63
+ * @param request - Framework request returned by {@link createDeferredFrameworkRequest}.
64
+ * @returns A promise that settles after body, rawBody, and files fields are populated when applicable.
65
+ */
66
+ export declare function materializeFrameworkRequestBody(request: FrameworkRequest): Promise<void>;
67
+ /**
68
+ * Creates a synchronous memoized value resolver.
69
+ *
70
+ * @param factory - Function that computes the value on first access.
71
+ * @returns A stable resolver that returns the cached value after the first call.
72
+ */
73
+ export declare function createMemoizedValue<T>(factory: () => T): MemoizedValue<T>;
74
+ /**
75
+ * Creates an async memoized side-effect resolver.
76
+ *
77
+ * @param factory - Async function to run at most once.
78
+ * @returns A resolver that returns the same in-flight or completed promise for every call.
79
+ */
80
+ export declare function createMemoizedAsyncValue(factory: () => Promise<void>): () => Promise<void>;
20
81
  /**
21
82
  * Creates an abort signal that fires when the Node response closes unexpectedly.
22
83
  *
@@ -31,4 +92,71 @@ export declare function createRequestSignal(response: ServerResponse): AbortSign
31
92
  * @returns The request identifier when present.
32
93
  */
33
94
  export declare function resolveRequestIdFromHeaders(headers: IncomingHttpHeaders): string | undefined;
95
+ /**
96
+ * Parses a raw URL search string into the framework query shape.
97
+ *
98
+ * @param search - Raw search string, with or without a leading question mark.
99
+ * @returns Query values where repeated keys become string arrays.
100
+ */
101
+ export declare function parseQueryParamsFromSearch(search: string): Record<string, string | string[]>;
102
+ /**
103
+ * Snapshots host-parsed query values when they already match framework semantics.
104
+ *
105
+ * @param query - Host query object exposed by a Node-backed adapter.
106
+ * @returns A cloned query record when all values are strings or string arrays; otherwise `undefined` for raw URL fallback.
107
+ */
108
+ export declare function snapshotSimpleQueryRecord(query: unknown): QueryRecord | undefined;
109
+ /**
110
+ * Clones Node request headers into the framework header record shape.
111
+ *
112
+ * @param headers - Raw Node incoming headers.
113
+ * @returns A shallow header snapshot with array values cloned.
114
+ */
115
+ export declare function cloneRequestHeaders(headers: IncomingHttpHeaders): FrameworkRequest['headers'];
116
+ /**
117
+ * Clones a single Node header value when it is array-backed.
118
+ *
119
+ * @param value - Header value to snapshot.
120
+ * @returns The original scalar value or a cloned array value.
121
+ */
122
+ export declare function cloneHeaderValue<T extends string | string[] | undefined>(value: T): T;
123
+ /**
124
+ * Reads the primary value from a Node header value.
125
+ *
126
+ * @param headerValue - Header value that may contain multiple entries.
127
+ * @returns The first header value when present.
128
+ */
129
+ export declare function readPrimaryHeaderValue(headerValue: string | string[] | undefined): string | undefined;
130
+ /**
131
+ * Normalizes a Node content-type header to its primary media type.
132
+ *
133
+ * @param headerValue - Raw content-type header value.
134
+ * @returns Lowercase primary media type without parameters, or `undefined` when absent.
135
+ */
136
+ export declare function normalizePrimaryContentType(headerValue: string | string[] | undefined): string | undefined;
137
+ /**
138
+ * Parses a Node cookie header into framework cookie values.
139
+ *
140
+ * @param cookieHeader - Raw cookie header value or values.
141
+ * @returns Cookie name/value pairs with percent-decoded values when possible.
142
+ */
143
+ export declare function parseCookieHeader(cookieHeader: string | string[] | undefined): Record<string, string>;
144
+ /**
145
+ * Splits a raw Node request URL into path and search components.
146
+ *
147
+ * @param rawUrl - Raw request URL, absolute URL, or undefined value from Node.
148
+ * @returns The pathname and search string used by framework request matching and query parsing.
149
+ */
150
+ export declare function splitRawRequestUrl(rawUrl: string | undefined): {
151
+ path: string;
152
+ search: string;
153
+ };
154
+ /**
155
+ * Resolves a raw Node request URL into an absolute URL string.
156
+ *
157
+ * @param rawUrl - Raw request URL, absolute URL, or undefined value from Node.
158
+ * @returns An absolute URL suitable for Web-standard parsers.
159
+ */
160
+ export declare function resolveAbsoluteRequestUrl(rawUrl: string | undefined): string;
161
+ export {};
34
162
  //# sourceMappingURL=internal-node-request.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal-node-request.d.ts","sourceRoot":"","sources":["../../src/node/internal-node-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,cAAc,EACf,MAAM,WAAW,CAAC;AAInB,OAAO,EAEL,wBAAwB,EACxB,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAOzB,qBAAa,mCAAoC,SAAQ,wBAAwB;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,eAAe;IAIrD,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;CAahD;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,WAAW,EACnB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,SAAkB,EAC7B,eAAe,UAAQ,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,WAAW,CAezE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,GAAG,SAAS,CAG5F"}
1
+ {"version":3,"file":"internal-node-request.d.ts","sourceRoot":"","sources":["../../src/node/internal-node-request.ts"],"names":[],"mappings":"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"}