@loutrejs/loutre 0.4.1 → 0.6.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 (164) hide show
  1. package/README.md +63 -32
  2. package/dist/adapters/aws-lambda.d.ts +5 -3
  3. package/dist/adapters/aws-lambda.js +53 -23
  4. package/dist/adapters/bun.d.ts +7 -4
  5. package/dist/adapters/bun.js +52 -42
  6. package/dist/adapters/cloudflare-workers.d.ts +5 -3
  7. package/dist/adapters/cloudflare-workers.js +23 -28
  8. package/dist/adapters/deno.d.ts +7 -4
  9. package/dist/adapters/deno.js +94 -57
  10. package/dist/adapters/electron.d.ts +13 -5
  11. package/dist/adapters/electron.js +76 -28
  12. package/dist/application/definition.d.ts +31 -0
  13. package/dist/application/definition.js +16 -0
  14. package/dist/application/index.d.ts +4 -63
  15. package/dist/application/index.js +2 -11
  16. package/dist/application/kernel-internal.d.ts +2 -0
  17. package/dist/application/kernel-internal.js +10 -0
  18. package/dist/application/kernel.d.ts +21 -0
  19. package/dist/application/kernel.js +65 -0
  20. package/dist/core/diagnostic.d.ts +9 -0
  21. package/dist/core/diagnostic.js +9 -0
  22. package/dist/core/extension.d.ts +107 -0
  23. package/dist/core/extension.js +73 -0
  24. package/dist/core/generic-layer.d.ts +26 -0
  25. package/dist/core/generic-layer.js +116 -0
  26. package/dist/core/index.d.ts +31 -15
  27. package/dist/core/index.js +15 -15
  28. package/dist/core/injection.d.ts +4 -13
  29. package/dist/core/injection.js +63 -0
  30. package/dist/core/model/context.d.ts +18 -0
  31. package/dist/core/model/context.js +34 -0
  32. package/dist/core/model/lifecycle.d.ts +5 -0
  33. package/dist/core/model/lifecycle.js +44 -0
  34. package/dist/core/model/modules.d.ts +2 -0
  35. package/dist/core/model/modules.js +101 -0
  36. package/dist/core/model/providers.d.ts +4 -0
  37. package/dist/core/model/providers.js +74 -0
  38. package/dist/core/model/snapshot.d.ts +6 -0
  39. package/dist/core/model/snapshot.js +31 -0
  40. package/dist/core/model/types.d.ts +78 -0
  41. package/dist/core/model/validation.d.ts +4 -0
  42. package/dist/core/model/validation.js +40 -0
  43. package/dist/core/model/visibility.d.ts +4 -0
  44. package/dist/core/model/visibility.js +20 -0
  45. package/dist/core/model.d.ts +10 -0
  46. package/dist/core/model.js +346 -0
  47. package/dist/core/module.d.ts +8 -13
  48. package/dist/core/source-location.d.ts +8 -0
  49. package/dist/core/source-location.js +31 -0
  50. package/dist/core/token-internal.d.ts +3 -0
  51. package/dist/core/token-internal.js +4 -0
  52. package/dist/core/type.d.ts +7 -0
  53. package/dist/core/type.js +4 -0
  54. package/dist/generated/version.d.ts +1 -1
  55. package/dist/generated/version.js +1 -1
  56. package/dist/graph/index.d.ts +2 -3
  57. package/dist/graph/index.js +1 -3
  58. package/dist/graph/model.d.ts +34 -0
  59. package/dist/graph/model.js +127 -0
  60. package/dist/http/auth.d.ts +46 -0
  61. package/dist/http/auth.js +96 -0
  62. package/dist/http/client.d.ts +28 -31
  63. package/dist/http/client.js +60 -41
  64. package/dist/http/cors-internal.d.ts +29 -0
  65. package/dist/http/cors-internal.js +160 -0
  66. package/dist/http/cors.d.ts +5 -8
  67. package/dist/http/cors.js +7 -165
  68. package/dist/http/extension.d.ts +348 -0
  69. package/dist/http/extension.js +947 -0
  70. package/dist/http/index.d.ts +9 -7
  71. package/dist/http/index.js +5 -7
  72. package/dist/{application → http}/openapi.d.ts +12 -3
  73. package/dist/{application → http}/openapi.js +164 -101
  74. package/dist/http/path.d.ts +2 -39
  75. package/dist/http/path.js +7 -2
  76. package/dist/http/runtime/request.d.ts +17 -0
  77. package/dist/http/runtime/request.js +109 -0
  78. package/dist/http/runtime/response.d.ts +18 -0
  79. package/dist/http/runtime/response.js +108 -0
  80. package/dist/index.d.ts +4 -0
  81. package/dist/index.js +2 -0
  82. package/dist/message-port/extension.d.ts +66 -0
  83. package/dist/message-port/extension.js +395 -0
  84. package/dist/message-port/index.d.ts +4 -73
  85. package/dist/message-port/index.js +2 -189
  86. package/dist/message-port/transport.d.ts +11 -0
  87. package/dist/message-port/transport.js +45 -0
  88. package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
  89. package/dist/runtime/async-iterator-lifecycle.js +95 -0
  90. package/dist/runtime/capability.d.ts +11 -11
  91. package/dist/runtime/capability.js +3 -3
  92. package/dist/runtime/di.d.ts +2 -22
  93. package/dist/runtime/di.js +8 -285
  94. package/dist/runtime/execution-tracker.d.ts +8 -0
  95. package/dist/runtime/execution-tracker.js +54 -0
  96. package/dist/runtime/index.d.ts +15 -9
  97. package/dist/runtime/index.js +9 -9
  98. package/dist/runtime/ingress-gate.d.ts +7 -0
  99. package/dist/runtime/ingress-gate.js +33 -0
  100. package/dist/runtime/kernel.d.ts +23 -0
  101. package/dist/runtime/kernel.js +354 -0
  102. package/dist/runtime/logger.d.ts +2 -0
  103. package/dist/runtime/logger.js +2 -0
  104. package/dist/runtime/node-capabilities.d.ts +1 -1
  105. package/dist/runtime/node-capabilities.js +1 -1
  106. package/dist/runtime/server-port.d.ts +2 -0
  107. package/dist/runtime/server-port.js +11 -0
  108. package/dist/tasks/extension.d.ts +144 -0
  109. package/dist/tasks/extension.js +499 -0
  110. package/dist/tasks/index.d.ts +2 -0
  111. package/dist/tasks/index.js +1 -0
  112. package/dist/tasks/runtime/cron.d.ts +6 -0
  113. package/dist/tasks/runtime/cron.js +89 -0
  114. package/dist/websocket/errors.d.ts +9 -0
  115. package/dist/websocket/errors.js +18 -0
  116. package/dist/websocket/extension.d.ts +154 -0
  117. package/dist/websocket/extension.js +524 -0
  118. package/dist/websocket/index.d.ts +3 -0
  119. package/dist/websocket/index.js +2 -0
  120. package/package.json +12 -16
  121. package/dist/application/binding.d.ts +0 -33
  122. package/dist/application/binding.js +0 -295
  123. package/dist/application/host.d.ts +0 -8
  124. package/dist/application/host.js +0 -14
  125. package/dist/application/queue.d.ts +0 -3
  126. package/dist/application/queue.js +0 -4
  127. package/dist/application/scheduler.d.ts +0 -2
  128. package/dist/application/scheduler.js +0 -45
  129. package/dist/core/context-key.d.ts +0 -14
  130. package/dist/core/context-key.js +0 -14
  131. package/dist/core/contract.d.ts +0 -94
  132. package/dist/core/contract.js +0 -79
  133. package/dist/core/execution.d.ts +0 -78
  134. package/dist/core/execution.js +0 -61
  135. package/dist/core/implementation.d.ts +0 -34
  136. package/dist/core/implementation.js +0 -30
  137. package/dist/core/layer.d.ts +0 -109
  138. package/dist/core/layer.js +0 -52
  139. package/dist/graph/compiler.d.ts +0 -4
  140. package/dist/graph/compiler.js +0 -228
  141. package/dist/graph/graph.d.ts +0 -17
  142. package/dist/graph/graph.js +0 -1103
  143. package/dist/graph/ir.d.ts +0 -175
  144. package/dist/http/application.d.ts +0 -18
  145. package/dist/http/application.js +0 -506
  146. package/dist/http/basic-auth.d.ts +0 -37
  147. package/dist/http/basic-auth.js +0 -67
  148. package/dist/http/definitions.d.ts +0 -225
  149. package/dist/http/definitions.js +0 -69
  150. package/dist/http/hosted-protocol.d.ts +0 -4
  151. package/dist/http/hosted-protocol.js +0 -4
  152. package/dist/http/params.d.ts +0 -2
  153. package/dist/http/params.js +0 -19
  154. package/dist/http/request-body.d.ts +0 -4
  155. package/dist/http/request-body.js +0 -6
  156. package/dist/http/validate.d.ts +0 -20
  157. package/dist/http/validate.js +0 -6
  158. package/dist/message-port/environment.d.ts +0 -2
  159. package/dist/message-port/environment.js +0 -4
  160. package/dist/runtime/application.d.ts +0 -38
  161. package/dist/runtime/application.js +0 -339
  162. package/dist/runtime/pipeline.d.ts +0 -11
  163. package/dist/runtime/pipeline.js +0 -161
  164. /package/dist/{graph/ir.js → core/model/types.js} +0 -0
@@ -1,79 +0,0 @@
1
- export function protocolGroup(protocol, procedures) {
2
- return Object.freeze({
3
- kind: 'protocol-group',
4
- protocol,
5
- procedures: Object.freeze({ ...procedures }),
6
- });
7
- }
8
- function defineContract(groups) {
9
- if (groups.length === 0) {
10
- throw new Error('contract([]) requires at least one protocol group');
11
- }
12
- const procedures = {};
13
- for (const group of groups) {
14
- for (const [procedureName, descriptor] of Object.entries(group.procedures)) {
15
- const current = procedures[procedureName];
16
- if (Object.hasOwn(current?.protocols ?? {}, group.protocol)) {
17
- throw new Error(`Duplicate contract procedure protocol: ${procedureName}.${group.protocol}`);
18
- }
19
- procedures[procedureName] = {
20
- kind: 'procedure',
21
- protocols: {
22
- ...current?.protocols,
23
- [group.protocol]: descriptor,
24
- },
25
- };
26
- }
27
- }
28
- assertUniqueDispatchKeys(procedures);
29
- return Object.freeze({
30
- kind: 'contract',
31
- procedures: Object.freeze(procedures),
32
- });
33
- }
34
- function mergeContracts(contracts) {
35
- if (contracts.length === 0) {
36
- throw new Error('contract.merge([]) requires at least one Contract');
37
- }
38
- const procedures = {};
39
- for (const source of contracts) {
40
- for (const [procedureName, procedureDefinition] of Object.entries(source.procedures)) {
41
- const current = procedures[procedureName];
42
- const protocols = { ...current?.protocols };
43
- for (const [protocolName, descriptor] of Object.entries(procedureDefinition.protocols)) {
44
- if (Object.hasOwn(protocols, protocolName)) {
45
- throw new Error(`Duplicate contract procedure protocol: ${procedureName}.${protocolName}`);
46
- }
47
- protocols[protocolName] = descriptor;
48
- }
49
- procedures[procedureName] = { kind: 'procedure', protocols };
50
- }
51
- }
52
- assertUniqueDispatchKeys(procedures);
53
- return Object.freeze({
54
- kind: 'contract',
55
- procedures: Object.freeze(procedures),
56
- });
57
- }
58
- export const contract = Object.assign(defineContract, {
59
- merge: mergeContracts,
60
- });
61
- function assertUniqueDispatchKeys(procedures) {
62
- const paths = new Map();
63
- for (const [procedureName, procedureDefinition] of Object.entries(procedures)) {
64
- for (const [protocolName, protocol] of Object.entries(procedureDefinition.protocols)) {
65
- const dispatchKey = protocol.dispatchKey;
66
- if (dispatchKey === null)
67
- continue;
68
- if (typeof dispatchKey !== 'string') {
69
- throw new Error(`Protocol dispatchKey must be a string or null: ${procedureName}.${protocolName}`);
70
- }
71
- const path = `${procedureName}.${protocolName}`;
72
- const existing = paths.get(dispatchKey);
73
- if (existing) {
74
- throw new Error(`Duplicate protocol dispatch key "${dispatchKey}" between ${existing} and ${path}`);
75
- }
76
- paths.set(dispatchKey, path);
77
- }
78
- }
79
- }
@@ -1,78 +0,0 @@
1
- import { type SchemaOutput, type StandardSchemaV1 } from './schema.js';
2
- import { type Token } from './token.js';
3
- export type TaskRuntime<TInput, TOutput> = [TInput] extends [void] ? () => TOutput | Promise<TOutput> : (input: TInput) => TOutput | Promise<TOutput>;
4
- export interface TaskDescriptor<TInput = unknown, TOutput = unknown, TName extends string = string> {
5
- readonly kind: 'task';
6
- readonly name: TName;
7
- readonly factory: () => TaskRuntime<TInput, TOutput>;
8
- }
9
- export type TaskInput<T> = T extends TaskDescriptor<infer TInput, any, any> ? TInput : never;
10
- export type TaskOutput<T> = T extends TaskDescriptor<any, infer TOutput, any> ? TOutput : never;
11
- export type TaskArguments<T> = [TaskInput<T>] extends [void] ? readonly [] : readonly [input: TaskInput<T>];
12
- export declare function task<TInput = void, TOutput = void, const TName extends string = string>(declaration: {
13
- readonly name: TName;
14
- readonly factory: () => TaskRuntime<TInput, TOutput>;
15
- }): TaskDescriptor<TInput, TOutput, TName>;
16
- type VoidTaskConstraint<TTask> = [TaskInput<TTask>] extends [void] ? unknown : never;
17
- export type CronOverlap = 'allow' | 'skip';
18
- export interface CronTriggerDescriptor<TTask extends TaskDescriptor<void, any> = TaskDescriptor<void, any>, TName extends string = string> {
19
- readonly kind: 'trigger';
20
- readonly trigger: 'cron';
21
- readonly name: TName;
22
- readonly expression: string;
23
- readonly timezone: string;
24
- readonly overlap: CronOverlap;
25
- readonly task: TTask;
26
- }
27
- export declare function cron<const TTask extends TaskDescriptor<any, any>, const TName extends string>(declaration: {
28
- readonly name: TName;
29
- readonly expression: string;
30
- readonly timezone: string;
31
- readonly overlap?: CronOverlap;
32
- readonly task: TTask;
33
- } & VoidTaskConstraint<TTask>): CronTriggerDescriptor<TTask & TaskDescriptor<void, any>, TName>;
34
- export interface FixedDelayTriggerDescriptor<TTask extends TaskDescriptor<void, any> = TaskDescriptor<void, any>, TName extends string = string> {
35
- readonly kind: 'trigger';
36
- readonly trigger: 'fixed-delay';
37
- readonly name: TName;
38
- readonly delay: number;
39
- readonly immediate: boolean;
40
- readonly task: TTask;
41
- }
42
- export declare function fixedDelay<const TTask extends TaskDescriptor<any, any>, const TName extends string>(declaration: {
43
- readonly name: TName;
44
- readonly delay: number;
45
- readonly immediate?: boolean;
46
- readonly task: TTask;
47
- } & VoidTaskConstraint<TTask>): FixedDelayTriggerDescriptor<TTask & TaskDescriptor<void, any>, TName>;
48
- declare const queueDriverToken: unique symbol;
49
- export interface QueueDescriptor<TSchema extends StandardSchemaV1 = StandardSchemaV1, TName extends string = string> {
50
- readonly kind: 'queue';
51
- readonly name: TName;
52
- readonly payload: TSchema;
53
- readonly [queueDriverToken]: Token<unknown>;
54
- }
55
- export type QueuePayload<T> = T extends QueueDescriptor<infer TSchema, any> ? SchemaOutput<TSchema> : never;
56
- export declare function queue<const TSchema extends StandardSchemaV1, const TName extends string = string>(declaration: {
57
- readonly name: TName;
58
- readonly payload: TSchema;
59
- }): QueueDescriptor<TSchema, TName>;
60
- export declare function queueRuntimeToken(descriptor: QueueDescriptor): Token<unknown>;
61
- export interface QueueConsumerTriggerDescriptor<TQueue extends QueueDescriptor<any> = QueueDescriptor<any>, TTask extends TaskDescriptor<any, any> = TaskDescriptor<any, any>, TName extends string = string> {
62
- readonly kind: 'trigger';
63
- readonly trigger: 'queue-consumer';
64
- readonly name: TName;
65
- readonly queue: TQueue;
66
- readonly task: TTask;
67
- }
68
- type ConsumerTaskConstraint<TQueue, TTask> = [TaskInput<TTask>] extends [
69
- QueuePayload<TQueue>
70
- ] ? [QueuePayload<TQueue>] extends [TaskInput<TTask>] ? unknown : never : never;
71
- export declare function consume<const TQueue extends QueueDescriptor<any>, const TTask extends TaskDescriptor<any, any>, const TName extends string>(declaration: {
72
- readonly name: TName;
73
- readonly queue: TQueue;
74
- readonly task: TTask;
75
- } & ConsumerTaskConstraint<TQueue, TTask>): QueueConsumerTriggerDescriptor<TQueue, TTask & TaskDescriptor<QueuePayload<TQueue>, any>, TName>;
76
- export type TriggerDescriptor = CronTriggerDescriptor<any, any> | FixedDelayTriggerDescriptor<any, any> | QueueConsumerTriggerDescriptor<any, any, any>;
77
- export type TriggerTask<TTrigger> = TTrigger extends TriggerDescriptor ? TTrigger['task'] : never;
78
- export {};
@@ -1,61 +0,0 @@
1
- import { token } from './token.js';
2
- export function task(declaration) {
3
- return Object.freeze({
4
- kind: 'task',
5
- name: declaration.name,
6
- factory: declaration.factory,
7
- });
8
- }
9
- export function cron(declaration) {
10
- return Object.freeze({
11
- kind: 'trigger',
12
- trigger: 'cron',
13
- name: declaration.name,
14
- expression: declaration.expression,
15
- timezone: declaration.timezone,
16
- overlap: declaration.overlap ?? 'skip',
17
- task: declaration.task,
18
- });
19
- }
20
- export function fixedDelay(declaration) {
21
- if (!Number.isFinite(declaration.delay) ||
22
- !Number.isInteger(declaration.delay) ||
23
- declaration.delay < 0) {
24
- throw new Error('LUTRE_TRIGGER_INVALID_FIXED_DELAY: fixedDelay.delay must be a non-negative finite integer.');
25
- }
26
- return Object.freeze({
27
- kind: 'trigger',
28
- trigger: 'fixed-delay',
29
- name: declaration.name,
30
- delay: declaration.delay,
31
- immediate: declaration.immediate ?? false,
32
- task: declaration.task,
33
- });
34
- }
35
- const queueDriverToken = Symbol('loutre.queue-driver');
36
- export function queue(declaration) {
37
- const payload = declaration.payload;
38
- if (payload === null ||
39
- (typeof payload !== 'object' && typeof payload !== 'function') ||
40
- !('~standard' in payload)) {
41
- throw new Error('LUTRE_QUEUE_PAYLOAD_SCHEMA: queue.payload must implement Standard Schema.');
42
- }
43
- return Object.freeze({
44
- kind: 'queue',
45
- name: declaration.name,
46
- payload: declaration.payload,
47
- [queueDriverToken]: token(`loutre.queue-driver.${declaration.name}`),
48
- });
49
- }
50
- export function queueRuntimeToken(descriptor) {
51
- return descriptor[queueDriverToken];
52
- }
53
- export function consume(declaration) {
54
- return Object.freeze({
55
- kind: 'trigger',
56
- trigger: 'queue-consumer',
57
- name: declaration.name,
58
- queue: declaration.queue,
59
- task: declaration.task,
60
- });
61
- }
@@ -1,34 +0,0 @@
1
- import type { ContractDefinition, ContractProcedures, ProtocolDescriptor, ProtocolFactory } from './contract.js';
2
- type ProcedureNamesForProtocol<TContract extends ContractDefinition, TProtocol extends string> = {
3
- [K in keyof ContractProcedures<TContract>]: TProtocol extends keyof ContractProcedures<TContract>[K]['protocols'] ? K : never;
4
- }[keyof ContractProcedures<TContract>] & string;
5
- type ImplementationRuntimeShape<TContract extends ContractDefinition, TProtocol extends string, TProcedures extends string> = {
6
- [K in TProcedures]: ContractProcedures<TContract>[K]['protocols'][TProtocol & keyof ContractProcedures<TContract>[K]['protocols']] extends ProtocolDescriptor<TProtocol, infer TContext, infer TResult, any, any> ? (context: TContext) => TResult | Promise<TResult> : never;
7
- };
8
- export interface ImplementationDescriptor<TContract extends ContractDefinition = ContractDefinition, TProtocol extends string = string, TProcedures extends readonly string[] = readonly string[], TRuntime extends object = object, TCapabilities extends readonly string[] = readonly string[]> {
9
- readonly kind: 'implementation';
10
- readonly name: string;
11
- readonly contract: TContract;
12
- readonly protocol: TProtocol;
13
- readonly capabilities: TCapabilities;
14
- readonly procedures: TProcedures;
15
- readonly factory: () => TRuntime;
16
- }
17
- type AvailableProtocolConstraint<TContract extends ContractDefinition, TProtocol extends string, TCapabilities extends readonly string[]> = [ProcedureNamesForProtocol<TContract, TProtocol>] extends [never] ? never : ProtocolFactory<TProtocol, TCapabilities>;
18
- type FullImplementationDeclaration<TContract extends ContractDefinition, TProtocol extends string, TCapabilities extends readonly string[]> = {
19
- readonly name: string;
20
- readonly contract: TContract;
21
- readonly protocol: AvailableProtocolConstraint<TContract, TProtocol, TCapabilities>;
22
- readonly procedures?: never;
23
- readonly factory: () => ImplementationRuntimeShape<TContract, TProtocol, ProcedureNamesForProtocol<TContract, TProtocol>>;
24
- };
25
- type PartialImplementationDeclaration<TContract extends ContractDefinition, TProtocol extends string, TProcedures extends readonly ProcedureNamesForProtocol<TContract, TProtocol>[], TCapabilities extends readonly string[]> = {
26
- readonly name: string;
27
- readonly contract: TContract;
28
- readonly protocol: AvailableProtocolConstraint<TContract, TProtocol, TCapabilities>;
29
- readonly procedures: TProcedures;
30
- readonly factory: () => ImplementationRuntimeShape<TContract, TProtocol, TProcedures[number]>;
31
- };
32
- export declare function implementation<const TContract extends ContractDefinition, const TProtocol extends string, const TCapabilities extends readonly string[]>(declaration: FullImplementationDeclaration<TContract, TProtocol, TCapabilities>): ImplementationDescriptor<TContract, TProtocol, readonly ProcedureNamesForProtocol<TContract, TProtocol>[], ImplementationRuntimeShape<TContract, TProtocol, ProcedureNamesForProtocol<TContract, TProtocol>>, TCapabilities>;
33
- export declare function implementation<const TContract extends ContractDefinition, const TProtocol extends string, const TProcedures extends readonly ProcedureNamesForProtocol<TContract, TProtocol>[], const TCapabilities extends readonly string[]>(declaration: PartialImplementationDeclaration<TContract, TProtocol, TProcedures, TCapabilities>): ImplementationDescriptor<TContract, TProtocol, TProcedures, ImplementationRuntimeShape<TContract, TProtocol, TProcedures[number]>, TCapabilities>;
34
- export {};
@@ -1,30 +0,0 @@
1
- export function implementation(declaration) {
2
- const protocol = declaration.protocol.protocol;
3
- const available = Object.entries(declaration.contract.procedures)
4
- .filter(([, procedure]) => protocol in procedure.protocols)
5
- .map(([name]) => name);
6
- if (available.length === 0) {
7
- throw new Error(`LUTRE_IMPL_003: Contract does not declare any procedure for protocol ${protocol}.`);
8
- }
9
- const procedures = [...(declaration.procedures ?? available)];
10
- const selected = new Set();
11
- for (const procedure of procedures) {
12
- if (selected.has(procedure)) {
13
- throw new Error(`LUTRE_IMPL_003: Implementation ${declaration.name} selects procedure ${procedure} more than once.`);
14
- }
15
- selected.add(procedure);
16
- const definition = declaration.contract.procedures[procedure];
17
- if (!definition || !(protocol in definition.protocols)) {
18
- throw new Error(`LUTRE_IMPL_003: ${procedure} is not declared for protocol ${protocol}.`);
19
- }
20
- }
21
- return Object.freeze({
22
- kind: 'implementation',
23
- name: declaration.name,
24
- contract: declaration.contract,
25
- protocol,
26
- capabilities: declaration.protocol.capabilities ?? [],
27
- procedures: Object.freeze(procedures),
28
- factory: declaration.factory,
29
- });
30
- }
@@ -1,109 +0,0 @@
1
- import type { ContextKey, ContextProperties } from './context-key.js';
2
- export type LayerRole = 'generic' | 'authentication' | 'guard' | 'validation' | 'framework' | 'terminal';
3
- export type ValidatedInputPart = 'params' | 'query' | 'headers' | 'body';
4
- declare const shortCircuitMarker: unique symbol;
5
- export interface ShortCircuit<TResult = unknown> {
6
- readonly kind: 'short-circuit';
7
- readonly result: TResult;
8
- readonly [shortCircuitMarker]: true;
9
- }
10
- export declare function shortCircuit<const TResult>(result: TResult): ShortCircuit<TResult>;
11
- export declare function isShortCircuit(value: unknown): value is ShortCircuit;
12
- declare const shortCircuitResultType: unique symbol;
13
- export interface ShortCircuitDeclaration {
14
- readonly protocol: string;
15
- readonly variant: string;
16
- readonly response?: Readonly<Record<string, unknown>>;
17
- }
18
- export type LayerNext<TProvides extends readonly ContextKey[]> = number extends TProvides['length'] ? (provided: ContextProperties<TProvides>) => Promise<void> : TProvides extends readonly [] ? () => Promise<void> : (provided: ContextProperties<TProvides>) => Promise<void>;
19
- export type LayerRuntime<TContext extends object, TProvides extends readonly ContextKey[], TShortCircuitResult> = (context: TContext, next: LayerNext<TProvides>) => Promise<void | ShortCircuit<TShortCircuitResult>>;
20
- export type LayerFactory<TContext extends object, TProvides extends readonly ContextKey[], TShortCircuitResult> = () => LayerRuntime<TContext, TProvides, TShortCircuitResult>;
21
- export interface LayerDefinition<TRequires extends readonly ContextKey[] = readonly [], TProvides extends readonly ContextKey[] = readonly [], TContext extends object = {}, TShortCircuitResult = never, TShortCircuits extends readonly ShortCircuitDeclaration[] = readonly [], TName extends string = string, TRole extends Exclude<LayerRole, 'terminal' | 'validation'> = 'generic', TRequiresValidated extends readonly ValidatedInputPart[] = readonly []> {
22
- readonly name: TName;
23
- readonly role?: TRole;
24
- readonly requires?: TRequires;
25
- readonly provides?: TProvides;
26
- readonly requiresValidated?: TRequiresValidated;
27
- readonly shortCircuits?: TShortCircuits;
28
- readonly factory: LayerFactory<TContext & ContextProperties<TRequires>, TProvides, TShortCircuitResult>;
29
- }
30
- export interface LayerOccurrenceDescriptor<TRequires extends readonly ContextKey[] = readonly ContextKey[], TProvides extends readonly ContextKey[] = readonly ContextKey[], TShortCircuitResult = unknown, TShortCircuits extends readonly ShortCircuitDeclaration[] = readonly ShortCircuitDeclaration[], TName extends string = string, TRole extends Exclude<LayerRole, 'terminal' | 'validation'> = Exclude<LayerRole, 'terminal' | 'validation'>, TRequiresValidated extends readonly ValidatedInputPart[] = readonly ValidatedInputPart[], TContext extends object = object, TPipeline extends readonly PipelineItem[] = readonly PipelineItem[]> {
31
- readonly kind: 'layer';
32
- readonly name: TName;
33
- readonly role: TRole;
34
- readonly requires: TRequires;
35
- readonly provides: TProvides;
36
- readonly requiresValidated: TRequiresValidated;
37
- readonly shortCircuits: TShortCircuits;
38
- readonly definition: LayerDescriptor<TRequires, TProvides, TShortCircuitResult, TShortCircuits, TName, TRole, TRequiresValidated, TContext>;
39
- readonly pipeline: TPipeline;
40
- readonly factory?: never;
41
- readonly [shortCircuitResultType]?: TShortCircuitResult;
42
- }
43
- export interface LayerDescriptor<TRequires extends readonly ContextKey[] = readonly ContextKey[], TProvides extends readonly ContextKey[] = readonly ContextKey[], TShortCircuitResult = unknown, TShortCircuits extends readonly ShortCircuitDeclaration[] = readonly ShortCircuitDeclaration[], TName extends string = string, TRole extends Exclude<LayerRole, 'terminal' | 'validation'> = Exclude<LayerRole, 'terminal' | 'validation'>, TRequiresValidated extends readonly ValidatedInputPart[] = readonly ValidatedInputPart[], TContext extends object = object> {
44
- <const TPipeline extends readonly PipelineItem[]>(pipeline: TPipeline): LayerOccurrenceDescriptor<TRequires, TProvides, TShortCircuitResult, TShortCircuits, TName, TRole, TRequiresValidated, TContext, TPipeline>;
45
- readonly kind: 'layer';
46
- readonly name: TName;
47
- readonly role: TRole;
48
- readonly requires: TRequires;
49
- readonly provides: TProvides;
50
- readonly requiresValidated: TRequiresValidated;
51
- readonly shortCircuits: TShortCircuits;
52
- readonly factory: LayerFactory<TContext & ContextProperties<TRequires>, TProvides, TShortCircuitResult>;
53
- readonly definition?: never;
54
- readonly pipeline?: never;
55
- readonly [shortCircuitResultType]?: TShortCircuitResult;
56
- }
57
- export interface ValidationLayerDescriptor {
58
- readonly kind: 'validation';
59
- readonly name: `validate.${'params' | 'query' | 'headers' | 'body'}`;
60
- readonly role: 'validation';
61
- readonly part: 'params' | 'query' | 'headers' | 'body';
62
- }
63
- export interface TerminalLayerDescriptor<TProtocol extends string = string> {
64
- readonly kind: 'terminal';
65
- readonly name: `${TProtocol}.${string}`;
66
- readonly role: 'terminal';
67
- readonly protocol: TProtocol;
68
- }
69
- type AnyLayerDescriptor = LayerDescriptor<any, any, any, any, any, any, any, any>;
70
- type AnyLayerOccurrence = LayerOccurrenceDescriptor<any, any, any, any, any, any, any, any, any>;
71
- export type PipelineItem = AnyLayerDescriptor | AnyLayerOccurrence | ValidationLayerDescriptor | TerminalLayerDescriptor;
72
- export declare function isLayerOccurrence(item: PipelineItem): item is AnyLayerOccurrence;
73
- export declare function layerDefinitionOf(item: AnyLayerDescriptor | AnyLayerOccurrence): AnyLayerDescriptor;
74
- export declare function childPipelineOf(item: AnyLayerDescriptor | AnyLayerOccurrence): readonly PipelineItem[] | undefined;
75
- interface PipelineTerminalState<THasTerminal extends boolean, TValid extends boolean> {
76
- readonly hasTerminal: THasTerminal;
77
- readonly valid: TValid;
78
- }
79
- type InvalidPipelineTerminalState = PipelineTerminalState<boolean, false>;
80
- type FoldPipelineTerminals<TPipeline extends readonly PipelineItem[], TProtocol extends string, TState extends PipelineTerminalState<boolean, boolean>> = TState['valid'] extends false ? TState : number extends TPipeline['length'] ? InvalidPipelineTerminalState : TPipeline extends readonly [infer THead, ...infer TTail] ? TState['hasTerminal'] extends true ? InvalidPipelineTerminalState : FoldPipelineTerminals<Extract<TTail, readonly PipelineItem[]>, TProtocol, FoldPipelineItemTerminals<THead, TProtocol, TState>> : TState;
81
- type FoldPipelineItemTerminals<TItem, TProtocol extends string, TState extends PipelineTerminalState<boolean, boolean>> = TItem extends TerminalLayerDescriptor<infer TItemProtocol> ? [TItemProtocol, TProtocol] extends [TProtocol, TItemProtocol] ? PipelineTerminalState<true, true> : InvalidPipelineTerminalState : TItem extends LayerOccurrenceDescriptor<any, any, any, any, any, any, any, any, infer TPipeline> ? FoldPipelineTerminals<TPipeline, TProtocol, TState> : TState;
82
- export type IsValidProtocolPipeline<TPipeline extends readonly PipelineItem[], TProtocol extends string> = FoldPipelineTerminals<TPipeline, TProtocol, PipelineTerminalState<false, true>> extends PipelineTerminalState<true, true> ? true : false;
83
- export type ShortCircuitResultOf<TItem> = TItem extends LayerOccurrenceDescriptor<any, any, any, any, any, any, any, any, infer TPipeline> ? ShortCircuitResultOfPipeline<TPipeline> | ShortCircuitResultOfLayer<TItem> : ShortCircuitResultOfLayer<TItem>;
84
- type ShortCircuitResultOfLayer<TItem> = TItem extends {
85
- readonly [shortCircuitResultType]?: infer TResult;
86
- } ? TResult : never;
87
- export type ShortCircuitDeclarationsOf<TItem> = TItem extends LayerOccurrenceDescriptor<any, any, any, any, any, any, any, any, infer TPipeline> ? readonly [
88
- ...NormalizeDeclarations<TItem['shortCircuits']>,
89
- ...ShortCircuitDeclarationsOfPipeline<TPipeline>
90
- ] : TItem extends {
91
- readonly shortCircuits: infer TShortCircuits;
92
- } ? TShortCircuits : never;
93
- type ShortCircuitResultOfPipeline<TPipeline extends readonly PipelineItem[]> = TPipeline[number] extends infer TItem ? ShortCircuitResultOf<TItem> : never;
94
- type ShortCircuitDeclarationsOfPipeline<TPipeline extends readonly PipelineItem[]> = TPipeline extends readonly [infer THead, ...infer TTail] ? readonly [
95
- ...NormalizeDeclarations<ShortCircuitDeclarationsOf<THead>>,
96
- ...ShortCircuitDeclarationsOfPipeline<Extract<TTail, readonly PipelineItem[]>>
97
- ] : readonly [];
98
- type NormalizeDeclarations<TDeclarations> = TDeclarations extends readonly ShortCircuitDeclaration[] ? TDeclarations : readonly [];
99
- interface PipelineTypeState<TContext extends object, TValidated extends ValidatedInputPart, TDone extends boolean> {
100
- readonly context: TContext;
101
- readonly validated: TValidated;
102
- readonly done: TDone;
103
- }
104
- type FoldPipeline<TPipeline extends readonly PipelineItem[], TState extends PipelineTypeState<object, ValidatedInputPart, boolean>> = TState['done'] extends true ? TState : number extends TPipeline['length'] ? TState : TPipeline extends readonly [infer THead, ...infer TTail] ? FoldPipeline<Extract<TTail, readonly PipelineItem[]>, FoldPipelineItem<THead, TState>> : TState;
105
- type FoldPipelineItem<TItem, TState extends PipelineTypeState<object, ValidatedInputPart, boolean>> = TItem extends TerminalLayerDescriptor ? PipelineTypeState<TState['context'], TState['validated'], true> : TItem extends ValidationLayerDescriptor ? PipelineTypeState<TState['context'], TState['validated'] | TItem['part'], false> : TItem extends LayerOccurrenceDescriptor<any, infer TProvides, any, any, any, any, any, any, infer TPipeline> ? FoldPipeline<TPipeline, PipelineTypeState<TState['context'] & ContextProperties<TProvides>, TState['validated'], false>> : TItem extends LayerDescriptor<any, infer TProvides, any, any, any, any, any, any> ? PipelineTypeState<TState['context'] & ContextProperties<TProvides>, TState['validated'], false> : TState;
106
- export type ContextProvidedBeforeTerminal<TPipeline extends readonly PipelineItem[], TContext extends object = {}> = number extends TPipeline['length'] ? TContext : FoldPipeline<TPipeline, PipelineTypeState<TContext, never, false>>['context'];
107
- export type HasValidationBeforeTerminal<TPipeline extends readonly PipelineItem[], TPart extends ValidatedInputPart> = number extends TPipeline['length'] ? false : TPart extends FoldPipeline<TPipeline, PipelineTypeState<{}, never, false>>['validated'] ? true : false;
108
- export declare function layer<const TRequires extends readonly ContextKey[] = readonly [], const TProvides extends readonly ContextKey[] = readonly [], TContext extends object = {}, TShortCircuitResult = never, const TShortCircuits extends readonly ShortCircuitDeclaration[] = readonly [], const TName extends string = string, const TRole extends Exclude<LayerRole, 'terminal' | 'validation'> = 'generic', const TRequiresValidated extends readonly ValidatedInputPart[] = readonly []>(definition: LayerDefinition<TRequires, TProvides, TContext, TShortCircuitResult, TShortCircuits, TName, TRole, TRequiresValidated>): LayerDescriptor<TRequires, TProvides, TShortCircuitResult, TShortCircuits, TName, TRole, TRequiresValidated, TContext>;
109
- export {};
@@ -1,52 +0,0 @@
1
- const shortCircuitMarker = Symbol('loutre.short-circuit');
2
- export function shortCircuit(result) {
3
- return {
4
- kind: 'short-circuit',
5
- result,
6
- [shortCircuitMarker]: true,
7
- };
8
- }
9
- export function isShortCircuit(value) {
10
- return (typeof value === 'object' &&
11
- value !== null &&
12
- shortCircuitMarker in value &&
13
- value[shortCircuitMarker] === true);
14
- }
15
- export function isLayerOccurrence(item) {
16
- return item.kind === 'layer' && item.definition !== undefined;
17
- }
18
- export function layerDefinitionOf(item) {
19
- return isLayerOccurrence(item) ? item.definition : item;
20
- }
21
- export function childPipelineOf(item) {
22
- return isLayerOccurrence(item) ? item.pipeline : undefined;
23
- }
24
- export function layer(definition) {
25
- let descriptor;
26
- const callable = (pipeline) => Object.freeze({
27
- kind: 'layer',
28
- name: descriptor.name,
29
- role: descriptor.role,
30
- requires: descriptor.requires,
31
- provides: descriptor.provides,
32
- requiresValidated: descriptor.requiresValidated,
33
- shortCircuits: descriptor.shortCircuits,
34
- definition: descriptor,
35
- pipeline,
36
- });
37
- Object.defineProperty(callable, 'name', {
38
- value: definition.name,
39
- enumerable: true,
40
- configurable: true,
41
- });
42
- descriptor = Object.assign(callable, {
43
- kind: 'layer',
44
- role: definition.role ?? 'generic',
45
- requires: definition.requires ?? [],
46
- provides: definition.provides ?? [],
47
- requiresValidated: definition.requiresValidated ?? [],
48
- shortCircuits: definition.shortCircuits ?? [],
49
- factory: definition.factory,
50
- });
51
- return Object.freeze(descriptor);
52
- }
@@ -1,4 +0,0 @@
1
- import { type ApplicationCompilationInput } from './graph.js';
2
- import type { CompilationResult } from './ir.js';
3
- export declare function compileApplication(input: ApplicationCompilationInput): CompilationResult;
4
- export declare const buildApplicationGraph: typeof compileApplication;