@beignet/core 0.0.1
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 +5 -0
- package/README.md +288 -0
- package/dist/application/index.d.ts +260 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +324 -0
- package/dist/application/index.js.map +1 -0
- package/dist/client/client.d.ts +241 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +531 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +139 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/config/index.d.ts +122 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +216 -0
- package/dist/config/index.js.map +1 -0
- package/dist/contracts/contract-builder.d.ts +121 -0
- package/dist/contracts/contract-builder.d.ts.map +1 -0
- package/dist/contracts/contract-builder.js +346 -0
- package/dist/contracts/contract-builder.js.map +1 -0
- package/dist/contracts/contract-group.d.ts +106 -0
- package/dist/contracts/contract-group.d.ts.map +1 -0
- package/dist/contracts/contract-group.js +240 -0
- package/dist/contracts/contract-group.js.map +1 -0
- package/dist/contracts/contract-like.d.ts +21 -0
- package/dist/contracts/contract-like.d.ts.map +1 -0
- package/dist/contracts/contract-like.js +9 -0
- package/dist/contracts/contract-like.js.map +1 -0
- package/dist/contracts/index.d.ts +15 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +11 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/openapi-meta.d.ts +23 -0
- package/dist/contracts/openapi-meta.d.ts.map +1 -0
- package/dist/contracts/openapi-meta.js +2 -0
- package/dist/contracts/openapi-meta.js.map +1 -0
- package/dist/contracts/path-template.d.ts +17 -0
- package/dist/contracts/path-template.d.ts.map +1 -0
- package/dist/contracts/path-template.js +50 -0
- package/dist/contracts/path-template.js.map +1 -0
- package/dist/contracts/rate-limit.d.ts +50 -0
- package/dist/contracts/rate-limit.d.ts.map +1 -0
- package/dist/contracts/rate-limit.js +2 -0
- package/dist/contracts/rate-limit.js.map +1 -0
- package/dist/contracts/types.d.ts +97 -0
- package/dist/contracts/types.d.ts.map +1 -0
- package/dist/contracts/types.js +54 -0
- package/dist/contracts/types.js.map +1 -0
- package/dist/contracts/utils.d.ts +3 -0
- package/dist/contracts/utils.d.ts.map +1 -0
- package/dist/contracts/utils.js +44 -0
- package/dist/contracts/utils.js.map +1 -0
- package/dist/domain/entity.d.ts +87 -0
- package/dist/domain/entity.d.ts.map +1 -0
- package/dist/domain/entity.js +155 -0
- package/dist/domain/entity.js.map +1 -0
- package/dist/domain/events.d.ts +41 -0
- package/dist/domain/events.d.ts.map +1 -0
- package/dist/domain/events.js +21 -0
- package/dist/domain/events.js.map +1 -0
- package/dist/domain/index.d.ts +14 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +14 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/value-object.d.ts +60 -0
- package/dist/domain/value-object.d.ts.map +1 -0
- package/dist/domain/value-object.js +87 -0
- package/dist/domain/value-object.js.map +1 -0
- package/dist/errors/catalog.d.ts +71 -0
- package/dist/errors/catalog.d.ts.map +1 -0
- package/dist/errors/catalog.js +71 -0
- package/dist/errors/catalog.js.map +1 -0
- package/dist/errors/http.d.ts +77 -0
- package/dist/errors/http.d.ts.map +1 -0
- package/dist/errors/http.js +74 -0
- package/dist/errors/http.js.map +1 -0
- package/dist/errors/index.d.ts +10 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +14 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/response.d.ts +26 -0
- package/dist/errors/response.d.ts.map +1 -0
- package/dist/errors/response.js +34 -0
- package/dist/errors/response.js.map +1 -0
- package/dist/errors/validation.d.ts +18 -0
- package/dist/errors/validation.d.ts.map +1 -0
- package/dist/errors/validation.js +21 -0
- package/dist/errors/validation.js.map +1 -0
- package/dist/events/index.d.ts +58 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +102 -0
- package/dist/events/index.js.map +1 -0
- package/dist/jobs/index.d.ts +56 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +89 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/mail/index.d.ts +75 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +84 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/openapi/index.d.ts +207 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +449 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/schema-introspector.d.ts +38 -0
- package/dist/openapi/schema-introspector.d.ts.map +1 -0
- package/dist/openapi/schema-introspector.js +67 -0
- package/dist/openapi/schema-introspector.js.map +1 -0
- package/dist/ports/audit.d.ts +58 -0
- package/dist/ports/audit.d.ts.map +1 -0
- package/dist/ports/audit.js +74 -0
- package/dist/ports/audit.js.map +1 -0
- package/dist/ports/auth.d.ts +23 -0
- package/dist/ports/auth.d.ts.map +1 -0
- package/dist/ports/auth.js +31 -0
- package/dist/ports/auth.js.map +1 -0
- package/dist/ports/builder.d.ts +61 -0
- package/dist/ports/builder.d.ts.map +1 -0
- package/dist/ports/builder.js +48 -0
- package/dist/ports/builder.js.map +1 -0
- package/dist/ports/cache.d.ts +15 -0
- package/dist/ports/cache.d.ts.map +1 -0
- package/dist/ports/cache.js +57 -0
- package/dist/ports/cache.js.map +1 -0
- package/dist/ports/clock.d.ts +10 -0
- package/dist/ports/clock.d.ts.map +1 -0
- package/dist/ports/clock.js +21 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/events.d.ts +71 -0
- package/dist/ports/events.d.ts.map +1 -0
- package/dist/ports/events.js +2 -0
- package/dist/ports/events.js.map +1 -0
- package/dist/ports/id-generator.d.ts +12 -0
- package/dist/ports/id-generator.d.ts.map +1 -0
- package/dist/ports/id-generator.js +22 -0
- package/dist/ports/id-generator.js.map +1 -0
- package/dist/ports/index.d.ts +98 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +67 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/logger.d.ts +22 -0
- package/dist/ports/logger.d.ts.map +1 -0
- package/dist/ports/logger.js +34 -0
- package/dist/ports/logger.js.map +1 -0
- package/dist/ports/mailer.d.ts +6 -0
- package/dist/ports/mailer.d.ts.map +1 -0
- package/dist/ports/mailer.js +2 -0
- package/dist/ports/mailer.js.map +1 -0
- package/dist/ports/policy.d.ts +53 -0
- package/dist/ports/policy.d.ts.map +1 -0
- package/dist/ports/policy.js +81 -0
- package/dist/ports/policy.js.map +1 -0
- package/dist/ports/rate-limit.d.ts +41 -0
- package/dist/ports/rate-limit.d.ts.map +1 -0
- package/dist/ports/rate-limit.js +37 -0
- package/dist/ports/rate-limit.js.map +1 -0
- package/dist/ports/redaction.d.ts +26 -0
- package/dist/ports/redaction.d.ts.map +1 -0
- package/dist/ports/redaction.js +126 -0
- package/dist/ports/redaction.js.map +1 -0
- package/dist/ports/schedules.d.ts +9 -0
- package/dist/ports/schedules.d.ts.map +1 -0
- package/dist/ports/schedules.js +2 -0
- package/dist/ports/schedules.js.map +1 -0
- package/dist/ports/storage.d.ts +47 -0
- package/dist/ports/storage.d.ts.map +1 -0
- package/dist/ports/storage.js +185 -0
- package/dist/ports/storage.js.map +1 -0
- package/dist/ports/testing.d.ts +73 -0
- package/dist/ports/testing.d.ts.map +1 -0
- package/dist/ports/testing.js +105 -0
- package/dist/ports/testing.js.map +1 -0
- package/dist/ports/unit-of-work.d.ts +56 -0
- package/dist/ports/unit-of-work.d.ts.map +1 -0
- package/dist/ports/unit-of-work.js +64 -0
- package/dist/ports/unit-of-work.js.map +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/instrumentation.d.ts +91 -0
- package/dist/providers/instrumentation.d.ts.map +1 -0
- package/dist/providers/instrumentation.js +93 -0
- package/dist/providers/instrumentation.js.map +1 -0
- package/dist/providers/provider.d.ts +146 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +31 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/schedules/index.d.ts +105 -0
- package/dist/schedules/index.d.ts.map +1 -0
- package/dist/schedules/index.js +178 -0
- package/dist/schedules/index.js.map +1 -0
- package/dist/server/contract-like.d.ts +5 -0
- package/dist/server/contract-like.d.ts.map +1 -0
- package/dist/server/contract-like.js +5 -0
- package/dist/server/contract-like.js.map +1 -0
- package/dist/server/health.d.ts +41 -0
- package/dist/server/health.d.ts.map +1 -0
- package/dist/server/health.js +46 -0
- package/dist/server/health.js.map +1 -0
- package/dist/server/hooks/auth.d.ts +42 -0
- package/dist/server/hooks/auth.d.ts.map +1 -0
- package/dist/server/hooks/auth.js +61 -0
- package/dist/server/hooks/auth.js.map +1 -0
- package/dist/server/hooks/cors.d.ts +13 -0
- package/dist/server/hooks/cors.d.ts.map +1 -0
- package/dist/server/hooks/cors.js +70 -0
- package/dist/server/hooks/cors.js.map +1 -0
- package/dist/server/hooks/errors.d.ts +66 -0
- package/dist/server/hooks/errors.d.ts.map +1 -0
- package/dist/server/hooks/errors.js +83 -0
- package/dist/server/hooks/errors.js.map +1 -0
- package/dist/server/hooks/index.d.ts +12 -0
- package/dist/server/hooks/index.d.ts.map +1 -0
- package/dist/server/hooks/index.js +12 -0
- package/dist/server/hooks/index.js.map +1 -0
- package/dist/server/hooks/logging.d.ts +33 -0
- package/dist/server/hooks/logging.d.ts.map +1 -0
- package/dist/server/hooks/logging.js +90 -0
- package/dist/server/hooks/logging.js.map +1 -0
- package/dist/server/hooks/rate-limit.d.ts +29 -0
- package/dist/server/hooks/rate-limit.d.ts.map +1 -0
- package/dist/server/hooks/rate-limit.js +93 -0
- package/dist/server/hooks/rate-limit.js.map +1 -0
- package/dist/server/hooks/utils.d.ts +9 -0
- package/dist/server/hooks/utils.d.ts.map +1 -0
- package/dist/server/hooks/utils.js +16 -0
- package/dist/server/hooks/utils.js.map +1 -0
- package/dist/server/hooks.d.ts +2 -0
- package/dist/server/hooks.d.ts.map +1 -0
- package/dist/server/hooks.js +2 -0
- package/dist/server/hooks.js.map +1 -0
- package/dist/server/http.d.ts +124 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +2 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +19 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +15 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/openapi.d.ts +32 -0
- package/dist/server/openapi.d.ts.map +1 -0
- package/dist/server/openapi.js +43 -0
- package/dist/server/openapi.js.map +1 -0
- package/dist/server/providers/index.d.ts +4 -0
- package/dist/server/providers/index.d.ts.map +1 -0
- package/dist/server/providers/index.js +4 -0
- package/dist/server/providers/index.js.map +1 -0
- package/dist/server/providers/loadProviderConfig.d.ts +7 -0
- package/dist/server/providers/loadProviderConfig.d.ts.map +1 -0
- package/dist/server/providers/loadProviderConfig.js +42 -0
- package/dist/server/providers/loadProviderConfig.js.map +1 -0
- package/dist/server/server.d.ts +86 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +1031 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/types.d.ts +3 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +3 -0
- package/dist/server/types.js.map +1 -0
- package/package.json +129 -0
- package/src/application/index.ts +747 -0
- package/src/client/client.ts +1105 -0
- package/src/client/index.ts +45 -0
- package/src/client/types.ts +305 -0
- package/src/config/index.ts +497 -0
- package/src/contracts/contract-builder.ts +583 -0
- package/src/contracts/contract-group.ts +502 -0
- package/src/contracts/contract-like.ts +29 -0
- package/src/contracts/index.ts +53 -0
- package/src/contracts/openapi-meta.ts +22 -0
- package/src/contracts/path-template.ts +91 -0
- package/src/contracts/rate-limit.ts +50 -0
- package/src/contracts/types.ts +207 -0
- package/src/contracts/utils.ts +56 -0
- package/src/domain/entity.ts +256 -0
- package/src/domain/events.ts +52 -0
- package/src/domain/index.ts +18 -0
- package/src/domain/value-object.ts +135 -0
- package/src/errors/catalog.ts +149 -0
- package/src/errors/http.ts +80 -0
- package/src/errors/index.ts +28 -0
- package/src/errors/response.ts +54 -0
- package/src/errors/validation.ts +35 -0
- package/src/events/index.ts +246 -0
- package/src/jobs/index.ts +211 -0
- package/src/mail/index.ts +177 -0
- package/src/openapi/index.ts +865 -0
- package/src/openapi/schema-introspector.ts +107 -0
- package/src/ports/audit.ts +176 -0
- package/src/ports/auth.ts +76 -0
- package/src/ports/builder.ts +97 -0
- package/src/ports/cache.ts +94 -0
- package/src/ports/clock.ts +34 -0
- package/src/ports/events.ts +100 -0
- package/src/ports/id-generator.ts +36 -0
- package/src/ports/index.ts +221 -0
- package/src/ports/logger.ts +67 -0
- package/src/ports/policy.ts +242 -0
- package/src/ports/rate-limit.ts +91 -0
- package/src/ports/redaction.ts +199 -0
- package/src/ports/storage.ts +282 -0
- package/src/ports/testing.ts +234 -0
- package/src/ports/unit-of-work.ts +134 -0
- package/src/providers/index.ts +40 -0
- package/src/providers/instrumentation.ts +248 -0
- package/src/providers/provider.ts +191 -0
- package/src/schedules/index.ts +442 -0
- package/src/server/contract-like.ts +8 -0
- package/src/server/health.ts +82 -0
- package/src/server/hooks/auth.ts +147 -0
- package/src/server/hooks/cors.ts +87 -0
- package/src/server/hooks/errors.ts +126 -0
- package/src/server/hooks/index.ts +43 -0
- package/src/server/hooks/logging.ts +121 -0
- package/src/server/hooks/rate-limit.ts +171 -0
- package/src/server/hooks/utils.ts +16 -0
- package/src/server/hooks.ts +1 -0
- package/src/server/http.ts +189 -0
- package/src/server/index.ts +35 -0
- package/src/server/openapi.ts +72 -0
- package/src/server/providers/index.ts +3 -0
- package/src/server/providers/loadProviderConfig.ts +72 -0
- package/src/server/server.ts +1521 -0
- package/src/server/types.ts +2 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { parseEventPayload } from "../events";
|
|
2
|
+
import type { DomainEventDef, EventBusPort, InferEventPayload } from "./events";
|
|
3
|
+
|
|
4
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
5
|
+
|
|
6
|
+
export type UnitOfWorkCallback<TxPorts, Result> = (
|
|
7
|
+
tx: TxPorts,
|
|
8
|
+
) => MaybePromise<Result>;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A transaction boundary for application workflows.
|
|
12
|
+
*
|
|
13
|
+
* The transaction ports are app-owned. A database adapter can provide
|
|
14
|
+
* transaction-scoped repositories, while test or in-memory adapters can use
|
|
15
|
+
* `createNoopUnitOfWork`.
|
|
16
|
+
*/
|
|
17
|
+
export interface UnitOfWorkPort<TxPorts> {
|
|
18
|
+
transaction<Result>(
|
|
19
|
+
work: UnitOfWorkCallback<TxPorts, Result>,
|
|
20
|
+
): Promise<Result>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface NoopUnitOfWorkOptions<TxPorts> {
|
|
24
|
+
/**
|
|
25
|
+
* Runs after the callback completes successfully.
|
|
26
|
+
*
|
|
27
|
+
* Use this to flush buffered domain events after the work has committed.
|
|
28
|
+
*/
|
|
29
|
+
afterCommit?: (tx: TxPorts) => MaybePromise<void>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Runs after the callback throws.
|
|
33
|
+
*
|
|
34
|
+
* Use this to clear buffers or release test resources. The original error is
|
|
35
|
+
* rethrown after this hook runs.
|
|
36
|
+
*/
|
|
37
|
+
afterRollback?: (error: unknown, tx: TxPorts) => MaybePromise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface RecordedDomainEvent {
|
|
41
|
+
event: DomainEventDef;
|
|
42
|
+
eventName: string;
|
|
43
|
+
payload: unknown;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface DomainEventRecorderPort {
|
|
47
|
+
record<E extends DomainEventDef>(
|
|
48
|
+
event: E,
|
|
49
|
+
payload: InferEventPayload<E>,
|
|
50
|
+
): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface BufferedDomainEventRecorder extends DomainEventRecorderPort {
|
|
54
|
+
entries(): readonly RecordedDomainEvent[];
|
|
55
|
+
clear(): void;
|
|
56
|
+
flush(eventBus: EventBusPort): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Create a simple Unit of Work implementation for tests, in-memory adapters,
|
|
61
|
+
* and infrastructure that already handles transactions elsewhere.
|
|
62
|
+
*
|
|
63
|
+
* This helper does not create database transactions. It gives applications the
|
|
64
|
+
* same UOW shape everywhere and runs commit/rollback hooks around the callback.
|
|
65
|
+
*/
|
|
66
|
+
export function createNoopUnitOfWork<TxPorts>(
|
|
67
|
+
txPortsOrFactory: TxPorts | (() => TxPorts),
|
|
68
|
+
options: NoopUnitOfWorkOptions<TxPorts> = {},
|
|
69
|
+
): UnitOfWorkPort<TxPorts> {
|
|
70
|
+
const createTxPorts =
|
|
71
|
+
typeof txPortsOrFactory === "function"
|
|
72
|
+
? (txPortsOrFactory as () => TxPorts)
|
|
73
|
+
: () => txPortsOrFactory;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
async transaction<Result>(
|
|
77
|
+
work: UnitOfWorkCallback<TxPorts, Result>,
|
|
78
|
+
): Promise<Result> {
|
|
79
|
+
const tx = createTxPorts();
|
|
80
|
+
|
|
81
|
+
let result: Result;
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
result = await work(tx);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
try {
|
|
87
|
+
await options.afterRollback?.(error, tx);
|
|
88
|
+
} catch {
|
|
89
|
+
// Preserve the application error that caused the rollback path.
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await options.afterCommit?.(tx);
|
|
96
|
+
return result;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Buffer domain events during a transaction and publish them only after the
|
|
103
|
+
* owning Unit of Work commits.
|
|
104
|
+
*/
|
|
105
|
+
export function createDomainEventRecorder(): BufferedDomainEventRecorder {
|
|
106
|
+
const records: RecordedDomainEvent[] = [];
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
record(event, payload) {
|
|
110
|
+
records.push({
|
|
111
|
+
event,
|
|
112
|
+
eventName: event.name,
|
|
113
|
+
payload,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
entries() {
|
|
118
|
+
return records;
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
clear() {
|
|
122
|
+
records.length = 0;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
async flush(eventBus) {
|
|
126
|
+
while (records.length > 0) {
|
|
127
|
+
const record = records[0];
|
|
128
|
+
const payload = await parseEventPayload(record.event, record.payload);
|
|
129
|
+
await eventBus.publish(record.event, payload);
|
|
130
|
+
records.shift();
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @beignet/core/providers
|
|
3
|
+
*
|
|
4
|
+
* Provider lifecycle and instrumentation primitives for Beignet.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
type BaseProviderInstrumentationEvent,
|
|
9
|
+
type CustomProviderInstrumentationEvent,
|
|
10
|
+
createProviderInstrumentation,
|
|
11
|
+
type ErrorProviderInstrumentationEvent,
|
|
12
|
+
type EventBusProviderInstrumentationEvent,
|
|
13
|
+
isProviderInstrumentation,
|
|
14
|
+
isProviderInstrumentationPort,
|
|
15
|
+
type JobProviderInstrumentationEvent,
|
|
16
|
+
type ProviderCustomInstrumentationEventInput,
|
|
17
|
+
type ProviderInstrumentation,
|
|
18
|
+
type ProviderInstrumentationEvent,
|
|
19
|
+
type ProviderInstrumentationEventInput,
|
|
20
|
+
type ProviderInstrumentationOptions,
|
|
21
|
+
type ProviderInstrumentationPort,
|
|
22
|
+
type ProviderInstrumentationTarget,
|
|
23
|
+
type ProviderInstrumentationWatcherName,
|
|
24
|
+
type ProviderLifecycleInstrumentationEvent,
|
|
25
|
+
type RequestProviderInstrumentationEvent,
|
|
26
|
+
resolveProviderInstrumentationPort,
|
|
27
|
+
type ScheduleProviderInstrumentationEvent,
|
|
28
|
+
type UseCaseProviderInstrumentationEvent,
|
|
29
|
+
} from "./instrumentation";
|
|
30
|
+
export {
|
|
31
|
+
createProvider,
|
|
32
|
+
type InferOutput,
|
|
33
|
+
type MaybePromise,
|
|
34
|
+
type ProvidedPortsOf,
|
|
35
|
+
type ProvidedPortsOfList,
|
|
36
|
+
type ProviderConfigDef,
|
|
37
|
+
type ProviderLifecycleContext,
|
|
38
|
+
type ProviderSetupResult,
|
|
39
|
+
type ServiceProvider,
|
|
40
|
+
} from "./provider";
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { type Redactor, redactValue } from "../ports/redaction";
|
|
2
|
+
|
|
3
|
+
export type ProviderInstrumentationWatcherName = string;
|
|
4
|
+
|
|
5
|
+
export interface BaseProviderInstrumentationEvent {
|
|
6
|
+
id?: string;
|
|
7
|
+
timestamp?: string;
|
|
8
|
+
requestId?: string;
|
|
9
|
+
traceId?: string;
|
|
10
|
+
spanId?: string;
|
|
11
|
+
parentSpanId?: string;
|
|
12
|
+
traceparent?: string;
|
|
13
|
+
watcher?: ProviderInstrumentationWatcherName;
|
|
14
|
+
details?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RequestProviderInstrumentationEvent
|
|
18
|
+
extends BaseProviderInstrumentationEvent {
|
|
19
|
+
type: "request";
|
|
20
|
+
method: string;
|
|
21
|
+
path: string;
|
|
22
|
+
contractName?: string;
|
|
23
|
+
status?: number;
|
|
24
|
+
durationMs?: number;
|
|
25
|
+
summary?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ErrorProviderInstrumentationEvent
|
|
29
|
+
extends BaseProviderInstrumentationEvent {
|
|
30
|
+
type: "error";
|
|
31
|
+
message: string;
|
|
32
|
+
stack?: string;
|
|
33
|
+
contractName?: string;
|
|
34
|
+
useCaseName?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface UseCaseProviderInstrumentationEvent
|
|
38
|
+
extends BaseProviderInstrumentationEvent {
|
|
39
|
+
type: "usecase";
|
|
40
|
+
name: string;
|
|
41
|
+
kind?: "command" | "query";
|
|
42
|
+
phase: "start" | "end" | "error";
|
|
43
|
+
durationMs?: number;
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface EventBusProviderInstrumentationEvent
|
|
48
|
+
extends BaseProviderInstrumentationEvent {
|
|
49
|
+
type: "eventBus";
|
|
50
|
+
eventName: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface JobProviderInstrumentationEvent
|
|
54
|
+
extends BaseProviderInstrumentationEvent {
|
|
55
|
+
type: "job";
|
|
56
|
+
jobName: string;
|
|
57
|
+
status: "scheduled" | "started" | "completed" | "failed";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ScheduleProviderInstrumentationEvent
|
|
61
|
+
extends BaseProviderInstrumentationEvent {
|
|
62
|
+
type: "schedule";
|
|
63
|
+
scheduleName: string;
|
|
64
|
+
status: "started" | "completed" | "failed";
|
|
65
|
+
cron?: string;
|
|
66
|
+
timezone?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ProviderLifecycleInstrumentationEvent
|
|
70
|
+
extends BaseProviderInstrumentationEvent {
|
|
71
|
+
type: "provider";
|
|
72
|
+
providerName: string;
|
|
73
|
+
action: "setup" | "start" | "stop";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface CustomProviderInstrumentationEvent
|
|
77
|
+
extends BaseProviderInstrumentationEvent {
|
|
78
|
+
type: "custom";
|
|
79
|
+
name: string;
|
|
80
|
+
label?: string;
|
|
81
|
+
summary?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type ProviderInstrumentationEvent =
|
|
85
|
+
| RequestProviderInstrumentationEvent
|
|
86
|
+
| ErrorProviderInstrumentationEvent
|
|
87
|
+
| UseCaseProviderInstrumentationEvent
|
|
88
|
+
| EventBusProviderInstrumentationEvent
|
|
89
|
+
| JobProviderInstrumentationEvent
|
|
90
|
+
| ScheduleProviderInstrumentationEvent
|
|
91
|
+
| ProviderLifecycleInstrumentationEvent
|
|
92
|
+
| CustomProviderInstrumentationEvent;
|
|
93
|
+
|
|
94
|
+
export type ProviderInstrumentationEventInput = ProviderInstrumentationEvent;
|
|
95
|
+
|
|
96
|
+
export type ProviderCustomInstrumentationEventInput = Omit<
|
|
97
|
+
CustomProviderInstrumentationEvent,
|
|
98
|
+
"type"
|
|
99
|
+
>;
|
|
100
|
+
|
|
101
|
+
export interface ProviderInstrumentationPort<
|
|
102
|
+
EventInput extends
|
|
103
|
+
ProviderInstrumentationEventInput = ProviderInstrumentationEventInput,
|
|
104
|
+
WatcherName extends string = ProviderInstrumentationWatcherName,
|
|
105
|
+
RecordResult = unknown,
|
|
106
|
+
> {
|
|
107
|
+
record(event: EventInput): RecordResult;
|
|
108
|
+
isWatcherEnabled?(name: WatcherName): boolean;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface ProviderInstrumentationOptions {
|
|
112
|
+
providerName: string;
|
|
113
|
+
watcher?: ProviderInstrumentationWatcherName;
|
|
114
|
+
redact?: Redactor<ProviderInstrumentationEventInput>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ProviderInstrumentation {
|
|
118
|
+
port: ProviderInstrumentationPort | undefined;
|
|
119
|
+
isEnabled(watcher?: ProviderInstrumentationWatcherName): boolean;
|
|
120
|
+
record(event: ProviderInstrumentationEventInput): unknown;
|
|
121
|
+
custom(event: ProviderCustomInstrumentationEventInput): unknown;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type ProviderInstrumentationTarget =
|
|
125
|
+
| ProviderInstrumentationPort
|
|
126
|
+
| ProviderInstrumentation
|
|
127
|
+
| {
|
|
128
|
+
devtools?: ProviderInstrumentationPort | ProviderInstrumentation;
|
|
129
|
+
instrumentation?: ProviderInstrumentationPort | ProviderInstrumentation;
|
|
130
|
+
}
|
|
131
|
+
| undefined;
|
|
132
|
+
|
|
133
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
134
|
+
return typeof value === "object" && value !== null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function isProviderInstrumentation(
|
|
138
|
+
value: unknown,
|
|
139
|
+
): value is ProviderInstrumentation {
|
|
140
|
+
return (
|
|
141
|
+
isObject(value) &&
|
|
142
|
+
typeof value.record === "function" &&
|
|
143
|
+
typeof value.custom === "function" &&
|
|
144
|
+
typeof value.isEnabled === "function"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function isProviderInstrumentationPort(
|
|
149
|
+
value: unknown,
|
|
150
|
+
): value is ProviderInstrumentationPort {
|
|
151
|
+
return isObject(value) && typeof value.record === "function";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function resolveProviderInstrumentationValue(
|
|
155
|
+
value: unknown,
|
|
156
|
+
): ProviderInstrumentationPort | undefined {
|
|
157
|
+
if (isProviderInstrumentation(value)) return value.port;
|
|
158
|
+
if (isProviderInstrumentationPort(value)) return value;
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function resolveProviderInstrumentationPort(
|
|
163
|
+
target: ProviderInstrumentationTarget,
|
|
164
|
+
): ProviderInstrumentationPort | undefined {
|
|
165
|
+
if (!target) return undefined;
|
|
166
|
+
|
|
167
|
+
const directPort = resolveProviderInstrumentationValue(target);
|
|
168
|
+
if (directPort) return directPort;
|
|
169
|
+
|
|
170
|
+
if (!isObject(target)) return undefined;
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
resolveProviderInstrumentationValue(target.instrumentation) ??
|
|
174
|
+
resolveProviderInstrumentationValue(target.devtools)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function withProviderDetails(providerName: string, details: unknown): unknown {
|
|
179
|
+
if (details === undefined) {
|
|
180
|
+
return { providerName };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (isObject(details) && !Array.isArray(details)) {
|
|
184
|
+
return { ...details, providerName };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { providerName, value: details };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function createProviderInstrumentation(
|
|
191
|
+
target: ProviderInstrumentationTarget,
|
|
192
|
+
options: ProviderInstrumentationOptions,
|
|
193
|
+
): ProviderInstrumentation {
|
|
194
|
+
if (isProviderInstrumentation(target)) {
|
|
195
|
+
return target;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const port = resolveProviderInstrumentationPort(target);
|
|
199
|
+
|
|
200
|
+
function isEnabled(watcher = options.watcher): boolean {
|
|
201
|
+
if (!port) return false;
|
|
202
|
+
if (!watcher) return true;
|
|
203
|
+
return port.isWatcherEnabled?.(watcher) ?? true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function record(event: ProviderInstrumentationEventInput): unknown {
|
|
207
|
+
if (!port) return undefined;
|
|
208
|
+
|
|
209
|
+
const watcher = event.watcher ?? options.watcher;
|
|
210
|
+
if (watcher && !isEnabled(watcher)) return undefined;
|
|
211
|
+
|
|
212
|
+
const eventWithWatcher =
|
|
213
|
+
options.watcher && event.watcher === undefined
|
|
214
|
+
? { ...event, watcher: options.watcher }
|
|
215
|
+
: event;
|
|
216
|
+
|
|
217
|
+
let redacted: ProviderInstrumentationEventInput;
|
|
218
|
+
try {
|
|
219
|
+
redacted = options.redact
|
|
220
|
+
? options.redact(redactValue(eventWithWatcher))
|
|
221
|
+
: redactValue(eventWithWatcher);
|
|
222
|
+
} catch {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
return port.record(redacted);
|
|
228
|
+
} catch {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function custom(event: ProviderCustomInstrumentationEventInput): unknown {
|
|
234
|
+
return record({
|
|
235
|
+
...event,
|
|
236
|
+
type: "custom",
|
|
237
|
+
watcher: event.watcher ?? options.watcher,
|
|
238
|
+
details: withProviderDetails(options.providerName, event.details),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
port,
|
|
244
|
+
isEnabled,
|
|
245
|
+
record,
|
|
246
|
+
custom,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider system for Beignet
|
|
3
|
+
*
|
|
4
|
+
* Providers are modular extensions that can add new ports or replace existing ones
|
|
5
|
+
* during application initialization. They support configuration via Standard Schema
|
|
6
|
+
* and optional lifecycle hooks.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
10
|
+
|
|
11
|
+
type ProviderPorts = Record<string, unknown>;
|
|
12
|
+
declare const noProvidedPorts: unique symbol;
|
|
13
|
+
type NoProvidedPorts = { [noProvidedPorts]?: never };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extract the output type from a Standard Schema.
|
|
17
|
+
* This is the validated/parsed type that results from schema validation.
|
|
18
|
+
*/
|
|
19
|
+
export type InferOutput<T extends StandardSchemaV1> =
|
|
20
|
+
StandardSchemaV1.InferOutput<T>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configuration definition for a service provider.
|
|
24
|
+
* Specifies the schema for validating config and optional environment variable prefix.
|
|
25
|
+
*/
|
|
26
|
+
export interface ProviderConfigDef<CfgSchema extends StandardSchemaV1> {
|
|
27
|
+
/**
|
|
28
|
+
* Standard Schema for validating provider configuration.
|
|
29
|
+
* Can be Zod, Valibot, ArkType, or any Standard Schema compatible library.
|
|
30
|
+
*/
|
|
31
|
+
schema: CfgSchema;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Optional prefix to read env vars, e.g. "REDIS_".
|
|
35
|
+
* When provided, the implementation will read process.env keys starting with this prefix
|
|
36
|
+
* and pass them to the schema for validation.
|
|
37
|
+
*/
|
|
38
|
+
envPrefix?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
42
|
+
|
|
43
|
+
export type ProviderLifecycleContext = {
|
|
44
|
+
ports: Readonly<ProviderPorts>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type ProviderSetupResult<ProvidedPorts extends ProviderPorts> = {
|
|
48
|
+
/**
|
|
49
|
+
* Ports contributed by this provider.
|
|
50
|
+
* Keys overwrite earlier ports with the same name at runtime. Prefer unique
|
|
51
|
+
* keys unless the replacement implements the same port contract.
|
|
52
|
+
*/
|
|
53
|
+
ports?: ProvidedPorts;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Optional hook called after all providers have contributed their ports.
|
|
57
|
+
*/
|
|
58
|
+
start?: (ctx: ProviderLifecycleContext) => MaybePromise<void>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Optional hook called when the server is stopped.
|
|
62
|
+
*/
|
|
63
|
+
stop?: (ctx: ProviderLifecycleContext) => MaybePromise<void>;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A service provider that can extend or replace ports during app initialization.
|
|
68
|
+
*
|
|
69
|
+
* Providers support:
|
|
70
|
+
* - Configuration via Standard Schema (any compatible library: Zod, Valibot, etc.)
|
|
71
|
+
* - Returning ports with new capabilities (e.g., cache, mailer)
|
|
72
|
+
* - Replacing existing ports by returning the same key
|
|
73
|
+
* - Optional start/stop hooks
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* const redisProvider = createProvider({
|
|
78
|
+
* name: "redis",
|
|
79
|
+
* config: {
|
|
80
|
+
* schema: z.object({ URL: z.string().url() }),
|
|
81
|
+
* envPrefix: "REDIS_",
|
|
82
|
+
* },
|
|
83
|
+
* async setup({ config }) {
|
|
84
|
+
* const client = new Redis(config.URL);
|
|
85
|
+
* return {
|
|
86
|
+
* ports: {
|
|
87
|
+
* cache: {
|
|
88
|
+
* get: (key) => client.get(key),
|
|
89
|
+
* set: (key, value) => client.set(key, value),
|
|
90
|
+
* },
|
|
91
|
+
* },
|
|
92
|
+
* stop: () => client.quit(),
|
|
93
|
+
* };
|
|
94
|
+
* },
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export interface ServiceProvider<
|
|
99
|
+
Ports,
|
|
100
|
+
CfgSchema extends StandardSchemaV1 = StandardSchemaV1<void, void>,
|
|
101
|
+
ProvidedPorts extends ProviderPorts = NoProvidedPorts,
|
|
102
|
+
> {
|
|
103
|
+
/**
|
|
104
|
+
* Unique name for this provider (used for logging/debugging)
|
|
105
|
+
*/
|
|
106
|
+
name: string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Optional configuration definition.
|
|
110
|
+
* If provided, the config will be loaded and validated before calling setup.
|
|
111
|
+
*/
|
|
112
|
+
config?: ProviderConfigDef<CfgSchema>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Setup phase: create the ports this provider contributes.
|
|
116
|
+
* Called during app initialization, before routes are registered.
|
|
117
|
+
*
|
|
118
|
+
* @param ctx.ports - Ports contributed by previous providers
|
|
119
|
+
* @param ctx.config - Validated config (if config was defined), or undefined
|
|
120
|
+
*/
|
|
121
|
+
setup(ctx: {
|
|
122
|
+
ports: Readonly<Ports>;
|
|
123
|
+
config: InferOutput<CfgSchema> | undefined;
|
|
124
|
+
}): MaybePromise<ProviderSetupResult<ProvidedPorts>>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Type-only marker for ports this provider contributes.
|
|
128
|
+
* Runtime provider objects do not need to set this property.
|
|
129
|
+
*/
|
|
130
|
+
readonly __providedPorts?: ProvidedPorts;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Extract the ports a provider contributes.
|
|
135
|
+
*/
|
|
136
|
+
export type ProvidedPortsOf<TProvider> =
|
|
137
|
+
TProvider extends ServiceProvider<
|
|
138
|
+
infer _Ports,
|
|
139
|
+
infer _CfgSchema,
|
|
140
|
+
infer ProvidedPorts
|
|
141
|
+
>
|
|
142
|
+
? ProvidedPorts
|
|
143
|
+
: NoProvidedPorts;
|
|
144
|
+
|
|
145
|
+
type UnionToIntersection<T> = (
|
|
146
|
+
T extends unknown
|
|
147
|
+
? (value: T) => void
|
|
148
|
+
: never
|
|
149
|
+
) extends (value: infer I) => void
|
|
150
|
+
? I
|
|
151
|
+
: never;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Extract and merge the ports contributed by a provider list.
|
|
155
|
+
*/
|
|
156
|
+
export type ProvidedPortsOfList<TProviders> =
|
|
157
|
+
TProviders extends readonly unknown[]
|
|
158
|
+
? [TProviders[number]] extends [never]
|
|
159
|
+
? NoProvidedPorts
|
|
160
|
+
: UnionToIntersection<ProvidedPortsOf<TProviders[number]>>
|
|
161
|
+
: NoProvidedPorts;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Helper function to create a provider with proper type inference.
|
|
165
|
+
*
|
|
166
|
+
* This is a simple identity function that helps TypeScript infer the correct types
|
|
167
|
+
* for the provider definition.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* export const myProvider = createProvider({
|
|
172
|
+
* name: "my-provider",
|
|
173
|
+
* config: {
|
|
174
|
+
* schema: z.object({ apiKey: z.string() }),
|
|
175
|
+
* envPrefix: "MY_SERVICE_",
|
|
176
|
+
* },
|
|
177
|
+
* async setup({ config }) {
|
|
178
|
+
* return { ports: { myService: createMyService(config) } };
|
|
179
|
+
* },
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function createProvider<
|
|
184
|
+
Ports = unknown,
|
|
185
|
+
CfgSchema extends StandardSchemaV1 = StandardSchemaV1<void, void>,
|
|
186
|
+
ProvidedPorts extends ProviderPorts = NoProvidedPorts,
|
|
187
|
+
>(
|
|
188
|
+
def: ServiceProvider<Ports, CfgSchema, ProvidedPorts>,
|
|
189
|
+
): ServiceProvider<Ports, CfgSchema, ProvidedPorts> {
|
|
190
|
+
return def;
|
|
191
|
+
}
|