@ddd-ts-kit/http 0.7.0 → 0.9.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.
- package/README.md +107 -4
- package/dist/controller/controller-request.d.ts +7 -1
- package/dist/controller/controller-request.d.ts.map +1 -1
- package/dist/controller/controller-routes.d.ts.map +1 -1
- package/dist/controller/controller-routes.js +22 -3
- package/dist/controller/controller-routes.js.map +1 -1
- package/dist/controller/controller-spec.d.ts +7 -0
- package/dist/controller/controller-spec.d.ts.map +1 -1
- package/dist/controller/guard-refusals.d.ts +9 -0
- package/dist/controller/guard-refusals.d.ts.map +1 -0
- package/dist/controller/guard-refusals.js +16 -0
- package/dist/controller/guard-refusals.js.map +1 -0
- package/dist/controller/guards/has-scope.d.ts +10 -0
- package/dist/controller/guards/has-scope.d.ts.map +1 -0
- package/dist/controller/guards/has-scope.js +27 -0
- package/dist/controller/guards/has-scope.js.map +1 -0
- package/dist/controller/guards/tenant-member.d.ts +9 -0
- package/dist/controller/guards/tenant-member.d.ts.map +1 -0
- package/dist/controller/guards/tenant-member.js +22 -0
- package/dist/controller/guards/tenant-member.js.map +1 -0
- package/dist/controller/http-request.d.ts +9 -3
- package/dist/controller/http-request.d.ts.map +1 -1
- package/dist/error/default-error-mapping.d.ts.map +1 -1
- package/dist/error/default-error-mapping.js +3 -0
- package/dist/error/default-error-mapping.js.map +1 -1
- package/dist/express/mount-express.d.ts +2 -0
- package/dist/express/mount-express.d.ts.map +1 -1
- package/dist/express/mount-express.js +9 -1
- package/dist/express/mount-express.js.map +1 -1
- package/dist/fastify/mount-fastify.d.ts +5 -1
- package/dist/fastify/mount-fastify.d.ts.map +1 -1
- package/dist/fastify/mount-fastify.js +26 -3
- package/dist/fastify/mount-fastify.js.map +1 -1
- package/dist/files/signed-file-routes-options.d.ts +5 -0
- package/dist/files/signed-file-routes-options.d.ts.map +1 -0
- package/dist/files/signed-file-routes-options.js +2 -0
- package/dist/files/signed-file-routes-options.js.map +1 -0
- package/dist/files/signed-file-routes.d.ts +14 -0
- package/dist/files/signed-file-routes.d.ts.map +1 -0
- package/dist/files/signed-file-routes.js +69 -0
- package/dist/files/signed-file-routes.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/openapi/path-items.d.ts.map +1 -1
- package/dist/openapi/path-items.js +6 -8
- package/dist/openapi/path-items.js.map +1 -1
- package/dist/openapi/request-body.d.ts +6 -0
- package/dist/openapi/request-body.d.ts.map +1 -0
- package/dist/openapi/request-body.js +36 -0
- package/dist/openapi/request-body.js.map +1 -0
- package/dist/openapi/responses.d.ts.map +1 -1
- package/dist/openapi/responses.js +4 -1
- package/dist/openapi/responses.js.map +1 -1
- package/dist/pipeline/execute-options.d.ts +19 -0
- package/dist/pipeline/execute-options.d.ts.map +1 -1
- package/dist/pipeline/execute-route.d.ts.map +1 -1
- package/dist/pipeline/execute-route.js +44 -13
- package/dist/pipeline/execute-route.js.map +1 -1
- package/dist/pipeline/execution-of-request.d.ts +2 -0
- package/dist/pipeline/execution-of-request.d.ts.map +1 -1
- package/dist/pipeline/execution-of-request.js +1 -0
- package/dist/pipeline/execution-of-request.js.map +1 -1
- package/dist/pipeline/guard-refusal.d.ts +8 -0
- package/dist/pipeline/guard-refusal.d.ts.map +1 -0
- package/dist/pipeline/guard-refusal.js +2 -0
- package/dist/pipeline/guard-refusal.js.map +1 -0
- package/dist/pipeline/raw-request.d.ts +3 -0
- package/dist/pipeline/raw-request.d.ts.map +1 -1
- package/dist/pipeline/receive-upload.d.ts +12 -0
- package/dist/pipeline/receive-upload.d.ts.map +1 -0
- package/dist/pipeline/receive-upload.js +12 -0
- package/dist/pipeline/receive-upload.js.map +1 -0
- package/dist/pipeline/received-upload.d.ts +7 -0
- package/dist/pipeline/received-upload.d.ts.map +1 -0
- package/dist/pipeline/received-upload.js +2 -0
- package/dist/pipeline/received-upload.js.map +1 -0
- package/dist/pipeline/upload-reader.d.ts +9 -0
- package/dist/pipeline/upload-reader.d.ts.map +1 -0
- package/dist/pipeline/upload-reader.js +2 -0
- package/dist/pipeline/upload-reader.js.map +1 -0
- package/dist/route/header-of.d.ts +4 -0
- package/dist/route/header-of.d.ts.map +1 -0
- package/dist/route/header-of.js +6 -0
- package/dist/route/header-of.js.map +1 -0
- package/dist/route/incoming-file.d.ts +7 -0
- package/dist/route/incoming-file.d.ts.map +1 -0
- package/dist/route/incoming-file.js +2 -0
- package/dist/route/incoming-file.js.map +1 -0
- package/dist/route/request-context.d.ts +3 -0
- package/dist/route/request-context.d.ts.map +1 -1
- package/dist/route/route-input.d.ts +3 -0
- package/dist/route/route-input.d.ts.map +1 -1
- package/dist/route/route-spec.d.ts +5 -0
- package/dist/route/route-spec.d.ts.map +1 -1
- package/dist/route/upload-spec.d.ts +12 -0
- package/dist/route/upload-spec.d.ts.map +1 -0
- package/dist/route/upload-spec.js +2 -0
- package/dist/route/upload-spec.js.map +1 -0
- package/dist/tenancy/first-tenant-of.d.ts +4 -0
- package/dist/tenancy/first-tenant-of.d.ts.map +1 -0
- package/dist/tenancy/first-tenant-of.js +13 -0
- package/dist/tenancy/first-tenant-of.js.map +1 -0
- package/dist/tenancy/resolved-tenant.d.ts +22 -0
- package/dist/tenancy/resolved-tenant.d.ts.map +1 -0
- package/dist/tenancy/resolved-tenant.js +29 -0
- package/dist/tenancy/resolved-tenant.js.map +1 -0
- package/dist/tenancy/tenant-from-claim.d.ts +4 -0
- package/dist/tenancy/tenant-from-claim.d.ts.map +1 -0
- package/dist/tenancy/tenant-from-claim.js +5 -0
- package/dist/tenancy/tenant-from-claim.js.map +1 -0
- package/dist/tenancy/tenant-from-header.d.ts +4 -0
- package/dist/tenancy/tenant-from-header.d.ts.map +1 -0
- package/dist/tenancy/tenant-from-header.js +9 -0
- package/dist/tenancy/tenant-from-header.js.map +1 -0
- package/dist/tenancy/tenant-from-path.d.ts +4 -0
- package/dist/tenancy/tenant-from-path.d.ts.map +1 -0
- package/dist/tenancy/tenant-from-path.js +8 -0
- package/dist/tenancy/tenant-from-path.js.map +1 -0
- package/dist/tenancy/tenant-from-subdomain.d.ts +8 -0
- package/dist/tenancy/tenant-from-subdomain.d.ts.map +1 -0
- package/dist/tenancy/tenant-from-subdomain.js +17 -0
- package/dist/tenancy/tenant-from-subdomain.js.map +1 -0
- package/dist/tenancy/tenant-request.d.ts +10 -0
- package/dist/tenancy/tenant-request.d.ts.map +1 -0
- package/dist/tenancy/tenant-request.js +2 -0
- package/dist/tenancy/tenant-request.js.map +1 -0
- package/dist/tenancy/tenant-resolver.d.ts +8 -0
- package/dist/tenancy/tenant-resolver.d.ts.map +1 -0
- package/dist/tenancy/tenant-resolver.js +2 -0
- package/dist/tenancy/tenant-resolver.js.map +1 -0
- package/dist/tenancy/unknown-tenant-error.d.ts +6 -0
- package/dist/tenancy/unknown-tenant-error.d.ts.map +1 -0
- package/dist/tenancy/unknown-tenant-error.js +6 -0
- package/dist/tenancy/unknown-tenant-error.js.map +1 -0
- package/dist/uploads/missing-file.d.ts +4 -0
- package/dist/uploads/missing-file.d.ts.map +1 -0
- package/dist/uploads/missing-file.js +6 -0
- package/dist/uploads/missing-file.js.map +1 -0
- package/dist/uploads/multipart-limits.d.ts +7 -0
- package/dist/uploads/multipart-limits.d.ts.map +1 -0
- package/dist/uploads/multipart-limits.js +2 -0
- package/dist/uploads/multipart-limits.js.map +1 -0
- package/dist/uploads/multipart-uploads.d.ts +8 -0
- package/dist/uploads/multipart-uploads.d.ts.map +1 -0
- package/dist/uploads/multipart-uploads.js +9 -0
- package/dist/uploads/multipart-uploads.js.map +1 -0
- package/dist/uploads/read-multipart.d.ts +13 -0
- package/dist/uploads/read-multipart.d.ts.map +1 -0
- package/dist/uploads/read-multipart.js +65 -0
- package/dist/uploads/read-multipart.js.map +1 -0
- package/dist/uploads.d.ts +3 -0
- package/dist/uploads.d.ts.map +1 -0
- package/dist/uploads.js +2 -0
- package/dist/uploads.js.map +1 -0
- package/package.json +14 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-of-request.js","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,SAAS,GAIV,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"execution-of-request.js","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import type { ErrorContext } from './error-context.js';
|
|
3
|
+
/** A request a guard of its route refused, before any use case: what `onGuardRefusal` is told. */
|
|
4
|
+
export interface GuardRefusal extends Omit<ErrorContext, 'execution'> {
|
|
5
|
+
/** The execution context of the request: who was refused, in which session and tenant. */
|
|
6
|
+
readonly execution: ExecutionContext;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=guard-refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard-refusal.d.ts","sourceRoot":"","sources":["../../src/pipeline/guard-refusal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,kGAAkG;AAClG,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC;IACnE,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard-refusal.js","sourceRoot":"","sources":["../../src/pipeline/guard-refusal.ts"],"names":[],"mappings":""}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
1
2
|
import type { RawHeaders } from '../route/raw-headers.js';
|
|
2
3
|
/** What an adapter extracts from its framework before handing over to `executeRoute`. */
|
|
3
4
|
export interface RawRequest {
|
|
@@ -6,5 +7,7 @@ export interface RawRequest {
|
|
|
6
7
|
readonly headers: RawHeaders;
|
|
7
8
|
readonly body: unknown;
|
|
8
9
|
readonly raw: unknown;
|
|
10
|
+
/** The body as it arrives, which an upload and a raw body are read from. */
|
|
11
|
+
readonly stream?: Readable;
|
|
9
12
|
}
|
|
10
13
|
//# sourceMappingURL=raw-request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-request.d.ts","sourceRoot":"","sources":["../../src/pipeline/raw-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"raw-request.d.ts","sourceRoot":"","sources":["../../src/pipeline/raw-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;CAC5B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IncomingFile } from '../route/incoming-file.js';
|
|
2
|
+
import type { Route } from '../route/route.js';
|
|
3
|
+
import type { ExecuteOptions } from './execute-options.js';
|
|
4
|
+
import type { RawRequest } from './raw-request.js';
|
|
5
|
+
interface Received {
|
|
6
|
+
readonly request: RawRequest;
|
|
7
|
+
readonly upload?: IncomingFile;
|
|
8
|
+
}
|
|
9
|
+
/** For a route that declares an upload: its text fields become the body, its file the `upload` of the input. */
|
|
10
|
+
export declare function receiveUpload(route: Route, request: RawRequest, options: ExecuteOptions): Promise<Received>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=receive-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive-upload.d.ts","sourceRoot":"","sources":["../../src/pipeline/receive-upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,UAAU,QAAQ;IAChB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,gHAAgH;AAChH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAcjH"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** For a route that declares an upload: its text fields become the body, its file the `upload` of the input. */
|
|
2
|
+
export async function receiveUpload(route, request, options) {
|
|
3
|
+
if (route.upload === undefined) {
|
|
4
|
+
return { request };
|
|
5
|
+
}
|
|
6
|
+
if (options.uploads === undefined) {
|
|
7
|
+
throw new Error(`Route "${route.operationId}" declares an upload: mount the routes with \`uploads: multipartUploads()\` of @ddd-ts-kit/http/uploads.`);
|
|
8
|
+
}
|
|
9
|
+
const { fields, file } = await options.uploads(route.upload, request);
|
|
10
|
+
return { request: { ...request, body: fields }, upload: file };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=receive-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive-upload.js","sourceRoot":"","sources":["../../src/pipeline/receive-upload.ts"],"names":[],"mappings":"AAUA,gHAAgH;AAChH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAY,EAAE,OAAmB,EAAE,OAAuB;IAC5F,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,UAAU,KAAK,CAAC,WAAW,0GAA0G,CACtI,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEtE,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IncomingFile } from '../route/incoming-file.js';
|
|
2
|
+
/** What an upload reader found in a request: the text fields sent before the file, and the file. */
|
|
3
|
+
export interface ReceivedUpload {
|
|
4
|
+
readonly fields: Readonly<Record<string, string>>;
|
|
5
|
+
readonly file: IncomingFile;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=received-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"received-upload.d.ts","sourceRoot":"","sources":["../../src/pipeline/received-upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,oGAAoG;AACpG,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"received-upload.js","sourceRoot":"","sources":["../../src/pipeline/received-upload.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UploadSpec } from '../route/upload-spec.js';
|
|
2
|
+
import type { RawRequest } from './raw-request.js';
|
|
3
|
+
import type { ReceivedUpload } from './received-upload.js';
|
|
4
|
+
/**
|
|
5
|
+
* Reads the upload a route declares out of its request, as soon as the file starts to arrive.
|
|
6
|
+
* `multipartUploads()` of `@ddd-ts-kit/http/uploads` is the one of the kit.
|
|
7
|
+
*/
|
|
8
|
+
export type UploadReader = (spec: UploadSpec, request: RawRequest) => Promise<ReceivedUpload>;
|
|
9
|
+
//# sourceMappingURL=upload-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-reader.d.ts","sourceRoot":"","sources":["../../src/pipeline/upload-reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-reader.js","sourceRoot":"","sources":["../../src/pipeline/upload-reader.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-of.d.ts","sourceRoot":"","sources":["../../src/route/header-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIlE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-of.js","sourceRoot":"","sources":["../../src/route/header-of.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,MAAM,UAAU,QAAQ,CAAC,OAAmB,EAAE,IAAY;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReceivedFile } from '@ddd-ts-kit/kernel';
|
|
2
|
+
/**
|
|
3
|
+
* The file of an upload as a handler receives it: still streaming, checked on its way, the
|
|
4
|
+
* `ReceivedFile` of the kernel that a controller hands to its command as it is.
|
|
5
|
+
*/
|
|
6
|
+
export type IncomingFile = ReceivedFile;
|
|
7
|
+
//# sourceMappingURL=incoming-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incoming-file.d.ts","sourceRoot":"","sources":["../../src/route/incoming-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incoming-file.js","sourceRoot":"","sources":["../../src/route/incoming-file.ts"],"names":[],"mappings":""}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
1
2
|
import type { ExecutionContext } from '@ddd-ts-kit/kernel';
|
|
2
3
|
import type { RawHeaders } from './raw-headers.js';
|
|
3
4
|
export interface RequestContext {
|
|
@@ -12,5 +13,7 @@ export interface RequestContext {
|
|
|
12
13
|
readonly rawHeaders?: RawHeaders;
|
|
13
14
|
/** The framework's own request object, for the rare case the neutral input is not enough. */
|
|
14
15
|
readonly raw: unknown;
|
|
16
|
+
/** The body as it arrives, unparsed, for a route declared with `rawBody`. */
|
|
17
|
+
readonly stream?: Readable;
|
|
15
18
|
}
|
|
16
19
|
//# sourceMappingURL=request-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/route/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,yHAAyH;IACzH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/route/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,yHAAyH;IACzH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;CAC5B"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IncomingFile } from './incoming-file.js';
|
|
1
2
|
import type { RequestContext } from './request-context.js';
|
|
2
3
|
/** The handler input once the schema types are erased, as the pipeline sees it. */
|
|
3
4
|
export interface RouteInput {
|
|
@@ -5,6 +6,8 @@ export interface RouteInput {
|
|
|
5
6
|
readonly query: unknown;
|
|
6
7
|
readonly headers: unknown;
|
|
7
8
|
readonly body: unknown;
|
|
9
|
+
/** The file of a route that declares an upload. */
|
|
10
|
+
readonly upload?: IncomingFile;
|
|
8
11
|
readonly context: RequestContext;
|
|
9
12
|
}
|
|
10
13
|
//# sourceMappingURL=route-input.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-input.d.ts","sourceRoot":"","sources":["../../src/route/route-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,mFAAmF;AACnF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CAClC"}
|
|
1
|
+
{"version":3,"file":"route-input.d.ts","sourceRoot":"","sources":["../../src/route/route-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,mFAAmF;AACnF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CAClC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { HttpMethod } from './http-method.js';
|
|
2
2
|
import type { RequestSchemas } from './request-schemas.js';
|
|
3
3
|
import type { ResponsesSpec } from './responses-spec.js';
|
|
4
|
+
import type { UploadSpec } from './upload-spec.js';
|
|
4
5
|
export interface RouteSpec<Request extends RequestSchemas = RequestSchemas, Responses extends ResponsesSpec = ResponsesSpec> {
|
|
5
6
|
readonly method: HttpMethod;
|
|
6
7
|
/** Express-style path: literal segments and `:name` parameters, for example `/orders/:orderId`. */
|
|
@@ -10,6 +11,10 @@ export interface RouteSpec<Request extends RequestSchemas = RequestSchemas, Resp
|
|
|
10
11
|
readonly description?: string;
|
|
11
12
|
readonly tags?: readonly string[];
|
|
12
13
|
readonly request?: Request;
|
|
14
|
+
/** A file received as `multipart/form-data`: the text fields are the body, the file streams to the handler. */
|
|
15
|
+
readonly upload?: UploadSpec;
|
|
16
|
+
/** The body is not parsed: the handler reads `context.stream`. For a route that receives a file as it is, such as `signedFileRoutes`. */
|
|
17
|
+
readonly rawBody?: boolean;
|
|
13
18
|
readonly responses: Responses;
|
|
14
19
|
/** Domain error codes this route may answer; they are documented in the contract. */
|
|
15
20
|
readonly errors?: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-spec.d.ts","sourceRoot":"","sources":["../../src/route/route-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"route-spec.d.ts","sourceRoot":"","sources":["../../src/route/route-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,SAAS,CACxB,OAAO,SAAS,cAAc,GAAG,cAAc,EAC/C,SAAS,SAAS,aAAa,GAAG,aAAa;IAE/C,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,mGAAmG;IACnG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,+GAA+G;IAC/G,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,yIAAyI;IACzI,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The file a route receives, in a `multipart/form-data` request: the field that carries it, the
|
|
3
|
+
* most it may weigh and the media types it may be. All three are part of the contract (the
|
|
4
|
+
* OpenAPI document states them) and are enforced while the content streams.
|
|
5
|
+
*/
|
|
6
|
+
export interface UploadSpec {
|
|
7
|
+
readonly field: string;
|
|
8
|
+
readonly maxBytes: number;
|
|
9
|
+
/** Exact types or families (`image/*`), verified on the first bytes of the content, never on the file name. */
|
|
10
|
+
readonly mediaTypes: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=upload-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-spec.d.ts","sourceRoot":"","sources":["../../src/route/upload-spec.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+GAA+G;IAC/G,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-spec.js","sourceRoot":"","sources":["../../src/route/upload-spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
2
|
+
/** The first tenant one of the resolvers names, in order: `firstTenantOf(tenantFromSubdomain('app.example.com'), tenantFromClaim())`. */
|
|
3
|
+
export declare function firstTenantOf(...resolvers: readonly TenantResolver[]): TenantResolver;
|
|
4
|
+
//# sourceMappingURL=first-tenant-of.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-tenant-of.d.ts","sourceRoot":"","sources":["../../src/tenancy/first-tenant-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,yIAAyI;AACzI,wBAAgB,aAAa,CAAC,GAAG,SAAS,EAAE,SAAS,cAAc,EAAE,GAAG,cAAc,CAYrF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** The first tenant one of the resolvers names, in order: `firstTenantOf(tenantFromSubdomain('app.example.com'), tenantFromClaim())`. */
|
|
2
|
+
export function firstTenantOf(...resolvers) {
|
|
3
|
+
return (request) => {
|
|
4
|
+
for (const resolver of resolvers) {
|
|
5
|
+
const tenantId = resolver(request);
|
|
6
|
+
if (tenantId !== undefined) {
|
|
7
|
+
return tenantId;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=first-tenant-of.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-tenant-of.js","sourceRoot":"","sources":["../../src/tenancy/first-tenant-of.ts"],"names":[],"mappings":"AAEA,yIAAyI;AACzI,MAAM,UAAU,aAAa,CAAC,GAAG,SAAoC;IACnE,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAEnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Actor } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import type { RawHeaders } from '../route/raw-headers.js';
|
|
3
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
4
|
+
interface TenantResolution {
|
|
5
|
+
readonly resolver: TenantResolver | undefined;
|
|
6
|
+
readonly headers: Readonly<RawHeaders>;
|
|
7
|
+
readonly params: unknown;
|
|
8
|
+
readonly actor: Actor;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The tenant a request names, refused (403) when an authenticated caller does not belong to it:
|
|
12
|
+
* a header or a subdomain chosen by the client never opens another tenant's data. A tenant id
|
|
13
|
+
* outside the grammar of `isTenantId` (`*`, a list, a `:`) names no tenant that can exist, and
|
|
14
|
+
* is answered 404 before anything reads it, whoever calls. An anonymous caller keeps the tenant
|
|
15
|
+
* it addressed, for the public routes of a tenant (its sign-in page, its booking page); what it
|
|
16
|
+
* may do there is decided by the use cases, as for any anonymous caller. An authenticated caller
|
|
17
|
+
* is held to its tenants on every route, public ones included: to open the public page of
|
|
18
|
+
* another tenant, it calls without its credential.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolvedTenant({ resolver, headers, params, actor }: TenantResolution): string | undefined;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=resolved-tenant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolved-tenant.d.ts","sourceRoot":"","sources":["../../src/tenancy/resolved-tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,UAAU,gBAAgB;IACxB,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAiBzG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isAnonymous, isTenantId, isTenantMember } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import { guardRefusals } from '../controller/guard-refusals.js';
|
|
3
|
+
import { ForbiddenError } from '../error/forbidden-error.js';
|
|
4
|
+
import { isRecord } from '../support/is-record.js';
|
|
5
|
+
import { UnknownTenantError } from './unknown-tenant-error.js';
|
|
6
|
+
/**
|
|
7
|
+
* The tenant a request names, refused (403) when an authenticated caller does not belong to it:
|
|
8
|
+
* a header or a subdomain chosen by the client never opens another tenant's data. A tenant id
|
|
9
|
+
* outside the grammar of `isTenantId` (`*`, a list, a `:`) names no tenant that can exist, and
|
|
10
|
+
* is answered 404 before anything reads it, whoever calls. An anonymous caller keeps the tenant
|
|
11
|
+
* it addressed, for the public routes of a tenant (its sign-in page, its booking page); what it
|
|
12
|
+
* may do there is decided by the use cases, as for any anonymous caller. An authenticated caller
|
|
13
|
+
* is held to its tenants on every route, public ones included: to open the public page of
|
|
14
|
+
* another tenant, it calls without its credential.
|
|
15
|
+
*/
|
|
16
|
+
export function resolvedTenant({ resolver, headers, params, actor }) {
|
|
17
|
+
const tenantId = resolver?.({ headers, params: isRecord(params) ? params : {}, actor });
|
|
18
|
+
if (tenantId !== undefined && !isTenantId(tenantId)) {
|
|
19
|
+
throw new UnknownTenantError('The request names no tenant that can exist');
|
|
20
|
+
}
|
|
21
|
+
if (tenantId === undefined || isAnonymous(actor) || isTenantMember(actor, tenantId)) {
|
|
22
|
+
return tenantId;
|
|
23
|
+
}
|
|
24
|
+
const refused = new ForbiddenError('The tenant of the request is not one the caller belongs to');
|
|
25
|
+
// Refused at the edge like a guard refuses, and reported as one (`onGuardRefusal`).
|
|
26
|
+
guardRefusals.mark(refused);
|
|
27
|
+
throw refused;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=resolved-tenant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolved-tenant.js","sourceRoot":"","sources":["../../src/tenancy/resolved-tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAS/D;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAoB;IACnF,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAExF,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QACpF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,4DAA4D,CAAC,CAAC;IAEjG,oFAAoF;IACpF,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5B,MAAM,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
2
|
+
/** The tenant of the credential (`Actor.tenantId`), which the execution context takes by default anyway: for `firstTenantOf`. */
|
|
3
|
+
export declare function tenantFromClaim(): TenantResolver;
|
|
4
|
+
//# sourceMappingURL=tenant-from-claim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-claim.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-claim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,iIAAiI;AACjI,wBAAgB,eAAe,IAAI,cAAc,CAEhD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-claim.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-claim.ts"],"names":[],"mappings":"AAEA,iIAAiI;AACjI,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
2
|
+
/** The value of a header, `x-tenant-id` by default; a header sent twice names none. */
|
|
3
|
+
export declare function tenantFromHeader(name?: string): TenantResolver;
|
|
4
|
+
//# sourceMappingURL=tenant-from-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-header.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,IAAI,SAAgB,GAAG,cAAc,CAQrE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The value of a header, `x-tenant-id` by default; a header sent twice names none. */
|
|
2
|
+
export function tenantFromHeader(name = 'x-tenant-id') {
|
|
3
|
+
const header = name.toLowerCase();
|
|
4
|
+
return ({ headers }) => {
|
|
5
|
+
const value = headers[header];
|
|
6
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=tenant-from-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-header.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-header.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAG,aAAa;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAElC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACrB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
2
|
+
/** A path parameter, `tenantId` by default: `/tenants/:tenantId/invoices`. A route without it names none. */
|
|
3
|
+
export declare function tenantFromPath(parameter?: string): TenantResolver;
|
|
4
|
+
//# sourceMappingURL=tenant-from-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-path.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,6GAA6G;AAC7G,wBAAgB,cAAc,CAAC,SAAS,SAAa,GAAG,cAAc,CAMrE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** A path parameter, `tenantId` by default: `/tenants/:tenantId/invoices`. A route without it names none. */
|
|
2
|
+
export function tenantFromPath(parameter = 'tenantId') {
|
|
3
|
+
return ({ params }) => {
|
|
4
|
+
const value = params[parameter];
|
|
5
|
+
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=tenant-from-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-path.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-path.ts"],"names":[],"mappings":"AAEA,6GAA6G;AAC7G,MAAM,UAAU,cAAc,CAAC,SAAS,GAAG,UAAU;IACnD,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAEhC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TenantResolver } from './tenant-resolver.js';
|
|
2
|
+
/**
|
|
3
|
+
* The label left of the base domain: with `app.example.com`, `acme.app.example.com` is the tenant
|
|
4
|
+
* `acme`. The base domain itself, another domain and a deeper subdomain name none. It reads the
|
|
5
|
+
* `Host` header: behind a proxy, have it pass the original host.
|
|
6
|
+
*/
|
|
7
|
+
export declare function tenantFromSubdomain(baseDomain: string): TenantResolver;
|
|
8
|
+
//# sourceMappingURL=tenant-from-subdomain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-subdomain.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-subdomain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CActE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The label left of the base domain: with `app.example.com`, `acme.app.example.com` is the tenant
|
|
3
|
+
* `acme`. The base domain itself, another domain and a deeper subdomain name none. It reads the
|
|
4
|
+
* `Host` header: behind a proxy, have it pass the original host.
|
|
5
|
+
*/
|
|
6
|
+
export function tenantFromSubdomain(baseDomain) {
|
|
7
|
+
const suffix = `.${baseDomain.toLowerCase()}`;
|
|
8
|
+
return ({ headers }) => {
|
|
9
|
+
const host = typeof headers['host'] === 'string' ? headers['host'].toLowerCase().replace(/:\d+$/, '') : '';
|
|
10
|
+
if (!host.endsWith(suffix)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const label = host.slice(0, -suffix.length);
|
|
14
|
+
return label === '' || label.includes('.') ? undefined : label;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=tenant-from-subdomain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-from-subdomain.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-subdomain.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;IAE9C,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3G,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAE5C,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Actor } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import type { RawHeaders } from '../route/raw-headers.js';
|
|
3
|
+
/** What a resolver reads to name the tenant of a request: who calls, and how the request was addressed. */
|
|
4
|
+
export interface TenantRequest {
|
|
5
|
+
readonly headers: Readonly<RawHeaders>;
|
|
6
|
+
/** The path parameters, through the schema of the route when it declares one. */
|
|
7
|
+
readonly params: Readonly<Record<string, unknown>>;
|
|
8
|
+
readonly actor: Actor;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=tenant-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-request.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,2GAA2G;AAC3G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-request.js","sourceRoot":"","sources":["../../src/tenancy/tenant-request.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TenantRequest } from './tenant-request.js';
|
|
2
|
+
/**
|
|
3
|
+
* Names the tenant of a request, or `undefined` when the request names none: the subdomain, a
|
|
4
|
+
* header, a path segment or a claim of the credential. What it answers becomes the `tenantId` of
|
|
5
|
+
* the execution context, once the pipeline has checked that the caller belongs to it.
|
|
6
|
+
*/
|
|
7
|
+
export type TenantResolver = (request: TenantRequest) => string | undefined;
|
|
8
|
+
//# sourceMappingURL=tenant-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-resolver.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-resolver.js","sourceRoot":"","sources":["../../src/tenancy/tenant-resolver.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DomainError } from '@ddd-ts-kit/kernel';
|
|
2
|
+
/** A request that names a tenant outside the grammar of `isTenantId`: no such tenant can exist. */
|
|
3
|
+
export declare class UnknownTenantError extends DomainError {
|
|
4
|
+
readonly code = "NOT_FOUND";
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=unknown-tenant-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-tenant-error.d.ts","sourceRoot":"","sources":["../../src/tenancy/unknown-tenant-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,mGAAmG;AACnG,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,eAAe;CAC7B"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DomainError } from '@ddd-ts-kit/kernel';
|
|
2
|
+
/** A request that names a tenant outside the grammar of `isTenantId`: no such tenant can exist. */
|
|
3
|
+
export class UnknownTenantError extends DomainError {
|
|
4
|
+
code = 'NOT_FOUND';
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=unknown-tenant-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-tenant-error.js","sourceRoot":"","sources":["../../src/tenancy/unknown-tenant-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,mGAAmG;AACnG,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACxC,IAAI,GAAG,WAAW,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-file.d.ts","sourceRoot":"","sources":["../../src/uploads/missing-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAK1D"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ValidationError } from '@ddd-ts-kit/validation';
|
|
2
|
+
/** The refusal of a multipart request without the file its route declares. */
|
|
3
|
+
export function missingFile(field) {
|
|
4
|
+
return new ValidationError([{ path: `body.${field}`, code: 'required', message: `A file is expected in the field "${field}".` }], 'The request is not valid.');
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=missing-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-file.js","sourceRoot":"","sources":["../../src/uploads/missing-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,IAAI,eAAe,CACxB,CAAC,EAAE,IAAI,EAAE,QAAQ,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,oCAAoC,KAAK,IAAI,EAAE,CAAC,EACrG,2BAA2B,CAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-limits.d.ts","sourceRoot":"","sources":["../../src/uploads/multipart-limits.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-limits.js","sourceRoot":"","sources":["../../src/uploads/multipart-limits.ts"],"names":[],"mappings":""}
|