@loutrejs/loutre 0.1.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.
Files changed (103) hide show
  1. package/dist/adapters/aws-lambda.d.ts +52 -0
  2. package/dist/adapters/aws-lambda.js +114 -0
  3. package/dist/adapters/bun.d.ts +20 -0
  4. package/dist/adapters/bun.js +82 -0
  5. package/dist/adapters/cloudflare-workers.d.ts +18 -0
  6. package/dist/adapters/cloudflare-workers.js +55 -0
  7. package/dist/adapters/deno.d.ts +28 -0
  8. package/dist/adapters/deno.js +106 -0
  9. package/dist/adapters/electron.d.ts +27 -0
  10. package/dist/adapters/electron.js +52 -0
  11. package/dist/application/binding.d.ts +33 -0
  12. package/dist/application/binding.js +292 -0
  13. package/dist/application/host.d.ts +8 -0
  14. package/dist/application/host.js +14 -0
  15. package/dist/application/index.d.ts +62 -0
  16. package/dist/application/index.js +11 -0
  17. package/dist/application/openapi.d.ts +28 -0
  18. package/dist/application/openapi.js +362 -0
  19. package/dist/application/queue.d.ts +3 -0
  20. package/dist/application/queue.js +4 -0
  21. package/dist/application/scheduler.d.ts +2 -0
  22. package/dist/application/scheduler.js +45 -0
  23. package/dist/core/args.d.ts +16 -0
  24. package/dist/core/args.js +29 -0
  25. package/dist/core/context-key.d.ts +14 -0
  26. package/dist/core/context-key.js +14 -0
  27. package/dist/core/contract.d.ts +54 -0
  28. package/dist/core/contract.js +30 -0
  29. package/dist/core/env.d.ts +16 -0
  30. package/dist/core/env.js +29 -0
  31. package/dist/core/error.d.ts +24 -0
  32. package/dist/core/error.js +25 -0
  33. package/dist/core/execution.d.ts +78 -0
  34. package/dist/core/execution.js +61 -0
  35. package/dist/core/implementation.d.ts +34 -0
  36. package/dist/core/implementation.js +30 -0
  37. package/dist/core/index.d.ts +15 -0
  38. package/dist/core/index.js +15 -0
  39. package/dist/core/injection.d.ts +28 -0
  40. package/dist/core/injection.js +35 -0
  41. package/dist/core/layer.d.ts +109 -0
  42. package/dist/core/layer.js +52 -0
  43. package/dist/core/lifecycle.d.ts +34 -0
  44. package/dist/core/lifecycle.js +3 -0
  45. package/dist/core/module.d.ts +53 -0
  46. package/dist/core/module.js +31 -0
  47. package/dist/core/provider.d.ts +57 -0
  48. package/dist/core/provider.js +63 -0
  49. package/dist/core/runtime-input.d.ts +11 -0
  50. package/dist/core/runtime-input.js +1 -0
  51. package/dist/core/schema.d.ts +13 -0
  52. package/dist/core/schema.js +20 -0
  53. package/dist/core/token.d.ts +16 -0
  54. package/dist/core/token.js +13 -0
  55. package/dist/graph/graph.d.ts +17 -0
  56. package/dist/graph/graph.js +1078 -0
  57. package/dist/graph/index.d.ts +2 -0
  58. package/dist/graph/index.js +2 -0
  59. package/dist/graph/ir.d.ts +159 -0
  60. package/dist/graph/ir.js +1 -0
  61. package/dist/http/application.d.ts +18 -0
  62. package/dist/http/application.js +506 -0
  63. package/dist/http/basic-auth.d.ts +37 -0
  64. package/dist/http/basic-auth.js +67 -0
  65. package/dist/http/cors.d.ts +17 -0
  66. package/dist/http/cors.js +171 -0
  67. package/dist/http/definitions.d.ts +217 -0
  68. package/dist/http/definitions.js +65 -0
  69. package/dist/http/hosted-protocol.d.ts +4 -0
  70. package/dist/http/hosted-protocol.js +4 -0
  71. package/dist/http/index.d.ts +7 -0
  72. package/dist/http/index.js +6 -0
  73. package/dist/http/params.d.ts +2 -0
  74. package/dist/http/params.js +19 -0
  75. package/dist/http/path.d.ts +55 -0
  76. package/dist/http/path.js +88 -0
  77. package/dist/http/request-body.d.ts +4 -0
  78. package/dist/http/request-body.js +6 -0
  79. package/dist/http/validate.d.ts +20 -0
  80. package/dist/http/validate.js +6 -0
  81. package/dist/index.d.ts +2 -0
  82. package/dist/index.js +2 -0
  83. package/dist/message-port/environment.d.ts +2 -0
  84. package/dist/message-port/environment.js +4 -0
  85. package/dist/message-port/index.d.ts +65 -0
  86. package/dist/message-port/index.js +182 -0
  87. package/dist/runtime/application.d.ts +37 -0
  88. package/dist/runtime/application.js +324 -0
  89. package/dist/runtime/capability.d.ts +16 -0
  90. package/dist/runtime/capability.js +18 -0
  91. package/dist/runtime/di.d.ts +37 -0
  92. package/dist/runtime/di.js +441 -0
  93. package/dist/runtime/error.d.ts +10 -0
  94. package/dist/runtime/error.js +15 -0
  95. package/dist/runtime/index.d.ts +7 -0
  96. package/dist/runtime/index.js +7 -0
  97. package/dist/runtime/logger.d.ts +36 -0
  98. package/dist/runtime/logger.js +207 -0
  99. package/dist/runtime/node-capabilities.d.ts +5 -0
  100. package/dist/runtime/node-capabilities.js +18 -0
  101. package/dist/runtime/pipeline.d.ts +11 -0
  102. package/dist/runtime/pipeline.js +161 -0
  103. package/package.json +81 -0
@@ -0,0 +1,441 @@
1
+ import { asModuleInstance, childPipelineOf, isArgsClass, isEnvClass, layerDefinitionOf, normalizeProvider, runInInjectionContext, tokenName, } from '../core/index.js';
2
+ import { Logger } from './logger.js';
3
+ export class DependencyResolutionError extends Error {
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = 'DependencyResolutionError';
7
+ }
8
+ }
9
+ class GraphProbeBoundary extends Error {
10
+ source;
11
+ constructor(source) {
12
+ super(`Graph Probe reached runtime-dependent value: ${source}`);
13
+ this.source = source;
14
+ this.name = 'GraphProbeBoundary';
15
+ }
16
+ }
17
+ export function collectRuntimeModuleGraph(roots) {
18
+ const modules = [];
19
+ const providers = [];
20
+ const environmentProviders = new Set();
21
+ const visited = new Set();
22
+ const visit = (moduleLike) => {
23
+ const module = asModuleInstance(moduleLike);
24
+ if (visited.has(module))
25
+ return;
26
+ visited.add(module);
27
+ for (const imported of module.definition.imports ?? [])
28
+ visit(imported);
29
+ modules.push(module);
30
+ for (const declaration of module.definition.providers ?? []) {
31
+ const provider = normalizeProvider(declaration);
32
+ if (provider.kind === 'environment') {
33
+ if (environmentProviders.has(provider.provide))
34
+ continue;
35
+ environmentProviders.add(provider.provide);
36
+ }
37
+ providers.push(provider);
38
+ }
39
+ };
40
+ for (const root of roots)
41
+ visit(root);
42
+ return { modules, providers };
43
+ }
44
+ export class Container {
45
+ #providers = new Map();
46
+ #applicationCache = new Map();
47
+ #implementationCache = new Map();
48
+ #implementationConsumers = new Map();
49
+ #taskCache = new Map();
50
+ #taskConsumers = new Map();
51
+ #layerCache = new Map();
52
+ #logger;
53
+ #recorder;
54
+ #environment = new Map();
55
+ #arguments = new Map();
56
+ #probe;
57
+ constructor(providers, options = {}) {
58
+ this.#logger =
59
+ options instanceof Logger ? options : (options.logger ?? new Logger());
60
+ this.#recorder = options instanceof Logger ? undefined : options.recorder;
61
+ this.#probe = options instanceof Logger ? false : (options.probe ?? false);
62
+ if (!(options instanceof Logger)) {
63
+ for (const [environment, value] of options.environment ?? []) {
64
+ this.#environment.set(environment, value);
65
+ }
66
+ for (const [argumentsContract, value] of options.arguments ?? []) {
67
+ this.#arguments.set(argumentsContract, value);
68
+ }
69
+ }
70
+ for (const provider of providers) {
71
+ const existing = this.#providers.get(provider.provide);
72
+ if (existing) {
73
+ if (existing.kind === provider.kind &&
74
+ isRuntimeInputProvider(provider)) {
75
+ continue;
76
+ }
77
+ if (isRuntimeInputProvider(existing) ||
78
+ isRuntimeInputProvider(provider)) {
79
+ const source = existing.kind === 'arguments' || provider.kind === 'arguments'
80
+ ? 'Arguments'
81
+ : 'Environment';
82
+ const code = source === 'Arguments' ? 'LUTRE_ARGS_001' : 'LUTRE_ENV_001';
83
+ throw new DependencyResolutionError(`${code}: ${source} ${tokenName(provider.provide)} is runtime-managed and cannot also be declared as a normal provider.`);
84
+ }
85
+ throw new DependencyResolutionError(`LUTRE_DI_DUPLICATE: Duplicate provider for ${tokenName(provider.provide)}`);
86
+ }
87
+ this.#providers.set(provider.provide, provider);
88
+ }
89
+ }
90
+ bindEnvironment(environment, value) {
91
+ const provider = this.#providers.get(environment);
92
+ if (!provider || provider.kind !== 'environment') {
93
+ throw new DependencyResolutionError(`LUTRE_ENV_002: ${environment.name} is not declared by any Module.environment.`);
94
+ }
95
+ if (this.#applicationCache.has(environment)) {
96
+ throw new DependencyResolutionError(`LUTRE_ENV_006: Environment ${environment.name} was already resolved and cannot be rebound.`);
97
+ }
98
+ this.#environment.set(environment, value);
99
+ }
100
+ bindArguments(argumentsContract, value) {
101
+ const provider = this.#providers.get(argumentsContract);
102
+ if (!provider || provider.kind !== 'arguments') {
103
+ throw new DependencyResolutionError(`LUTRE_ARGS_002: ${argumentsContract.name} is not declared by Application.arguments.`);
104
+ }
105
+ if (this.#applicationCache.has(argumentsContract)) {
106
+ throw new DependencyResolutionError(`LUTRE_ARGS_006: Arguments ${argumentsContract.name} was already resolved and cannot be rebound.`);
107
+ }
108
+ this.#arguments.set(argumentsContract, value);
109
+ }
110
+ resolve(token) {
111
+ return this.#resolve(token);
112
+ }
113
+ probeClass(target) {
114
+ try {
115
+ return this.#instantiate(target, [target]);
116
+ }
117
+ catch (error) {
118
+ if (isGraphProbeBoundary(error)) {
119
+ return createOpaqueProbeValue(target.name);
120
+ }
121
+ throw error;
122
+ }
123
+ }
124
+ prepareImplementation(implementation) {
125
+ if (this.#implementationCache.has(implementation))
126
+ return;
127
+ let consumer = this.#implementationConsumers.get(implementation);
128
+ if (!consumer) {
129
+ consumer = {
130
+ kind: 'implementation-consumer',
131
+ id: `runtime-implementation:${this.#implementationConsumers.size + 1}`,
132
+ name: implementation.name,
133
+ };
134
+ this.#implementationConsumers.set(implementation, consumer);
135
+ }
136
+ this.#constructImplementation(implementation, consumer, true);
137
+ }
138
+ implementationRuntime(implementation) {
139
+ const cached = this.#implementationCache.get(implementation);
140
+ if (!cached) {
141
+ throw new DependencyResolutionError(`LUTRE_IMPL_NOT_PREPARED: Implementation ${implementation.name} is not prepared during application construction.`);
142
+ }
143
+ return cached;
144
+ }
145
+ prepareTask(task) {
146
+ if (this.#taskCache.has(task))
147
+ return;
148
+ let consumer = this.#taskConsumers.get(task);
149
+ if (!consumer) {
150
+ consumer = {
151
+ kind: 'task-consumer',
152
+ id: `runtime-task:${this.#taskConsumers.size + 1}`,
153
+ name: task.name,
154
+ };
155
+ this.#taskConsumers.set(task, consumer);
156
+ }
157
+ this.#constructTask(task, consumer, true);
158
+ }
159
+ taskRuntime(task) {
160
+ const cached = this.#taskCache.get(task);
161
+ if (!cached) {
162
+ throw new DependencyResolutionError(`LUTRE_TASK_NOT_PREPARED: Task ${task.name} is not prepared during application construction.`);
163
+ }
164
+ return cached;
165
+ }
166
+ probeTask(task, consumer) {
167
+ try {
168
+ this.#constructTask(task, consumer, false);
169
+ }
170
+ catch (error) {
171
+ if (isGraphProbeBoundary(error))
172
+ return;
173
+ throw error;
174
+ }
175
+ }
176
+ probeImplementation(implementation, consumer) {
177
+ try {
178
+ return this.#constructImplementation(implementation, consumer, false);
179
+ }
180
+ catch (error) {
181
+ if (isGraphProbeBoundary(error)) {
182
+ return createOpaqueProbeValue(implementation.name);
183
+ }
184
+ throw error;
185
+ }
186
+ }
187
+ preparePipeline(pipeline) {
188
+ for (const item of pipeline) {
189
+ if (item.kind !== 'layer')
190
+ continue;
191
+ const definition = layerDefinitionOf(item);
192
+ this.#constructLayer(definition, {
193
+ kind: 'layer-consumer',
194
+ id: `runtime-layer:${definition.name}`,
195
+ name: definition.name,
196
+ }, true);
197
+ const child = childPipelineOf(item);
198
+ if (child)
199
+ this.preparePipeline(child);
200
+ }
201
+ }
202
+ layerRuntime(layer) {
203
+ const cached = this.#layerCache.get(layer);
204
+ if (!cached) {
205
+ throw new DependencyResolutionError(`LUTRE_LAYER_NOT_PREPARED: Layer ${layer.name} is not prepared during application construction.`);
206
+ }
207
+ return cached;
208
+ }
209
+ probeLayer(layer, consumer) {
210
+ try {
211
+ this.#constructLayer(layer, consumer, false);
212
+ }
213
+ catch (error) {
214
+ if (isGraphProbeBoundary(error))
215
+ return;
216
+ throw error;
217
+ }
218
+ }
219
+ #resolve(token, source, lineage = []) {
220
+ const cycleStart = lineage.indexOf(token);
221
+ if (cycleStart >= 0) {
222
+ const cycle = [...lineage.slice(cycleStart), token]
223
+ .map(tokenName)
224
+ .join(' -> ');
225
+ throw new DependencyResolutionError(`LUTRE_DI_CYCLE: 循環依存を検出しました: ${cycle}`);
226
+ }
227
+ const provider = this.#providers.get(token);
228
+ if (!provider) {
229
+ if (token === Logger) {
230
+ return this.#logger.child(source === undefined ? {} : { source });
231
+ }
232
+ if (isEnvClass(token)) {
233
+ throw new DependencyResolutionError(`LUTRE_ENV_002: ${token.name} is injected by ${source ?? 'Application'} but is not declared by any Module.environment.`);
234
+ }
235
+ if (isArgsClass(token)) {
236
+ throw new DependencyResolutionError(`LUTRE_ARGS_002: ${token.name} is injected by ${source ?? 'Application'} but is not declared by Application.arguments.`);
237
+ }
238
+ throw new DependencyResolutionError(`LUTRE_DI_UNRESOLVED: ${source ?? 'Application'} requires ${tokenName(token)}, but no provider is declared for ${tokenName(token)}.`);
239
+ }
240
+ const nextLineage = [...lineage, token];
241
+ if (provider.scope !== 'application') {
242
+ return this.#create(provider, nextLineage);
243
+ }
244
+ const cached = this.#applicationCache.get(token);
245
+ if (this.#applicationCache.has(token))
246
+ return cached;
247
+ const instance = this.#create(provider, nextLineage);
248
+ this.#applicationCache.set(token, instance);
249
+ return instance;
250
+ }
251
+ #create(provider, lineage) {
252
+ try {
253
+ switch (provider.kind) {
254
+ case 'value':
255
+ return provider.useValue;
256
+ case 'environment': {
257
+ if (this.#environment.has(provider.provide)) {
258
+ return this.#environment.get(provider.provide);
259
+ }
260
+ if (this.#probe)
261
+ return createOpaqueProbeValue(provider.provide.name);
262
+ throw new DependencyResolutionError(`LUTRE_ENV_005: Environment ${provider.provide.name} requires a runtime Environment source before Application initialization.`);
263
+ }
264
+ case 'arguments': {
265
+ if (this.#arguments.has(provider.provide)) {
266
+ return this.#arguments.get(provider.provide);
267
+ }
268
+ if (this.#probe)
269
+ return createOpaqueProbeValue(provider.provide.name);
270
+ throw new DependencyResolutionError(`LUTRE_ARGS_005: Arguments ${provider.provide.name} requires a runtime Arguments source before Application initialization.`);
271
+ }
272
+ case 'class':
273
+ return this.#instantiate(provider.useClass, lineage);
274
+ case 'factory': {
275
+ const dependencies = provider.inject.map((token) => this.#resolve(token, tokenName(provider.provide), lineage));
276
+ const value = provider.useFactory(...dependencies);
277
+ if (isThenable(value)) {
278
+ throw new DependencyResolutionError('LUTRE_DI_ASYNC_FACTORY: Async factory providers are not supported. Move asynchronous resource initialization to application lifecycle.');
279
+ }
280
+ return value;
281
+ }
282
+ case 'conditional': {
283
+ if (this.#probe)
284
+ return Object.create(null);
285
+ const input = this.#resolve(provider.select.contract, tokenName(provider.provide), lineage);
286
+ const selected = input[provider.select.key];
287
+ const implementation = provider.mapping[selected];
288
+ if (!implementation) {
289
+ throw new DependencyResolutionError(`${provider.select.key}=${String(selected)}に対応するconditional Providerがありません`);
290
+ }
291
+ return this.#instantiate(implementation, lineage);
292
+ }
293
+ }
294
+ }
295
+ catch (error) {
296
+ if (provider.scope === 'application') {
297
+ this.#applicationCache.delete(provider.provide);
298
+ }
299
+ if (this.#probe && isGraphProbeBoundary(error)) {
300
+ return createOpaqueProbeValue(tokenName(provider.provide));
301
+ }
302
+ throw error;
303
+ }
304
+ }
305
+ #instantiate(target, lineage) {
306
+ if (target.length > 0) {
307
+ throw new DependencyResolutionError(`LUTRE_DI_CONSTRUCTOR: ${target.name} has required constructor parameters. Declare framework dependencies with constructor default parameters using inject().`);
308
+ }
309
+ return runInInjectionContext({
310
+ consumer: target,
311
+ resolve: (token) => this.#resolve(token, target.name, lineage),
312
+ ...(this.#recorder === undefined
313
+ ? {}
314
+ : {
315
+ record: (consumer, dependency) => this.#recorder.record(consumer, dependency),
316
+ }),
317
+ }, () => new target());
318
+ }
319
+ #constructLayer(layer, consumer, cache) {
320
+ const cached = this.#layerCache.get(layer);
321
+ if (cache && cached)
322
+ return cached;
323
+ const runtime = runInInjectionContext({
324
+ consumer,
325
+ resolve: (token) => this.#resolve(token, layer.name),
326
+ ...(this.#recorder === undefined
327
+ ? {}
328
+ : {
329
+ record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
330
+ }),
331
+ }, () => layer.factory());
332
+ if (isThenable(runtime)) {
333
+ throw new DependencyResolutionError(`LUTRE_LAYER_ASYNC_FACTORY: Layer ${layer.name} factory must be synchronous.`);
334
+ }
335
+ if (typeof runtime !== 'function') {
336
+ throw new DependencyResolutionError(`LUTRE_LAYER_FACTORY_RESULT: Layer ${layer.name} factory must return a runtime function.`);
337
+ }
338
+ const normalized = runtime;
339
+ if (cache)
340
+ this.#layerCache.set(layer, normalized);
341
+ return normalized;
342
+ }
343
+ #constructImplementation(implementation, consumer, cache) {
344
+ const cached = this.#implementationCache.get(implementation);
345
+ if (cache && cached)
346
+ return cached;
347
+ const runtime = runInInjectionContext({
348
+ consumer,
349
+ resolve: (token) => this.#resolve(token, implementation.name),
350
+ ...(this.#recorder === undefined
351
+ ? {}
352
+ : {
353
+ record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
354
+ }),
355
+ }, () => implementation.factory());
356
+ if (isThenable(runtime)) {
357
+ throw new DependencyResolutionError(`LUTRE_IMPL_ASYNC_FACTORY: Implementation ${implementation.name} factory must be synchronous.`);
358
+ }
359
+ if (typeof runtime !== 'object' ||
360
+ runtime === null ||
361
+ Array.isArray(runtime)) {
362
+ throw new DependencyResolutionError(`LUTRE_IMPL_FACTORY_RESULT: Implementation ${implementation.name} factory must return a non-null object.`);
363
+ }
364
+ const normalized = runtime;
365
+ for (const procedure of implementation.procedures) {
366
+ if (typeof normalized[procedure] !== 'function') {
367
+ throw new DependencyResolutionError(`LUTRE_IMPL_004: Implementation ${implementation.name} does not implement callable procedure ${procedure}.`);
368
+ }
369
+ }
370
+ if (cache)
371
+ this.#implementationCache.set(implementation, normalized);
372
+ return normalized;
373
+ }
374
+ #constructTask(task, consumer, cache) {
375
+ const cached = this.#taskCache.get(task);
376
+ if (cache && cached)
377
+ return cached;
378
+ const runtime = runInInjectionContext({
379
+ consumer,
380
+ resolve: (token) => this.#resolve(token, task.name),
381
+ ...(this.#recorder === undefined
382
+ ? {}
383
+ : {
384
+ record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
385
+ }),
386
+ }, () => task.factory());
387
+ if (isThenable(runtime)) {
388
+ throw new DependencyResolutionError(`LUTRE_TASK_ASYNC_FACTORY: Task ${task.name} factory must be synchronous.`);
389
+ }
390
+ if (typeof runtime !== 'function') {
391
+ throw new DependencyResolutionError(`LUTRE_TASK_FACTORY_RESULT: Task ${task.name} factory must return a runtime function.`);
392
+ }
393
+ const normalized = runtime;
394
+ if (cache)
395
+ this.#taskCache.set(task, normalized);
396
+ return normalized;
397
+ }
398
+ }
399
+ function isRuntimeInputProvider(provider) {
400
+ return provider.kind === 'environment' || provider.kind === 'arguments';
401
+ }
402
+ function isGraphProbeBoundary(error) {
403
+ return error instanceof GraphProbeBoundary;
404
+ }
405
+ function createOpaqueProbeValue(source) {
406
+ const boundary = (operation) => new GraphProbeBoundary(`${source}.${String(operation)}`);
407
+ return new Proxy(Object.create(null), {
408
+ get(_target, key) {
409
+ throw boundary(key);
410
+ },
411
+ set(_target, key) {
412
+ throw boundary(key);
413
+ },
414
+ has(_target, key) {
415
+ throw boundary(key);
416
+ },
417
+ ownKeys() {
418
+ throw boundary('*');
419
+ },
420
+ getOwnPropertyDescriptor(_target, key) {
421
+ throw boundary(key);
422
+ },
423
+ defineProperty(_target, key) {
424
+ throw boundary(key);
425
+ },
426
+ deleteProperty(_target, key) {
427
+ throw boundary(key);
428
+ },
429
+ getPrototypeOf() {
430
+ throw boundary('[[Prototype]]');
431
+ },
432
+ setPrototypeOf() {
433
+ throw boundary('[[Prototype]]');
434
+ },
435
+ });
436
+ }
437
+ function isThenable(value) {
438
+ return (((typeof value === 'object' && value !== null) ||
439
+ typeof value === 'function') &&
440
+ typeof value.then === 'function');
441
+ }
@@ -0,0 +1,10 @@
1
+ export interface NormalizedApplicationError {
2
+ readonly code: 'INTERNAL_ERROR';
3
+ readonly errorId: string;
4
+ readonly message: string;
5
+ readonly stack?: string;
6
+ readonly cause?: unknown;
7
+ readonly context: Readonly<Record<string, unknown>>;
8
+ readonly original: unknown;
9
+ }
10
+ export declare function normalizeUnknownError(error: unknown, context?: Readonly<Record<string, unknown>>): NormalizedApplicationError;
@@ -0,0 +1,15 @@
1
+ export function normalizeUnknownError(error, context = {}) {
2
+ return {
3
+ code: 'INTERNAL_ERROR',
4
+ errorId: crypto.randomUUID(),
5
+ message: error instanceof Error ? error.message : String(error),
6
+ ...(error instanceof Error && error.stack !== undefined
7
+ ? { stack: error.stack }
8
+ : {}),
9
+ ...(error instanceof Error && error.cause !== undefined
10
+ ? { cause: error.cause }
11
+ : {}),
12
+ context,
13
+ original: error,
14
+ };
15
+ }
@@ -0,0 +1,7 @@
1
+ export * from './application.js';
2
+ export * from './capability.js';
3
+ export * from './di.js';
4
+ export * from './error.js';
5
+ export * from './logger.js';
6
+ export * from './pipeline.js';
7
+ export * from './node-capabilities.js';
@@ -0,0 +1,7 @@
1
+ export * from './application.js';
2
+ export * from './capability.js';
3
+ export * from './di.js';
4
+ export * from './error.js';
5
+ export * from './logger.js';
6
+ export * from './pipeline.js';
7
+ export * from './node-capabilities.js';
@@ -0,0 +1,36 @@
1
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
2
+ export interface LogRecord {
3
+ readonly timestamp: string;
4
+ readonly level: LogLevel;
5
+ readonly message: string;
6
+ readonly [key: string]: unknown;
7
+ }
8
+ export interface LoggerBackend {
9
+ write(record: LogRecord): void;
10
+ }
11
+ export interface ConsoleLoggerBackendOptions {
12
+ readonly colors?: boolean;
13
+ readonly prefix?: string;
14
+ }
15
+ export declare class ConsoleLoggerBackend implements LoggerBackend {
16
+ #private;
17
+ constructor(options?: ConsoleLoggerBackendOptions);
18
+ write(record: LogRecord): void;
19
+ }
20
+ export declare class JsonConsoleLoggerBackend implements LoggerBackend {
21
+ write(record: LogRecord): void;
22
+ }
23
+ export declare class Logger {
24
+ #private;
25
+ readonly backend: LoggerBackend;
26
+ readonly context: Readonly<Record<string, unknown>>;
27
+ constructor(backend?: LoggerBackend, context?: Readonly<Record<string, unknown>>);
28
+ child(context: Readonly<Record<string, unknown>>): Logger;
29
+ debug(message: string, context?: Readonly<Record<string, unknown>>): void;
30
+ info(message: string, context?: Readonly<Record<string, unknown>>): void;
31
+ warn(message: string, context?: Readonly<Record<string, unknown>>): void;
32
+ error(message: string, context?: Readonly<Record<string, unknown>>): void;
33
+ }
34
+ export declare class SilentLogger extends Logger {
35
+ constructor(context?: Readonly<Record<string, unknown>>);
36
+ }