@ddd-ts-kit/http 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +34 -2
  2. package/dist/controller/controller-routes.js +1 -0
  3. package/dist/controller/controller-routes.js.map +1 -1
  4. package/dist/controller/declared-route.d.ts +2 -0
  5. package/dist/controller/declared-route.d.ts.map +1 -1
  6. package/dist/controller/declared-route.js +3 -1
  7. package/dist/controller/declared-route.js.map +1 -1
  8. package/dist/docs/default-assets.d.ts +4 -0
  9. package/dist/docs/default-assets.d.ts.map +1 -0
  10. package/dist/docs/default-assets.js +7 -0
  11. package/dist/docs/default-assets.js.map +1 -0
  12. package/dist/docs/docs-page.d.ts.map +1 -1
  13. package/dist/docs/docs-page.js +1 -3
  14. package/dist/docs/docs-page.js.map +1 -1
  15. package/dist/docs/documents-page.d.ts +23 -0
  16. package/dist/docs/documents-page.d.ts.map +1 -0
  17. package/dist/docs/documents-page.js +16 -0
  18. package/dist/docs/documents-page.js.map +1 -0
  19. package/dist/docs/escape-html.d.ts +3 -0
  20. package/dist/docs/escape-html.d.ts.map +1 -0
  21. package/dist/docs/escape-html.js +5 -0
  22. package/dist/docs/escape-html.js.map +1 -0
  23. package/dist/docs/open-api-docs-routes.d.ts.map +1 -1
  24. package/dist/docs/open-api-docs-routes.js +2 -19
  25. package/dist/docs/open-api-docs-routes.js.map +1 -1
  26. package/dist/docs/open-api-documents-routes.d.ts +24 -0
  27. package/dist/docs/open-api-documents-routes.d.ts.map +1 -0
  28. package/dist/docs/open-api-documents-routes.js +57 -0
  29. package/dist/docs/open-api-documents-routes.js.map +1 -0
  30. package/dist/docs/text-route.d.ts +12 -0
  31. package/dist/docs/text-route.d.ts.map +1 -0
  32. package/dist/docs/text-route.js +15 -0
  33. package/dist/docs/text-route.js.map +1 -0
  34. package/dist/docs.d.ts +1 -0
  35. package/dist/docs.d.ts.map +1 -1
  36. package/dist/docs.js +1 -0
  37. package/dist/docs.js.map +1 -1
  38. package/dist/openapi/document-routes.d.ts +8 -0
  39. package/dist/openapi/document-routes.d.ts.map +1 -0
  40. package/dist/openapi/document-routes.js +2 -0
  41. package/dist/openapi/document-routes.js.map +1 -0
  42. package/dist/openapi/open-api-document-selection.d.ts +13 -0
  43. package/dist/openapi/open-api-document-selection.d.ts.map +1 -0
  44. package/dist/openapi/open-api-document-selection.js +2 -0
  45. package/dist/openapi/open-api-document-selection.js.map +1 -0
  46. package/dist/openapi/routes-by-document.d.ts +10 -0
  47. package/dist/openapi/routes-by-document.d.ts.map +1 -0
  48. package/dist/openapi/routes-by-document.js +31 -0
  49. package/dist/openapi/routes-by-document.js.map +1 -0
  50. package/dist/openapi.d.ts +3 -0
  51. package/dist/openapi.d.ts.map +1 -1
  52. package/dist/openapi.js +1 -0
  53. package/dist/openapi.js.map +1 -1
  54. package/dist/route/route.d.ts +5 -0
  55. package/dist/route/route.d.ts.map +1 -1
  56. package/package.json +3 -3
package/README.md CHANGED
@@ -429,14 +429,19 @@ const document = generateOpenApi({
429
429
  errorMapper, // the one the server runs with
430
430
  });
431
431
 
432
- writeFileSync('openapi.json', stringifyOpenApi(document));
432
+ writeFileSync('openapi/openapi.json', stringifyOpenApi(document));
433
433
 
434
434
  // In CI: regenerate and fail on a difference.
435
- if (checkOpenApiDrift(document, readFileSync('openapi.json', 'utf8')).drift) {
435
+ if (checkOpenApiDrift(document, readFileSync('openapi/openapi.json', 'utf8')).drift) {
436
436
  process.exit(1);
437
437
  }
438
438
  ```
439
439
 
440
+ `stringifyOpenApi` writes two-space JSON. A project generated by the CLI commits the contract in
441
+ YAML instead, `openapi/openapi.yaml`, through `stringifyContract(document, 'yaml')` of
442
+ `ddd-ts-kit/dist/contracts.js` in its `scripts/openapi.ts` (`openapi.format` of its config
443
+ chooses), and compares the text it writes with the committed one.
444
+
440
445
  What is generated: `{param}` paths, one parameter per property of the params, query and headers
441
446
  schemas, the request body, the declared responses, the `security` of every operation (an empty
442
447
  list for a public route), one `application/problem+json` response per
@@ -462,6 +467,33 @@ self-hosted files when it must work offline or under a strict content security p
462
467
  project generated by the CLI mounts them in `src/platform/http/with-documentation.ts`, with
463
468
  the UI chosen by `--docs-ui`, unless documentation is switched off by its configuration.
464
469
 
470
+ ## A contract split into documents
471
+
472
+ ```ts
473
+ import { openApiDocumentsRoutes } from '@ddd-ts-kit/http/docs';
474
+ import { generateOpenApi, routesByDocument } from '@ddd-ts-kit/http/openapi';
475
+
476
+ const documents = routesByDocument(routes, [
477
+ { name: 'public', title: 'Booking API', groups: ['AppointmentRoutes'] },
478
+ { name: 'back-office', title: 'Back office', tags: ['audit'], operations: ['openPractice'] },
479
+ ]).map(({ name, title, routes: selected }) => ({
480
+ name,
481
+ document: generateOpenApi({ info: { title: title ?? 'API', version: '1.0.0' }, routes: selected }),
482
+ }));
483
+
484
+ const served = [...routes, ...openApiDocumentsRoutes(documents, { ui: 'swagger' })];
485
+ ```
486
+
487
+ `routesByDocument` gives each document the routes of its route groups (a controller route
488
+ carries in `groups` the class names of its group and of every group above it), of its tags and
489
+ of its operations; a route may be in several documents, and a route in none is refused with a
490
+ `DeclarationError` naming it. Each document is generated on its own, so it holds every schema
491
+ it uses. `openApiDocumentsRoutes` serves each at `/openapi/<name>.json` with a page at
492
+ `/docs/<name>`, and on `/docs` Swagger UI with a selector between them (Scalar and Redoc show
493
+ one document at a time: `/docs` lists their pages); one document is served as
494
+ `openApiDocsRoutes` serves it. A generated project reads the documents from
495
+ `openapi.documents` of `ddd-ts-kit.config.json`, through `src/platform/http/openapi-documents.ts`.
496
+
465
497
  ## Limits
466
498
 
467
499
  - A body the framework itself refuses (malformed JSON, payload too large) is answered by the
@@ -21,6 +21,7 @@ function routeOf(resolved, options) {
21
21
  summary: spec.summary,
22
22
  ...(spec.description === undefined ? {} : { description: spec.description }),
23
23
  ...(declared.tags.length === 0 ? {} : { tags: declared.tags }),
24
+ ...(declared.groups.length === 0 ? {} : { groups: declared.groups }),
24
25
  ...requestOf(spec),
25
26
  responses: { [status]: { description: description ?? defaultDescription(body), ...bodyOf(body) } },
26
27
  errors: [...new Set([...declared.errors, ...resolved.guards.flatMap((guard) => guard.documents?.errors ?? [])])],
@@ -1 +1 @@
1
- {"version":3,"file":"controller-routes.js","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller-routes.js","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ export interface DeclaredRoute {
7
7
  readonly tags: readonly string[];
8
8
  readonly guards: readonly GuardReference[];
9
9
  readonly errors: readonly string[];
10
+ /** The class names of its route group and of every group above it, nearest first. */
11
+ readonly groups: readonly string[];
10
12
  }
11
13
  /** Folds the groups of a controller into its declaration, and refuses one that cannot stand. */
12
14
  export declare function declaredRoute(className: string, spec: ControllerSpec): DeclaredRoute;
@@ -1 +1 @@
1
- {"version":3,"file":"declared-route.d.ts","sourceRoot":"","sources":["../../src/controller/declared-route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAWD,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,aAAa,CAepF"}
1
+ {"version":3,"file":"declared-route.d.ts","sourceRoot":"","sources":["../../src/controller/declared-route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAYD,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,aAAa,CAgBpF"}
@@ -2,7 +2,7 @@ import { DeclarationError } from '@ddd-ts-kit/kernel/declarations';
2
2
  import { ROUTE_PATH_PATTERN } from '../route/route-path-pattern.js';
3
3
  import { Public } from './guards/public.js';
4
4
  import { presentationRegistry } from './presentation-registry.js';
5
- const NOTHING = { prefix: '', tags: [], guards: [], errors: [] };
5
+ const NOTHING = { groups: [], prefix: '', tags: [], guards: [], errors: [] };
6
6
  /** Folds the groups of a controller into its declaration, and refuses one that cannot stand. */
7
7
  export function declaredRoute(className, spec) {
8
8
  const inherited = spec.group === undefined ? NOTHING : inheritedFrom(className, spec.group);
@@ -16,6 +16,7 @@ export function declaredRoute(className, spec) {
16
16
  tags: distinct([...inherited.tags, ...(spec.tags ?? [])]),
17
17
  guards,
18
18
  errors: distinct([...inherited.errors, ...(spec.errors ?? [])]),
19
+ groups: inherited.groups,
19
20
  };
20
21
  }
21
22
  function inheritedFrom(className, group) {
@@ -25,6 +26,7 @@ function inheritedFrom(className, group) {
25
26
  }
26
27
  const above = options.parent === undefined ? NOTHING : inheritedFrom(className, options.parent);
27
28
  return {
29
+ groups: [group.name, ...above.groups],
28
30
  prefix: `${above.prefix}${options.prefix ?? ''}`,
29
31
  tags: [...above.tags, ...(options.tags ?? [])],
30
32
  guards: [...above.guards, ...(options.guards ?? [])],
@@ -1 +1 @@
1
- {"version":3,"file":"declared-route.js","sourceRoot":"","sources":["../../src/controller/declared-route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"declared-route.js","sourceRoot":"","sources":["../../src/controller/declared-route.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { DocsUi } from './docs-ui.js';
2
+ /** Where each documentation page loads its UI from by default: a public CDN, pinned to a major version. */
3
+ export declare const DEFAULT_ASSETS: Readonly<Record<DocsUi, string>>;
4
+ //# sourceMappingURL=default-assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-assets.d.ts","sourceRoot":"","sources":["../../src/docs/default-assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,2GAA2G;AAC3G,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI3D,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Where each documentation page loads its UI from by default: a public CDN, pinned to a major version. */
2
+ export const DEFAULT_ASSETS = {
3
+ swagger: 'https://cdn.jsdelivr.net/npm/swagger-ui-dist@5',
4
+ scalar: 'https://cdn.jsdelivr.net/npm/@scalar/api-reference@1',
5
+ redoc: 'https://cdn.jsdelivr.net/npm/redoc@2/bundles',
6
+ };
7
+ //# sourceMappingURL=default-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-assets.js","sourceRoot":"","sources":["../../src/docs/default-assets.ts"],"names":[],"mappings":"AAEA,2GAA2G;AAC3G,MAAM,CAAC,MAAM,cAAc,GAAqC;IAC9D,OAAO,EAAE,gDAAgD;IACzD,MAAM,EAAE,sDAAsD;IAC9D,KAAK,EAAE,8CAA8C;CACtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"docs-page.d.ts","sourceRoot":"","sources":["../../src/docs/docs-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,UAAU,QAAQ;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,GAAG,MAAM,CAazE"}
1
+ {"version":3,"file":"docs-page.d.ts","sourceRoot":"","sources":["../../src/docs/docs-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,UAAU,QAAQ;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,GAAG,MAAM,CAazE"}
@@ -1,3 +1,4 @@
1
+ import { escapeHtml } from './escape-html.js';
1
2
  /** The HTML page that loads the chosen UI and points it at the contract. */
2
3
  export function docsPage({ ui, title, specUrl, assets }) {
3
4
  const head = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(title)}</title>`;
@@ -12,7 +13,4 @@ export function docsPage({ ui, title, specUrl, assets }) {
12
13
  return `${head}</head><body><redoc spec-url="${spec}"></redoc><script src="${base}/redoc.standalone.js"></script></body></html>`;
13
14
  }
14
15
  }
15
- function escapeHtml(value) {
16
- return value.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
17
- }
18
16
  //# sourceMappingURL=docs-page.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"docs-page.js","sourceRoot":"","sources":["../../src/docs/docs-page.ts"],"names":[],"mappings":"AASA,4EAA4E;AAC5E,MAAM,UAAU,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAY;IAC/D,MAAM,IAAI,GAAG,wIAAwI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;IACjL,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAEhC,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,gCAAgC,IAAI,iEAAiE,IAAI,kEAAkE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,4CAA4C,CAAC;QAC/P,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,qDAAqD,IAAI,2BAA2B,IAAI,2BAA2B,CAAC;QACpI,KAAK,OAAO;YACV,OAAO,GAAG,IAAI,iCAAiC,IAAI,0BAA0B,IAAI,+CAA+C,CAAC;IACrI,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC"}
1
+ {"version":3,"file":"docs-page.js","sourceRoot":"","sources":["../../src/docs/docs-page.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAS9C,4EAA4E;AAC5E,MAAM,UAAU,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAY;IAC/D,MAAM,IAAI,GAAG,wIAAwI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;IACjL,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAEhC,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,gCAAgC,IAAI,iEAAiE,IAAI,kEAAkE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,4CAA4C,CAAC;QAC/P,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,qDAAqD,IAAI,2BAA2B,IAAI,2BAA2B,CAAC;QACpI,KAAK,OAAO;YACV,OAAO,GAAG,IAAI,iCAAiC,IAAI,0BAA0B,IAAI,+CAA+C,CAAC;IACrI,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { DocsUi } from './docs-ui.js';
2
+ /** One document of a split contract, as the documentation page lists it. */
3
+ export interface ListedDocument {
4
+ readonly name: string;
5
+ readonly title: string;
6
+ /** Where its JSON is served. */
7
+ readonly url: string;
8
+ /** Where its own page is served. */
9
+ readonly page: string;
10
+ }
11
+ interface DocumentsPage {
12
+ readonly ui: DocsUi;
13
+ readonly title: string;
14
+ readonly documents: readonly ListedDocument[];
15
+ readonly assets: string;
16
+ }
17
+ /**
18
+ * The page of a contract split into documents: Swagger UI with its selector between them; for
19
+ * the other pages, which show one document at a time, the list of the page of each document.
20
+ */
21
+ export declare function documentsPage({ ui, title, documents, assets }: DocumentsPage): string;
22
+ export {};
23
+ //# sourceMappingURL=documents-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documents-page.d.ts","sourceRoot":"","sources":["../../src/docs/documents-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,MAAM,CAerF"}
@@ -0,0 +1,16 @@
1
+ import { escapeHtml } from './escape-html.js';
2
+ /**
3
+ * The page of a contract split into documents: Swagger UI with its selector between them; for
4
+ * the other pages, which show one document at a time, the list of the page of each document.
5
+ */
6
+ export function documentsPage({ ui, title, documents, assets }) {
7
+ const head = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(title)}</title>`;
8
+ if (ui !== 'swagger') {
9
+ const links = documents.map((document) => `<li><a href="${escapeHtml(document.page)}">${escapeHtml(document.title)}</a></li>`);
10
+ return `${head}</head><body><h1>${escapeHtml(title)}</h1><ul>${links.join('')}</ul></body></html>`;
11
+ }
12
+ const base = escapeHtml(assets);
13
+ const urls = JSON.stringify(documents.map(({ url, title: name }) => ({ url, name }))).replaceAll('<', '\\u003c');
14
+ return `${head}<link rel="stylesheet" href="${base}/swagger-ui.css"></head><body><div id="ui"></div><script src="${base}/swagger-ui-bundle.js"></script><script src="${base}/swagger-ui-standalone-preset.js"></script><script>SwaggerUIBundle({ urls: ${urls}, dom_id: '#ui', presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset], layout: 'StandaloneLayout' });</script></body></html>`;
15
+ }
16
+ //# sourceMappingURL=documents-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documents-page.js","sourceRoot":"","sources":["../../src/docs/documents-page.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAmB9C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAiB;IAC3E,MAAM,IAAI,GAAG,wIAAwI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;IAEjL,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CACzB,CAAC,QAAQ,EAAE,EAAE,CAAC,gBAAgB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAClG,CAAC;QAEF,OAAO,GAAG,IAAI,oBAAoB,UAAU,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC;IACrG,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEjH,OAAO,GAAG,IAAI,gCAAgC,IAAI,iEAAiE,IAAI,gDAAgD,IAAI,8EAA8E,IAAI,4IAA4I,CAAC;AAC5Y,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** A text safe inside an HTML element or a quoted attribute. */
2
+ export declare function escapeHtml(value: string): string;
3
+ //# sourceMappingURL=escape-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-html.d.ts","sourceRoot":"","sources":["../../src/docs/escape-html.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,5 @@
1
+ /** A text safe inside an HTML element or a quoted attribute. */
2
+ export function escapeHtml(value) {
3
+ return value.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
4
+ }
5
+ //# sourceMappingURL=escape-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-html.js","sourceRoot":"","sources":["../../src/docs/escape-html.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"open-api-docs-routes.d.ts","sourceRoot":"","sources":["../../src/docs/open-api-docs-routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAmBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,iBAAsB,GAAG,SAAS,KAAK,EAAE,CA6B9G"}
1
+ {"version":3,"file":"open-api-docs-routes.d.ts","sourceRoot":"","sources":["../../src/docs/open-api-docs-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,iBAAsB,GAAG,SAAS,KAAK,EAAE,CA6B9G"}
@@ -1,14 +1,7 @@
1
- import { ok } from '@ddd-ts-kit/kernel';
2
- import { customSchema } from '@ddd-ts-kit/validation';
3
1
  import { stringifyOpenApi } from '../openapi/stringify-open-api.js';
4
- import { defineRoute } from '../route/define-route.js';
2
+ import { DEFAULT_ASSETS } from './default-assets.js';
5
3
  import { docsPage } from './docs-page.js';
6
- const DEFAULT_ASSETS = {
7
- swagger: 'https://cdn.jsdelivr.net/npm/swagger-ui-dist@5',
8
- scalar: 'https://cdn.jsdelivr.net/npm/@scalar/api-reference@1',
9
- redoc: 'https://cdn.jsdelivr.net/npm/redoc@2/bundles',
10
- };
11
- const text = customSchema((input) => ok(String(input)), { type: 'string' });
4
+ import { textRoute } from './text-route.js';
12
5
  /**
13
6
  * Two routes serving the generated contract and an interactive page for it. Mount them next
14
7
  * to the application routes; they are deliberately not part of the contract they display.
@@ -41,14 +34,4 @@ export function openApiDocsRoutes(document, options = {}) {
41
34
  }),
42
35
  ];
43
36
  }
44
- function textRoute(route) {
45
- return defineRoute({
46
- method: 'GET',
47
- path: route.path,
48
- operationId: route.operationId,
49
- summary: route.summary,
50
- responses: { 200: { description: route.description, body: text } },
51
- security: false,
52
- }, async () => ({ status: 200, body: route.body, headers: { 'content-type': route.contentType } }));
53
- }
54
37
  //# sourceMappingURL=open-api-docs-routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"open-api-docs-routes.js","sourceRoot":"","sources":["../../src/docs/open-api-docs-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA0B1C,MAAM,cAAc,GAA2B;IAC7C,OAAO,EAAE,gDAAgD;IACzD,MAAM,EAAE,sDAAsD;IAC9D,KAAK,EAAE,8CAA8C;CACtD,CAAC;AAEF,MAAM,IAAI,GAAG,YAAY,CAAS,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAEpF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAyB,EAAE,OAAO,GAAsB,EAAE;IAC1F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC;IACrD,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;IAEnC,MAAM,IAAI,GAAG,QAAQ,CAAC;QACpB,EAAE;QACF,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK;QAC3C,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,OAAO,CAAC,SAAS,IAAI,cAAc,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IAEH,OAAO;QACL,SAAS,CAAC;YACR,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,oBAAoB;YACjC,OAAO,EAAE,kBAAkB;YAC3B,WAAW,EAAE,2BAA2B;YACxC,WAAW,EAAE,iCAAiC;YAC9C,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,SAAS,CAAC;YACR,IAAI,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;YAC/B,WAAW,EAAE,cAAc;YAC3B,OAAO,EAAE,+BAA+B;YACxC,WAAW,EAAE,eAAe;YAC5B,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,IAAI;SACX,CAAC;KACH,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,OAAO,WAAW,CAChB;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAClE,QAAQ,EAAE,KAAK;KAChB,EACD,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAChG,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"open-api-docs-routes.js","sourceRoot":"","sources":["../../src/docs/open-api-docs-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAgB5C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAyB,EAAE,OAAO,GAAsB,EAAE;IAC1F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC;IACrD,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;IAEnC,MAAM,IAAI,GAAG,QAAQ,CAAC;QACpB,EAAE;QACF,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK;QAC3C,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,OAAO,CAAC,SAAS,IAAI,cAAc,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IAEH,OAAO;QACL,SAAS,CAAC;YACR,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,oBAAoB;YACjC,OAAO,EAAE,kBAAkB;YAC3B,WAAW,EAAE,2BAA2B;YACxC,WAAW,EAAE,iCAAiC;YAC9C,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,SAAS,CAAC;YACR,IAAI,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;YAC/B,WAAW,EAAE,cAAc;YAC3B,OAAO,EAAE,+BAA+B;YACxC,WAAW,EAAE,eAAe;YAC5B,WAAW,EAAE,0BAA0B;YACvC,IAAI,EAAE,IAAI;SACX,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { OpenApiDocument } from '../openapi/open-api-document.js';
2
+ import type { Route } from '../route/route.js';
3
+ import type { DocsUi } from './docs-ui.js';
4
+ /** One document of the contract and the name it is served under. */
5
+ export interface NamedOpenApiDocument {
6
+ readonly name: string;
7
+ readonly document: OpenApiDocument;
8
+ }
9
+ export interface DocumentsRoutesOptions {
10
+ /** Where the JSON of each document is served, `<contractsPath>/<name>.json`. Default `/openapi`. */
11
+ readonly contractsPath?: string;
12
+ /** Where the page is served, and the page of each document under it. Default `/docs`. */
13
+ readonly uiPath?: string;
14
+ readonly ui?: DocsUi;
15
+ readonly assetsUrl?: string;
16
+ readonly title?: string;
17
+ }
18
+ /**
19
+ * The routes of a contract split into documents: the JSON of each, a page per document and a
20
+ * page that offers them all (Swagger UI selects between them; the other pages link to each). One
21
+ * document is served as `openApiDocsRoutes` serves it, at `/openapi.json` and `/docs`.
22
+ */
23
+ export declare function openApiDocumentsRoutes(documents: readonly NamedOpenApiDocument[], options?: DocumentsRoutesOptions): readonly Route[];
24
+ //# sourceMappingURL=open-api-documents-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-api-documents-routes.d.ts","sourceRoot":"","sources":["../../src/docs/open-api-documents-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAI3C,oEAAoE;AACpE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,oGAAoG;IACpG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,yFAAyF;IACzF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,SAAS,oBAAoB,EAAE,EAC1C,OAAO,GAAE,sBAA2B,GACnC,SAAS,KAAK,EAAE,CAgBlB"}
@@ -0,0 +1,57 @@
1
+ import { stringifyOpenApi } from '../openapi/stringify-open-api.js';
2
+ import { DEFAULT_ASSETS } from './default-assets.js';
3
+ import { docsPage } from './docs-page.js';
4
+ import { documentsPage } from './documents-page.js';
5
+ import { openApiDocsRoutes } from './open-api-docs-routes.js';
6
+ import { textRoute } from './text-route.js';
7
+ /**
8
+ * The routes of a contract split into documents: the JSON of each, a page per document and a
9
+ * page that offers them all (Swagger UI selects between them; the other pages link to each). One
10
+ * document is served as `openApiDocsRoutes` serves it, at `/openapi.json` and `/docs`.
11
+ */
12
+ export function openApiDocumentsRoutes(documents, options = {}) {
13
+ const [only] = documents;
14
+ const { contractsPath = '/openapi', uiPath = '/docs', ui = 'swagger', ...shown } = options;
15
+ if (documents.length === 1 && only !== undefined) {
16
+ return openApiDocsRoutes(only.document, { ...shown, ui, uiPath });
17
+ }
18
+ const assets = shown.assetsUrl ?? DEFAULT_ASSETS[ui];
19
+ const listed = documents.map(({ name, document }) => listedDocument(name, document, { contractsPath, uiPath }));
20
+ const title = shown.title ?? 'API documentation';
21
+ return [
22
+ ...documents.flatMap(({ document }, index) => documentRoutes(document, listed[index], { ui, assets })),
23
+ page(uiPath, 'getOpenApiUi', documentsPage({ ui, title, documents: listed, assets })),
24
+ ];
25
+ }
26
+ function listedDocument(name, document, { contractsPath, uiPath }) {
27
+ return { name, title: document.info.title, url: `${contractsPath}/${name}.json`, page: `${uiPath}/${name}` };
28
+ }
29
+ function documentRoutes(document, listed, { ui, assets }) {
30
+ if (listed === undefined) {
31
+ return [];
32
+ }
33
+ const html = docsPage({ ui, title: listed.title, specUrl: listed.url, assets });
34
+ const id = listed.name.replace(/-(\w)/g, (_dash, letter) => letter.toUpperCase());
35
+ return [
36
+ textRoute({
37
+ path: listed.url,
38
+ operationId: `getOpenApiDocument_${id}`,
39
+ summary: `OpenAPI contract: ${listed.name}`,
40
+ description: 'An OpenAPI 3.1 document.',
41
+ contentType: 'application/json; charset=utf-8',
42
+ body: stringifyOpenApi(document),
43
+ }),
44
+ page(listed.page, `getOpenApiUi_${id}`, html),
45
+ ];
46
+ }
47
+ function page(path, operationId, body) {
48
+ return textRoute({
49
+ path,
50
+ operationId,
51
+ summary: 'Interactive API documentation',
52
+ description: 'An HTML page.',
53
+ contentType: 'text/html; charset=utf-8',
54
+ body,
55
+ });
56
+ }
57
+ //# sourceMappingURL=open-api-documents-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-api-documents-routes.js","sourceRoot":"","sources":["../../src/docs/open-api-documents-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAuB,MAAM,qBAAqB,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAkB5C;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAA0C,EAC1C,OAAO,GAA2B,EAAE;IAEpC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,aAAa,GAAG,UAAU,EAAE,MAAM,GAAG,OAAO,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE3F,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACjD,OAAO,iBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAChH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC;IAEjD,OAAO;QACL,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;KACtF,CAAC;AACJ,CAAC;AAOD,SAAS,cAAc,CAAC,IAAY,EAAE,QAAyB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAS;IAC/F,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,aAAa,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;AAC/G,CAAC;AAED,SAAS,cAAc,CACrB,QAAyB,EACzB,MAAkC,EAClC,EAAE,EAAE,EAAE,MAAM,EAAoD;IAEhE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAChF,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAE1F,OAAO;QACL,SAAS,CAAC;YACR,IAAI,EAAE,MAAM,CAAC,GAAG;YAChB,WAAW,EAAE,sBAAsB,EAAE,EAAE;YACvC,OAAO,EAAE,qBAAqB,MAAM,CAAC,IAAI,EAAE;YAC3C,WAAW,EAAE,0BAA0B;YACvC,WAAW,EAAE,iCAAiC;YAC9C,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,WAAmB,EAAE,IAAY;IAC3D,OAAO,SAAS,CAAC;QACf,IAAI;QACJ,WAAW;QACX,OAAO,EAAE,+BAA+B;QACxC,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,0BAA0B;QACvC,IAAI;KACL,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Route } from '../route/route.js';
2
+ /** A public GET route answering a fixed text: a contract or a page of the documentation. */
3
+ export interface TextRoute {
4
+ readonly path: string;
5
+ readonly operationId: string;
6
+ readonly summary: string;
7
+ readonly description: string;
8
+ readonly contentType: string;
9
+ readonly body: string;
10
+ }
11
+ export declare function textRoute(route: TextRoute): Route;
12
+ //# sourceMappingURL=text-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-route.d.ts","sourceRoot":"","sources":["../../src/docs/text-route.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,4FAA4F;AAC5F,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAID,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAYjD"}
@@ -0,0 +1,15 @@
1
+ import { ok } from '@ddd-ts-kit/kernel';
2
+ import { customSchema } from '@ddd-ts-kit/validation';
3
+ import { defineRoute } from '../route/define-route.js';
4
+ const text = customSchema((input) => ok(String(input)), { type: 'string' });
5
+ export function textRoute(route) {
6
+ return defineRoute({
7
+ method: 'GET',
8
+ path: route.path,
9
+ operationId: route.operationId,
10
+ summary: route.summary,
11
+ responses: { 200: { description: route.description, body: text } },
12
+ security: false,
13
+ }, async () => ({ status: 200, body: route.body, headers: { 'content-type': route.contentType } }));
14
+ }
15
+ //# sourceMappingURL=text-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-route.js","sourceRoot":"","sources":["../../src/docs/text-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAavD,MAAM,IAAI,GAAG,YAAY,CAAS,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAEpF,MAAM,UAAU,SAAS,CAAC,KAAgB;IACxC,OAAO,WAAW,CAChB;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAClE,QAAQ,EAAE,KAAK;KAChB,EACD,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAChG,CAAC;AACJ,CAAC"}
package/dist/docs.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export type { DocsUi } from './docs/docs-ui.js';
2
2
  export { openApiDocsRoutes, type DocsRoutesOptions } from './docs/open-api-docs-routes.js';
3
+ export { openApiDocumentsRoutes, type DocumentsRoutesOptions, type NamedOpenApiDocument, } from './docs/open-api-documents-routes.js';
3
4
  //# sourceMappingURL=docs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAC3F,OAAO,EACL,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,qCAAqC,CAAC"}
package/dist/docs.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { openApiDocsRoutes } from './docs/open-api-docs-routes.js';
2
+ export { openApiDocumentsRoutes, } from './docs/open-api-documents-routes.js';
2
3
  //# sourceMappingURL=docs.js.map
package/dist/docs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA0B,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA0B,MAAM,gCAAgC,CAAC;AAC3F,OAAO,EACL,sBAAsB,GAGvB,MAAM,qCAAqC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Route } from '../route/route.js';
2
+ /** The routes of one document of the contract. */
3
+ export interface DocumentRoutes {
4
+ readonly name: string;
5
+ readonly title?: string;
6
+ readonly routes: readonly Route[];
7
+ }
8
+ //# sourceMappingURL=document-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-routes.d.ts","sourceRoot":"","sources":["../../src/openapi/document-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;CACnC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=document-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-routes.js","sourceRoot":"","sources":["../../src/openapi/document-routes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * One document of a split contract, as `ddd-ts-kit docs` writes it from `openapi.documents` of
3
+ * the config: a route belongs to it when one of its route groups, one of its tags or its
4
+ * operation id is listed (the operations of the contexts the config names, read from the sources).
5
+ */
6
+ export interface OpenApiDocumentSelection {
7
+ readonly name: string;
8
+ readonly title?: string;
9
+ readonly groups?: readonly string[];
10
+ readonly tags?: readonly string[];
11
+ readonly operations?: readonly string[];
12
+ }
13
+ //# sourceMappingURL=open-api-document-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-api-document-selection.d.ts","sourceRoot":"","sources":["../../src/openapi/open-api-document-selection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=open-api-document-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-api-document-selection.js","sourceRoot":"","sources":["../../src/openapi/open-api-document-selection.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { Route } from '../route/route.js';
2
+ import type { DocumentRoutes } from './document-routes.js';
3
+ import type { OpenApiDocumentSelection } from './open-api-document-selection.js';
4
+ /**
5
+ * Splits the routes between the documents of the contract. Each document holds the routes it
6
+ * selects, a route may be in several on purpose, and a route in none is refused: nothing
7
+ * leaves the contract silently. Without any selection there is one document, `openapi`.
8
+ */
9
+ export declare function routesByDocument(routes: readonly Route[], selections: readonly OpenApiDocumentSelection[]): DocumentRoutes[];
10
+ //# sourceMappingURL=routes-by-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes-by-document.d.ts","sourceRoot":"","sources":["../../src/openapi/routes-by-document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAKjF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,UAAU,EAAE,SAAS,wBAAwB,EAAE,GAC9C,cAAc,EAAE,CAkBlB"}
@@ -0,0 +1,31 @@
1
+ import { DeclarationError } from '@ddd-ts-kit/kernel/declarations';
2
+ /** Without a selection, the one document every project had before the contract could be split. */
3
+ const WHOLE = 'openapi';
4
+ /**
5
+ * Splits the routes between the documents of the contract. Each document holds the routes it
6
+ * selects, a route may be in several on purpose, and a route in none is refused: nothing
7
+ * leaves the contract silently. Without any selection there is one document, `openapi`.
8
+ */
9
+ export function routesByDocument(routes, selections) {
10
+ if (selections.length === 0) {
11
+ return [{ name: WHOLE, routes }];
12
+ }
13
+ const unplaced = routes.filter((route) => !selections.some((selection) => selects(selection, route)));
14
+ if (unplaced.length > 0) {
15
+ throw new DeclarationError(`No document of "openapi.documents" holds ${unplaced.map(described).join(', ')}. Name its route group, its context or one of its tags in a document of ddd-ts-kit.config.json, then run \`ddd-ts-kit docs\`.`);
16
+ }
17
+ return selections.map(({ name, title, ...selection }) => ({
18
+ name,
19
+ ...(title === undefined ? {} : { title }),
20
+ routes: routes.filter((route) => selects(selection, route)),
21
+ }));
22
+ }
23
+ function selects(selection, route) {
24
+ return ((route.groups ?? []).some((group) => selection.groups?.includes(group) === true) ||
25
+ (route.tags ?? []).some((tag) => selection.tags?.includes(tag) === true) ||
26
+ selection.operations?.includes(route.operationId) === true);
27
+ }
28
+ function described(route) {
29
+ return `${route.method} ${route.path} (${route.operationId})`;
30
+ }
31
+ //# sourceMappingURL=routes-by-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes-by-document.js","sourceRoot":"","sources":["../../src/openapi/routes-by-document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAKnE,kGAAkG;AAClG,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAwB,EACxB,UAA+C;IAE/C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,gBAAgB,CACxB,4CAA4C,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,+HAA+H,CAC9M,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACxD,IAAI;QACJ,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;KAC5D,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,OAAO,CAAC,SAA2D,EAAE,KAAY;IACxF,OAAO,CACL,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;QAChF,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;QACxE,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,CAC3D,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAY;IAC7B,OAAO,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,WAAW,GAAG,CAAC;AAChE,CAAC"}
package/dist/openapi.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  export { checkOpenApiDrift } from './openapi/check-open-api-drift.js';
2
+ export type { DocumentRoutes } from './openapi/document-routes.js';
2
3
  export { generateOpenApi, type GenerateOpenApiOptions } from './openapi/generate-open-api.js';
3
4
  export type { OpenApiDocument } from './openapi/open-api-document.js';
5
+ export type { OpenApiDocumentSelection } from './openapi/open-api-document-selection.js';
4
6
  export type { OpenApiInfo } from './openapi/open-api-info.js';
5
7
  export type { OpenApiServer } from './openapi/open-api-server.js';
8
+ export { routesByDocument } from './openapi/routes-by-document.js';
6
9
  export { stringifyOpenApi } from './openapi/stringify-open-api.js';
7
10
  //# sourceMappingURL=openapi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
package/dist/openapi.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { checkOpenApiDrift } from './openapi/check-open-api-drift.js';
2
2
  export { generateOpenApi } from './openapi/generate-open-api.js';
3
+ export { routesByDocument } from './openapi/routes-by-document.js';
3
4
  export { stringifyOpenApi } from './openapi/stringify-open-api.js';
4
5
  //# sourceMappingURL=openapi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,eAAe,EAA+B,MAAM,gCAAgC,CAAC;AAI9F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,eAAe,EAA+B,MAAM,gCAAgC,CAAC;AAK9F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
@@ -6,6 +6,11 @@ import type { RouteSpec } from './route-spec.js';
6
6
  * shape sit in one list; they are checked where it matters, in `defineRoute`.
7
7
  */
8
8
  export interface Route extends RouteSpec {
9
+ /**
10
+ * The class names of the route group of a controller and of every group above it, nearest
11
+ * first: what a document of a split contract selects by. Not part of the contract.
12
+ */
13
+ readonly groups?: readonly string[];
9
14
  handle(input: RouteInput): RouteOutput | Promise<RouteOutput>;
10
15
  }
11
16
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/route/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,KAAM,SAAQ,SAAS;IAGtC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/D"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/route/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,KAAM,SAAQ,SAAS;IACtC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAIpC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/http",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Framework-agnostic route definitions with Express, Fastify and NestJS adapters and OpenAPI 3.1 generation.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,8 +46,8 @@
46
46
  "dist"
47
47
  ],
48
48
  "dependencies": {
49
- "@ddd-ts-kit/kernel": "0.4.1",
50
- "@ddd-ts-kit/validation": "0.4.1"
49
+ "@ddd-ts-kit/kernel": "0.5.0",
50
+ "@ddd-ts-kit/validation": "0.5.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@nestjs/common": ">=11.0.0",