@beignet/core 0.0.3 → 0.0.4
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 +157 -0
- package/README.md +785 -43
- package/dist/application/index.d.ts +28 -2
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +140 -12
- package/dist/application/index.js.map +1 -1
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +136 -48
- package/dist/client/client.js.map +1 -1
- package/dist/client/error-messages.d.ts +14 -0
- package/dist/client/error-messages.d.ts.map +1 -0
- package/dist/client/error-messages.js +23 -0
- package/dist/client/error-messages.js.map +1 -0
- package/dist/client/index.d.ts +8 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +35 -5
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client-only.d.ts +8 -0
- package/dist/client-only.d.ts.map +1 -0
- package/dist/client-only.js +8 -0
- package/dist/client-only.js.map +1 -0
- package/dist/config/index.d.ts +5 -5
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -2
- package/dist/config/index.js.map +1 -1
- package/dist/contracts/catalog-errors.d.ts +27 -0
- package/dist/contracts/catalog-errors.d.ts.map +1 -0
- package/dist/contracts/catalog-errors.js +69 -0
- package/dist/contracts/catalog-errors.js.map +1 -0
- package/dist/contracts/contract-builder.d.ts +15 -12
- package/dist/contracts/contract-builder.d.ts.map +1 -1
- package/dist/contracts/contract-builder.js +15 -41
- package/dist/contracts/contract-builder.js.map +1 -1
- package/dist/contracts/contract-group.d.ts +11 -8
- package/dist/contracts/contract-group.d.ts.map +1 -1
- package/dist/contracts/contract-group.js +13 -40
- package/dist/contracts/contract-group.js.map +1 -1
- package/dist/contracts/contract-like.d.ts +1 -1
- package/dist/contracts/contract-like.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +13 -9
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +9 -5
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/openapi-meta.d.ts +48 -0
- package/dist/contracts/openapi-meta.d.ts.map +1 -1
- package/dist/contracts/openapi-meta.js +3 -0
- package/dist/contracts/openapi-meta.js.map +1 -1
- package/dist/contracts/path-template.d.ts +1 -1
- package/dist/contracts/path-template.js +2 -2
- package/dist/contracts/path-template.js.map +1 -1
- package/dist/contracts/schema-shape.d.ts +37 -0
- package/dist/contracts/schema-shape.d.ts.map +1 -0
- package/dist/contracts/schema-shape.js +61 -0
- package/dist/contracts/schema-shape.js.map +1 -0
- package/dist/contracts/success-status.d.ts +32 -0
- package/dist/contracts/success-status.d.ts.map +1 -0
- package/dist/contracts/success-status.js +18 -0
- package/dist/contracts/success-status.js.map +1 -0
- package/dist/contracts/types.d.ts +25 -5
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js.map +1 -1
- package/dist/contracts/utils.d.ts +1 -1
- package/dist/contracts/utils.d.ts.map +1 -1
- package/dist/contracts/utils.js +1 -1
- package/dist/contracts/utils.js.map +1 -1
- package/dist/domain/events.d.ts +1 -1
- package/dist/domain/events.d.ts.map +1 -1
- package/dist/domain/events.js +1 -1
- package/dist/domain/events.js.map +1 -1
- package/dist/domain/index.d.ts +3 -3
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +3 -3
- package/dist/domain/index.js.map +1 -1
- package/dist/errors/catalog.d.ts +9 -1
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +7 -1
- package/dist/errors/catalog.js.map +1 -1
- package/dist/errors/http.d.ts +10 -0
- package/dist/errors/http.d.ts.map +1 -1
- package/dist/errors/http.js +11 -1
- package/dist/errors/http.js.map +1 -1
- package/dist/errors/index.d.ts +4 -4
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/response.d.ts +4 -1
- package/dist/errors/response.d.ts.map +1 -1
- package/dist/errors/response.js.map +1 -1
- package/dist/events/index.d.ts +10 -12
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +10 -10
- package/dist/events/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +5 -3
- package/dist/idempotency/index.d.ts.map +1 -1
- package/dist/idempotency/index.js.map +1 -1
- package/dist/jobs/index.d.ts +12 -14
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +13 -13
- package/dist/jobs/index.js.map +1 -1
- package/dist/notifications/index.d.ts +14 -16
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +14 -14
- package/dist/notifications/index.js.map +1 -1
- package/dist/openapi/index.d.ts +8 -3
- package/dist/openapi/index.d.ts.map +1 -1
- package/dist/openapi/index.js +41 -29
- package/dist/openapi/index.js.map +1 -1
- package/dist/openapi/schema-introspector.d.ts +37 -0
- package/dist/openapi/schema-introspector.d.ts.map +1 -1
- package/dist/openapi/schema-introspector.js +23 -17
- package/dist/openapi/schema-introspector.js.map +1 -1
- package/dist/outbox/index.d.ts +15 -6
- package/dist/outbox/index.d.ts.map +1 -1
- package/dist/outbox/index.js +60 -16
- package/dist/outbox/index.js.map +1 -1
- package/dist/ports/audit.d.ts +56 -10
- package/dist/ports/audit.d.ts.map +1 -1
- package/dist/ports/audit.js +71 -3
- package/dist/ports/audit.js.map +1 -1
- package/dist/ports/auth.d.ts +92 -0
- package/dist/ports/auth.d.ts.map +1 -1
- package/dist/ports/auth.js +92 -0
- package/dist/ports/auth.js.map +1 -1
- package/dist/ports/events.d.ts +2 -2
- package/dist/ports/events.d.ts.map +1 -1
- package/dist/ports/index.d.ts +62 -33
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +28 -34
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/policy.d.ts +32 -3
- package/dist/ports/policy.d.ts.map +1 -1
- package/dist/ports/policy.js +13 -2
- package/dist/ports/policy.js.map +1 -1
- package/dist/ports/testing.d.ts +1030 -2
- package/dist/ports/testing.d.ts.map +1 -1
- package/dist/ports/testing.js +1031 -1
- package/dist/ports/testing.js.map +1 -1
- package/dist/ports/unbound.d.ts +21 -0
- package/dist/ports/unbound.d.ts.map +1 -0
- package/dist/ports/unbound.js +57 -0
- package/dist/ports/unbound.js.map +1 -0
- package/dist/ports/unit-of-work.d.ts +1 -1
- package/dist/ports/unit-of-work.d.ts.map +1 -1
- package/dist/ports/unit-of-work.js +1 -1
- package/dist/ports/unit-of-work.js.map +1 -1
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/instrumentation.d.ts +45 -4
- package/dist/providers/instrumentation.d.ts.map +1 -1
- package/dist/providers/instrumentation.js +25 -6
- package/dist/providers/instrumentation.js.map +1 -1
- package/dist/providers/metadata.d.ts +39 -0
- package/dist/providers/metadata.d.ts.map +1 -0
- package/dist/providers/metadata.js +169 -0
- package/dist/providers/metadata.js.map +1 -0
- package/dist/providers/provider.d.ts +114 -9
- package/dist/providers/provider.d.ts.map +1 -1
- package/dist/providers/provider.js +3 -20
- package/dist/providers/provider.js.map +1 -1
- package/dist/schedules/index.d.ts +94 -13
- package/dist/schedules/index.d.ts.map +1 -1
- package/dist/schedules/index.js +66 -12
- package/dist/schedules/index.js.map +1 -1
- package/dist/server/audit-context.d.ts +29 -0
- package/dist/server/audit-context.d.ts.map +1 -0
- package/dist/server/audit-context.js +44 -0
- package/dist/server/audit-context.js.map +1 -0
- package/dist/server/context.d.ts +141 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +39 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/contract-like.d.ts +1 -1
- package/dist/server/contract-like.d.ts.map +1 -1
- package/dist/server/contract-like.js +1 -1
- package/dist/server/contract-like.js.map +1 -1
- package/dist/server/health.d.ts +2 -2
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/hooks/auth.d.ts +49 -10
- package/dist/server/hooks/auth.d.ts.map +1 -1
- package/dist/server/hooks/auth.js +77 -37
- package/dist/server/hooks/auth.js.map +1 -1
- package/dist/server/hooks/cors.d.ts +1 -1
- package/dist/server/hooks/cors.d.ts.map +1 -1
- package/dist/server/hooks/errors.d.ts +2 -2
- package/dist/server/hooks/errors.d.ts.map +1 -1
- package/dist/server/hooks/errors.js +2 -2
- package/dist/server/hooks/errors.js.map +1 -1
- package/dist/server/hooks/idempotency.d.ts +78 -0
- package/dist/server/hooks/idempotency.d.ts.map +1 -0
- package/dist/server/hooks/idempotency.js +154 -0
- package/dist/server/hooks/idempotency.js.map +1 -0
- package/dist/server/hooks/index.d.ts +8 -7
- package/dist/server/hooks/index.d.ts.map +1 -1
- package/dist/server/hooks/index.js +6 -5
- package/dist/server/hooks/index.js.map +1 -1
- package/dist/server/hooks/logging.d.ts +2 -2
- package/dist/server/hooks/logging.d.ts.map +1 -1
- package/dist/server/hooks/logging.js +1 -1
- package/dist/server/hooks/logging.js.map +1 -1
- package/dist/server/hooks/rate-limit.d.ts +25 -7
- package/dist/server/hooks/rate-limit.d.ts.map +1 -1
- package/dist/server/hooks/rate-limit.js +47 -12
- package/dist/server/hooks/rate-limit.js.map +1 -1
- package/dist/server/hooks.d.ts +1 -1
- package/dist/server/hooks.d.ts.map +1 -1
- package/dist/server/hooks.js +1 -1
- package/dist/server/hooks.js.map +1 -1
- package/dist/server/http.d.ts +61 -35
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +1 -20
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.d.ts +36 -12
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +24 -8
- package/dist/server/index.js.map +1 -1
- package/dist/server/instrumentation.d.ts +108 -0
- package/dist/server/instrumentation.d.ts.map +1 -0
- package/dist/server/instrumentation.js +297 -0
- package/dist/server/instrumentation.js.map +1 -0
- package/dist/server/openapi.d.ts +3 -3
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/openapi.js +1 -1
- package/dist/server/openapi.js.map +1 -1
- package/dist/server/providers/index.d.ts +3 -3
- package/dist/server/providers/index.d.ts.map +1 -1
- package/dist/server/providers/index.js +3 -3
- package/dist/server/providers/index.js.map +1 -1
- package/dist/server/providers/loadProviderConfig.d.ts +2 -2
- package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
- package/dist/server/providers/loadProviderConfig.js +2 -2
- package/dist/server/providers/loadProviderConfig.js.map +1 -1
- package/dist/server/request-context.d.ts +67 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +79 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/server-context.d.ts +38 -0
- package/dist/server/server-context.d.ts.map +1 -0
- package/dist/server/server-context.js +38 -0
- package/dist/server/server-context.js.map +1 -0
- package/dist/server/server.d.ts +105 -33
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +434 -118
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +2 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +2 -2
- package/dist/server/types.js.map +1 -1
- package/dist/server/use-case-route.d.ts +263 -0
- package/dist/server/use-case-route.d.ts.map +1 -0
- package/dist/server/use-case-route.js +77 -0
- package/dist/server/use-case-route.js.map +1 -0
- package/dist/server-only.d.ts +8 -0
- package/dist/server-only.d.ts.map +1 -0
- package/dist/server-only.js +8 -0
- package/dist/server-only.js.map +1 -0
- package/dist/tasks/index.d.ts +139 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +98 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/testing/index.d.ts +607 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +426 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/tracing/index.d.ts +89 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +101 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/uploads/client.d.ts +1 -1
- package/dist/uploads/client.d.ts.map +1 -1
- package/dist/uploads/index.d.ts +2 -2
- package/dist/uploads/index.d.ts.map +1 -1
- package/dist/uploads/index.js +1 -1
- package/dist/uploads/index.js.map +1 -1
- package/package.json +24 -2
- package/src/application/index.ts +193 -10
- package/src/client/client.ts +148 -150
- package/src/client/error-messages.ts +35 -0
- package/src/client/index.ts +12 -4
- package/src/client/types.ts +44 -5
- package/src/client-only.ts +7 -0
- package/src/config/index.ts +6 -6
- package/src/contracts/catalog-errors.ts +115 -0
- package/src/contracts/contract-builder.ts +39 -76
- package/src/contracts/contract-group.ts +33 -68
- package/src/contracts/contract-like.ts +1 -1
- package/src/contracts/index.ts +24 -11
- package/src/contracts/openapi-meta.ts +55 -0
- package/src/contracts/path-template.ts +2 -2
- package/src/contracts/schema-shape.ts +75 -0
- package/src/contracts/success-status.ts +68 -0
- package/src/contracts/types.ts +32 -5
- package/src/contracts/utils.ts +5 -2
- package/src/domain/events.ts +6 -2
- package/src/domain/index.ts +3 -3
- package/src/errors/catalog.ts +9 -1
- package/src/errors/http.ts +11 -1
- package/src/errors/index.ts +4 -4
- package/src/errors/response.ts +4 -1
- package/src/events/index.ts +12 -26
- package/src/idempotency/index.ts +5 -3
- package/src/jobs/index.ts +14 -24
- package/src/notifications/index.ts +17 -27
- package/src/openapi/index.ts +73 -38
- package/src/openapi/schema-introspector.ts +68 -17
- package/src/outbox/index.ts +84 -19
- package/src/ports/audit.ts +120 -11
- package/src/ports/auth.ts +132 -0
- package/src/ports/events.ts +2 -2
- package/src/ports/index.ts +104 -35
- package/src/ports/policy.ts +50 -3
- package/src/ports/testing.ts +2220 -33
- package/src/ports/unbound.ts +64 -0
- package/src/ports/unit-of-work.ts +6 -2
- package/src/providers/index.ts +16 -3
- package/src/providers/instrumentation.ts +86 -7
- package/src/providers/metadata.ts +234 -0
- package/src/providers/provider.ts +168 -9
- package/src/schedules/index.ts +173 -23
- package/src/server/audit-context.ts +45 -0
- package/src/server/context.ts +224 -0
- package/src/server/contract-like.ts +1 -1
- package/src/server/health.ts +2 -2
- package/src/server/hooks/auth.ts +141 -51
- package/src/server/hooks/cors.ts +1 -1
- package/src/server/hooks/errors.ts +7 -4
- package/src/server/hooks/idempotency.ts +263 -0
- package/src/server/hooks/index.ts +14 -7
- package/src/server/hooks/logging.ts +3 -3
- package/src/server/hooks/rate-limit.ts +85 -17
- package/src/server/hooks.ts +1 -1
- package/src/server/http.ts +78 -51
- package/src/server/index.ts +62 -12
- package/src/server/instrumentation.ts +470 -0
- package/src/server/openapi.ts +4 -4
- package/src/server/providers/index.ts +6 -3
- package/src/server/providers/loadProviderConfig.ts +4 -4
- package/src/server/request-context.ts +116 -0
- package/src/server/server-context.ts +44 -0
- package/src/server/server.ts +886 -238
- package/src/server/types.ts +2 -2
- package/src/server/use-case-route.ts +430 -0
- package/src/server-only.ts +7 -0
- package/src/tasks/index.ts +275 -0
- package/src/testing/index.ts +1142 -6
- package/src/tracing/index.ts +176 -0
- package/src/uploads/client.ts +1 -1
- package/src/uploads/index.ts +7 -3
- package/dist/ports/mailer.d.ts +0 -6
- package/dist/ports/mailer.d.ts.map +0 -1
- package/dist/ports/mailer.js +0 -2
- package/dist/ports/mailer.js.map +0 -1
- package/dist/ports/schedules.d.ts +0 -9
- package/dist/ports/schedules.d.ts.map +0 -1
- package/dist/ports/schedules.js +0 -2
- package/dist/ports/schedules.js.map +0 -1
package/src/ports/auth.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ActivityTenant } from "./audit.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Minimal request shape consumed by Beignet auth ports.
|
|
3
5
|
*
|
|
@@ -41,6 +43,136 @@ export class AuthUnauthorizedError extends Error {
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Error thrown by tenant helpers when a workflow requires a tenant scope but
|
|
48
|
+
* the current context has none.
|
|
49
|
+
*
|
|
50
|
+
* The server maps this to a framework-owned 403 response, mirroring how
|
|
51
|
+
* `AuthUnauthorizedError` maps to a framework-owned 401.
|
|
52
|
+
*/
|
|
53
|
+
export class TenantRequiredError extends Error {
|
|
54
|
+
readonly code = "TENANT_REQUIRED";
|
|
55
|
+
readonly status = 403;
|
|
56
|
+
|
|
57
|
+
constructor(message = "A tenant is required for this action.") {
|
|
58
|
+
super(message);
|
|
59
|
+
this.name = "TenantRequiredError";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Options accepted by the `requireX(ctx)` context helpers.
|
|
65
|
+
*/
|
|
66
|
+
export interface RequireOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Create the error to throw instead of the framework default.
|
|
69
|
+
*/
|
|
70
|
+
error?: () => unknown;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function throwRequired(
|
|
74
|
+
options: RequireOptions | undefined,
|
|
75
|
+
fallback: () => Error,
|
|
76
|
+
): never {
|
|
77
|
+
throw options?.error ? options.error() : fallback();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Return the authenticated session from `ctx.auth` or throw.
|
|
82
|
+
*
|
|
83
|
+
* Throws `AuthUnauthorizedError` (a framework-owned 401) by default. Pass
|
|
84
|
+
* `options.error` to throw an app-owned error instead.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const session = requireSession(ctx);
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export function requireSession<Session extends AuthSession>(
|
|
92
|
+
ctx: { auth?: Session | null },
|
|
93
|
+
options?: RequireOptions,
|
|
94
|
+
): Session {
|
|
95
|
+
if (!ctx.auth) {
|
|
96
|
+
throwRequired(options, () => new AuthUnauthorizedError());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return ctx.auth;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Return the authenticated user from `ctx.auth` or throw.
|
|
104
|
+
*
|
|
105
|
+
* The user type is inferred from the app's `ctx.auth` session. Throws
|
|
106
|
+
* `AuthUnauthorizedError` (a framework-owned 401) by default.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const user = requireUser(ctx);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export function requireUser<User>(
|
|
114
|
+
ctx: { auth?: AuthSession<User> | null },
|
|
115
|
+
options?: RequireOptions,
|
|
116
|
+
): User {
|
|
117
|
+
return requireSession(ctx, options).user;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Return the authenticated user's ID from `ctx.auth` or throw.
|
|
122
|
+
*
|
|
123
|
+
* Throws `AuthUnauthorizedError` (a framework-owned 401) by default.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* const userId = requireUserId(ctx);
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export function requireUserId(
|
|
131
|
+
ctx: { auth?: AuthSession<{ id: string }> | null },
|
|
132
|
+
options?: RequireOptions,
|
|
133
|
+
): string {
|
|
134
|
+
return requireUser(ctx, options).id;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Return the tenant scope from `ctx.tenant` or throw.
|
|
139
|
+
*
|
|
140
|
+
* Throws `TenantRequiredError` (a framework-owned 403) by default. Pass
|
|
141
|
+
* `options.error` to throw an app-owned error instead.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const tenant = requireTenant(ctx);
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export function requireTenant(
|
|
149
|
+
ctx: { tenant?: ActivityTenant | null },
|
|
150
|
+
options?: RequireOptions,
|
|
151
|
+
): ActivityTenant {
|
|
152
|
+
if (!ctx.tenant) {
|
|
153
|
+
throwRequired(options, () => new TenantRequiredError());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return ctx.tenant;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Return the tenant ID from `ctx.tenant` or throw.
|
|
161
|
+
*
|
|
162
|
+
* Throws `TenantRequiredError` (a framework-owned 403) by default.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* const tenantId = requireTenantId(ctx);
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export function requireTenantId(
|
|
170
|
+
ctx: { tenant?: ActivityTenant | null },
|
|
171
|
+
options?: RequireOptions,
|
|
172
|
+
): string {
|
|
173
|
+
return requireTenant(ctx, options).id;
|
|
174
|
+
}
|
|
175
|
+
|
|
44
176
|
/**
|
|
45
177
|
* App-facing authentication port.
|
|
46
178
|
*
|
package/src/ports/events.ts
CHANGED
|
@@ -2,11 +2,11 @@ import type {
|
|
|
2
2
|
EventPayloadDef,
|
|
3
3
|
InferEventPayload as InferContractEventPayload,
|
|
4
4
|
StandardSchema,
|
|
5
|
-
} from "../events";
|
|
5
|
+
} from "../events/index.js";
|
|
6
6
|
import type {
|
|
7
7
|
JobDef as ContractJobDef,
|
|
8
8
|
InferJobPayload as InferContractJobPayload,
|
|
9
|
-
} from "../jobs";
|
|
9
|
+
} from "../jobs/index.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Represents a defined Domain Event with name and payload schema.
|
package/src/ports/index.ts
CHANGED
|
@@ -27,9 +27,11 @@
|
|
|
27
27
|
* - `@beignet/core/mail` owns `MailerPort` and mail test adapters
|
|
28
28
|
* - `@beignet/core/notifications` owns notification helpers and test adapters
|
|
29
29
|
* - `@beignet/core/outbox` owns durable outbox helpers and test adapters
|
|
30
|
-
* - `@beignet/core/schedules` owns
|
|
30
|
+
* - `@beignet/core/schedules` owns schedule definitions and runners
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
+
import { createUnboundPort } from "./unbound.js";
|
|
34
|
+
|
|
33
35
|
/**
|
|
34
36
|
* A generic map of named "ports" (outbound dependencies) that your
|
|
35
37
|
* application depends on: db, mailer, cache, event bus, etc.
|
|
@@ -39,28 +41,78 @@
|
|
|
39
41
|
*/
|
|
40
42
|
export type AnyPorts = Record<string, unknown>;
|
|
41
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Definition accepted by the curried `definePorts<P>()(...)` form.
|
|
46
|
+
*/
|
|
47
|
+
export type DeferredPortsDefinition<
|
|
48
|
+
P extends AnyPorts,
|
|
49
|
+
Deferred extends readonly (keyof P & string)[],
|
|
50
|
+
> = {
|
|
51
|
+
/**
|
|
52
|
+
* Ports the app binds directly. Optional keys of `P` may be omitted here
|
|
53
|
+
* and contributed by providers instead.
|
|
54
|
+
*/
|
|
55
|
+
bound: Omit<P, Deferred[number]>;
|
|
56
|
+
/**
|
|
57
|
+
* Port keys that providers contribute during server startup. Deferred keys
|
|
58
|
+
* boot as throwing placeholders; `createServer(...)` fails startup if any
|
|
59
|
+
* are still unbound after providers have started (see `onUnboundPorts`).
|
|
60
|
+
*/
|
|
61
|
+
deferred: Deferred;
|
|
62
|
+
};
|
|
63
|
+
|
|
42
64
|
/**
|
|
43
65
|
* Define the set of ports (outbound dependencies) for your application.
|
|
44
66
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
67
|
+
* The identity form captures the exact shape of the provided `ports` object
|
|
68
|
+
* so you can export `type AppPorts = typeof appPorts`.
|
|
69
|
+
*
|
|
70
|
+
* The curried form, `definePorts<AppPorts>()({ bound, deferred })`, declares
|
|
71
|
+
* which port keys providers contribute at server startup. Deferred keys boot
|
|
72
|
+
* as throwing placeholders instead of hand-written stubs, and
|
|
73
|
+
* `createServer(...)` validates after provider startup that nothing is left
|
|
74
|
+
* unbound. Optional keys of `AppPorts` may go in either bucket.
|
|
48
75
|
*
|
|
49
76
|
* @example
|
|
50
77
|
* ```ts
|
|
78
|
+
* // Identity form: every port is bound directly.
|
|
51
79
|
* const appPorts = definePorts({
|
|
52
80
|
* db: dbAdapter,
|
|
53
81
|
* mailer: mailerAdapter,
|
|
54
82
|
* });
|
|
55
|
-
*
|
|
56
83
|
* export type AppPorts = typeof appPorts;
|
|
57
|
-
* ```
|
|
58
84
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
85
|
+
* // Deferred form: providers contribute the rest at startup.
|
|
86
|
+
* export const appPorts = definePorts<AppPorts>()({
|
|
87
|
+
* bound: { gate },
|
|
88
|
+
* deferred: ["db", "mailer", "storage"],
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
61
91
|
*/
|
|
62
|
-
export function definePorts<P extends AnyPorts>(ports: P): P
|
|
63
|
-
|
|
92
|
+
export function definePorts<P extends AnyPorts>(ports: P): P;
|
|
93
|
+
export function definePorts<P extends AnyPorts>(): <
|
|
94
|
+
const Deferred extends readonly (keyof P & string)[],
|
|
95
|
+
>(
|
|
96
|
+
definition: DeferredPortsDefinition<P, Deferred>,
|
|
97
|
+
) => P;
|
|
98
|
+
export function definePorts<P extends AnyPorts>(
|
|
99
|
+
ports?: P,
|
|
100
|
+
):
|
|
101
|
+
| P
|
|
102
|
+
| ((
|
|
103
|
+
definition: DeferredPortsDefinition<P, readonly (keyof P & string)[]>,
|
|
104
|
+
) => P) {
|
|
105
|
+
if (ports !== undefined) {
|
|
106
|
+
return ports;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (definition) => {
|
|
110
|
+
const result: AnyPorts = { ...(definition.bound as AnyPorts) };
|
|
111
|
+
for (const key of definition.deferred) {
|
|
112
|
+
result[key] = createUnboundPort(key);
|
|
113
|
+
}
|
|
114
|
+
return result as P;
|
|
115
|
+
};
|
|
64
116
|
}
|
|
65
117
|
|
|
66
118
|
/**
|
|
@@ -93,7 +145,7 @@ export type {
|
|
|
93
145
|
IdempotencyPort,
|
|
94
146
|
IdempotencyReservation,
|
|
95
147
|
IdempotencyReserveInput,
|
|
96
|
-
} from "../idempotency";
|
|
148
|
+
} from "../idempotency/index.js";
|
|
97
149
|
/**
|
|
98
150
|
* Notification port exports.
|
|
99
151
|
*/
|
|
@@ -104,7 +156,7 @@ export type {
|
|
|
104
156
|
NotificationPort,
|
|
105
157
|
SendNotificationOptions,
|
|
106
158
|
SendNotificationResult,
|
|
107
|
-
} from "../notifications";
|
|
159
|
+
} from "../notifications/index.js";
|
|
108
160
|
/**
|
|
109
161
|
* Transactional outbox port exports.
|
|
110
162
|
*/
|
|
@@ -118,7 +170,7 @@ export type {
|
|
|
118
170
|
OutboxMessageKind,
|
|
119
171
|
OutboxMessageStatus,
|
|
120
172
|
OutboxPort,
|
|
121
|
-
} from "../outbox";
|
|
173
|
+
} from "../outbox/index.js";
|
|
122
174
|
/**
|
|
123
175
|
* Audit log port exports.
|
|
124
176
|
*/
|
|
@@ -134,13 +186,15 @@ export type {
|
|
|
134
186
|
AuditLogOptions,
|
|
135
187
|
AuditLogPort,
|
|
136
188
|
AuditOutcome,
|
|
189
|
+
InstrumentedAuditLogOptions,
|
|
137
190
|
MemoryAuditLogPort,
|
|
138
|
-
} from "./audit";
|
|
191
|
+
} from "./audit.js";
|
|
139
192
|
/**
|
|
140
193
|
* Audit log helper exports.
|
|
141
194
|
*/
|
|
142
195
|
export {
|
|
143
196
|
createAnonymousActor,
|
|
197
|
+
createInstrumentedAuditLog,
|
|
144
198
|
createMemoryAuditLog,
|
|
145
199
|
createRedactedAuditLog,
|
|
146
200
|
createServiceActor,
|
|
@@ -149,7 +203,7 @@ export {
|
|
|
149
203
|
createUserActor,
|
|
150
204
|
normalizeAuditLogEntry,
|
|
151
205
|
redactAuditLogEntry,
|
|
152
|
-
} from "./audit";
|
|
206
|
+
} from "./audit.js";
|
|
153
207
|
/**
|
|
154
208
|
* Auth port exports.
|
|
155
209
|
*/
|
|
@@ -157,8 +211,9 @@ export type {
|
|
|
157
211
|
AuthPort,
|
|
158
212
|
AuthRequestLike,
|
|
159
213
|
AuthSession,
|
|
214
|
+
RequireOptions,
|
|
160
215
|
StaticAuthSessionFactory,
|
|
161
|
-
} from "./auth";
|
|
216
|
+
} from "./auth.js";
|
|
162
217
|
/**
|
|
163
218
|
* Auth helper exports.
|
|
164
219
|
*/
|
|
@@ -166,7 +221,13 @@ export {
|
|
|
166
221
|
AuthUnauthorizedError,
|
|
167
222
|
createAnonymousAuth,
|
|
168
223
|
createStaticAuth,
|
|
169
|
-
|
|
224
|
+
requireSession,
|
|
225
|
+
requireTenant,
|
|
226
|
+
requireTenantId,
|
|
227
|
+
requireUser,
|
|
228
|
+
requireUserId,
|
|
229
|
+
TenantRequiredError,
|
|
230
|
+
} from "./auth.js";
|
|
170
231
|
/**
|
|
171
232
|
* Ports builder exports.
|
|
172
233
|
*/
|
|
@@ -174,23 +235,23 @@ export {
|
|
|
174
235
|
createPortsBuilder,
|
|
175
236
|
type PortsBuilder,
|
|
176
237
|
type PortsOf,
|
|
177
|
-
} from "./builder";
|
|
238
|
+
} from "./builder.js";
|
|
178
239
|
/**
|
|
179
240
|
* Cache port exports.
|
|
180
241
|
*/
|
|
181
|
-
export type { CachePort, CacheSetOptions } from "./cache";
|
|
242
|
+
export type { CachePort, CacheSetOptions } from "./cache.js";
|
|
182
243
|
/**
|
|
183
244
|
* Cache helper exports.
|
|
184
245
|
*/
|
|
185
|
-
export { createMemoryCache } from "./cache";
|
|
246
|
+
export { createMemoryCache } from "./cache.js";
|
|
186
247
|
/**
|
|
187
248
|
* Clock port exports.
|
|
188
249
|
*/
|
|
189
|
-
export type { ClockPort, FrozenClockPort } from "./clock";
|
|
250
|
+
export type { ClockPort, FrozenClockPort } from "./clock.js";
|
|
190
251
|
/**
|
|
191
252
|
* Clock helper exports.
|
|
192
253
|
*/
|
|
193
|
-
export { createFrozenClock, createSystemClock } from "./clock";
|
|
254
|
+
export { createFrozenClock, createSystemClock } from "./clock.js";
|
|
194
255
|
/**
|
|
195
256
|
* Event bus and job dispatcher port exports.
|
|
196
257
|
*/
|
|
@@ -201,18 +262,21 @@ export type {
|
|
|
201
262
|
InferJobPayload,
|
|
202
263
|
JobDef,
|
|
203
264
|
JobDispatcherPort,
|
|
204
|
-
} from "./events";
|
|
265
|
+
} from "./events.js";
|
|
205
266
|
/**
|
|
206
267
|
* ID generator port exports.
|
|
207
268
|
*/
|
|
208
|
-
export type {
|
|
269
|
+
export type {
|
|
270
|
+
IdGeneratorPort,
|
|
271
|
+
SequenceIdGeneratorPort,
|
|
272
|
+
} from "./id-generator.js";
|
|
209
273
|
/**
|
|
210
274
|
* ID generator helper exports.
|
|
211
275
|
*/
|
|
212
276
|
export {
|
|
213
277
|
createSequenceIdGenerator,
|
|
214
278
|
createUuidIdGenerator,
|
|
215
|
-
} from "./id-generator";
|
|
279
|
+
} from "./id-generator.js";
|
|
216
280
|
/**
|
|
217
281
|
* Logger port exports.
|
|
218
282
|
*/
|
|
@@ -221,11 +285,11 @@ export type {
|
|
|
221
285
|
LogLevel,
|
|
222
286
|
MemoryLogEntry,
|
|
223
287
|
MemoryLoggerPort,
|
|
224
|
-
} from "./logger";
|
|
288
|
+
} from "./logger.js";
|
|
225
289
|
/**
|
|
226
290
|
* Logger helper exports.
|
|
227
291
|
*/
|
|
228
|
-
export { createMemoryLogger, createNoopLogger } from "./logger";
|
|
292
|
+
export { createMemoryLogger, createNoopLogger } from "./logger.js";
|
|
229
293
|
/**
|
|
230
294
|
* Policy and authorization gate type exports.
|
|
231
295
|
*/
|
|
@@ -233,6 +297,7 @@ export type {
|
|
|
233
297
|
BoundGate,
|
|
234
298
|
CreateGateOptions,
|
|
235
299
|
GateAllowedDecision,
|
|
300
|
+
GateContext,
|
|
236
301
|
GateDecision,
|
|
237
302
|
GateDeniedDecision,
|
|
238
303
|
GateDenyHandler,
|
|
@@ -243,7 +308,7 @@ export type {
|
|
|
243
308
|
PolicyMapFromDefinitions,
|
|
244
309
|
PolicyResolver,
|
|
245
310
|
PolicySubjectArgs,
|
|
246
|
-
} from "./policy";
|
|
311
|
+
} from "./policy.js";
|
|
247
312
|
/**
|
|
248
313
|
* Policy and authorization gate helper exports.
|
|
249
314
|
*/
|
|
@@ -253,7 +318,7 @@ export {
|
|
|
253
318
|
definePolicy,
|
|
254
319
|
deny,
|
|
255
320
|
GateAuthorizationError,
|
|
256
|
-
} from "./policy";
|
|
321
|
+
} from "./policy.js";
|
|
257
322
|
/**
|
|
258
323
|
* Rate limit port exports.
|
|
259
324
|
*/
|
|
@@ -261,11 +326,11 @@ export type {
|
|
|
261
326
|
RateLimitHitOptions,
|
|
262
327
|
RateLimitPort,
|
|
263
328
|
RateLimitResult,
|
|
264
|
-
} from "./rate-limit";
|
|
329
|
+
} from "./rate-limit.js";
|
|
265
330
|
/**
|
|
266
331
|
* Rate limit helper exports.
|
|
267
332
|
*/
|
|
268
|
-
export { createMemoryRateLimiter } from "./rate-limit";
|
|
333
|
+
export { createMemoryRateLimiter } from "./rate-limit.js";
|
|
269
334
|
/**
|
|
270
335
|
* Redaction helper exports.
|
|
271
336
|
*/
|
|
@@ -283,7 +348,7 @@ export {
|
|
|
283
348
|
type Redactor,
|
|
284
349
|
redactHeaders,
|
|
285
350
|
redactValue,
|
|
286
|
-
} from "./redaction";
|
|
351
|
+
} from "./redaction.js";
|
|
287
352
|
/**
|
|
288
353
|
* Storage port exports.
|
|
289
354
|
*/
|
|
@@ -296,11 +361,15 @@ export type {
|
|
|
296
361
|
StoragePort,
|
|
297
362
|
StoragePutOptions,
|
|
298
363
|
StorageVisibility,
|
|
299
|
-
} from "./storage";
|
|
364
|
+
} from "./storage.js";
|
|
300
365
|
/**
|
|
301
366
|
* Storage helper exports.
|
|
302
367
|
*/
|
|
303
|
-
export { createMemoryStorage } from "./storage";
|
|
368
|
+
export { createMemoryStorage } from "./storage.js";
|
|
369
|
+
/**
|
|
370
|
+
* Unbound (deferred) port helper exports.
|
|
371
|
+
*/
|
|
372
|
+
export { createUnboundPort, isUnboundPort } from "./unbound.js";
|
|
304
373
|
/**
|
|
305
374
|
* Unit of Work port exports.
|
|
306
375
|
*/
|
|
@@ -313,4 +382,4 @@ export {
|
|
|
313
382
|
type RecordedDomainEvent,
|
|
314
383
|
type UnitOfWorkCallback,
|
|
315
384
|
type UnitOfWorkPort,
|
|
316
|
-
} from "./unit-of-work";
|
|
385
|
+
} from "./unit-of-work.js";
|
package/src/ports/policy.ts
CHANGED
|
@@ -113,6 +113,12 @@ export type PolicyContextFromDefinitions<
|
|
|
113
113
|
* into every authorization call.
|
|
114
114
|
*/
|
|
115
115
|
export type BoundGate<TPolicies extends readonly PolicyDefinition[]> = {
|
|
116
|
+
/**
|
|
117
|
+
* Type-only marker that keeps `TPolicies` inferable from a bound gate.
|
|
118
|
+
* Runtime bound gates never implement this method. Method syntax keeps the
|
|
119
|
+
* marker bivariant so readonly and mutable policy tuples stay compatible.
|
|
120
|
+
*/
|
|
121
|
+
__policies?(policies: TPolicies): void;
|
|
116
122
|
/**
|
|
117
123
|
* Return only whether the ability is allowed.
|
|
118
124
|
*/
|
|
@@ -138,6 +144,18 @@ export type BoundGate<TPolicies extends readonly PolicyDefinition[]> = {
|
|
|
138
144
|
): Promise<GateAllowedDecision>;
|
|
139
145
|
};
|
|
140
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Context shape contributed by `gate.attach(...)`.
|
|
149
|
+
*/
|
|
150
|
+
export type GateContext<
|
|
151
|
+
TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[],
|
|
152
|
+
> = {
|
|
153
|
+
/**
|
|
154
|
+
* Gate bound to the context that carries it.
|
|
155
|
+
*/
|
|
156
|
+
gate: BoundGate<TPolicies>;
|
|
157
|
+
};
|
|
158
|
+
|
|
141
159
|
/**
|
|
142
160
|
* App-facing authorization gate.
|
|
143
161
|
*
|
|
@@ -150,9 +168,23 @@ export type GatePort<
|
|
|
150
168
|
TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[],
|
|
151
169
|
> = {
|
|
152
170
|
/**
|
|
153
|
-
* Bind this gate to a context
|
|
171
|
+
* Bind this gate to a fixed context snapshot.
|
|
172
|
+
*
|
|
173
|
+
* This is the low-level primitive: the returned gate keeps evaluating
|
|
174
|
+
* against the exact object it was bound to. Prefer `attach(...)` for app
|
|
175
|
+
* context assembly so identity changes can never go stale.
|
|
154
176
|
*/
|
|
155
177
|
bind(ctx: TContext): BoundGate<TPolicies>;
|
|
178
|
+
/**
|
|
179
|
+
* Attach a live `gate` property to a context object.
|
|
180
|
+
*
|
|
181
|
+
* The gate is exposed through a getter that re-binds against the receiving
|
|
182
|
+
* object on every access, so in-place updates to fields such as `actor` or
|
|
183
|
+
* `tenant` are always observed. The property is non-enumerable on purpose:
|
|
184
|
+
* spreading the context (`{ ...ctx }`) drops the gate instead of silently
|
|
185
|
+
* carrying a stale identity, and the next `ctx.gate` access fails loudly.
|
|
186
|
+
*/
|
|
187
|
+
attach<C extends TContext & object>(ctx: C): C & GateContext<TPolicies>;
|
|
156
188
|
/**
|
|
157
189
|
* Return only whether the ability is allowed for a context.
|
|
158
190
|
*/
|
|
@@ -284,8 +316,8 @@ export function definePolicy<
|
|
|
284
316
|
/**
|
|
285
317
|
* Create an authorization gate from app-owned policy definitions.
|
|
286
318
|
*
|
|
287
|
-
* Register the gate as a port, then
|
|
288
|
-
* `gate: ports.gate
|
|
319
|
+
* Register the gate as a port, then let the server context blueprint attach
|
|
320
|
+
* it: `context: { gate: (ports) => ports.gate, ... }`. Use cases can then call
|
|
289
321
|
* `ctx.gate.authorize(...)` for business authorization.
|
|
290
322
|
*
|
|
291
323
|
* @param options - Policy definitions and optional denial mapper.
|
|
@@ -348,8 +380,23 @@ export function createGate<
|
|
|
348
380
|
};
|
|
349
381
|
}
|
|
350
382
|
|
|
383
|
+
function attach<C extends TContext & object>(
|
|
384
|
+
ctx: C,
|
|
385
|
+
): C & GateContext<TPolicies> {
|
|
386
|
+
Object.defineProperty(ctx, "gate", {
|
|
387
|
+
configurable: true,
|
|
388
|
+
enumerable: false,
|
|
389
|
+
get(this: TContext) {
|
|
390
|
+
return bind(this);
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
return ctx as C & GateContext<TPolicies>;
|
|
395
|
+
}
|
|
396
|
+
|
|
351
397
|
const gate: GatePort<TContext, TPolicies> = {
|
|
352
398
|
bind,
|
|
399
|
+
attach,
|
|
353
400
|
async can(ctx, ability, ...subject) {
|
|
354
401
|
return (await inspect(ctx, ability, firstSubject(subject))).allowed;
|
|
355
402
|
},
|