@databehave/openapi 0.0.0-stage → 0.1.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 (68) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +93 -2
  4. package/dist/catalog.d.ts +51 -0
  5. package/dist/catalog.d.ts.map +1 -0
  6. package/dist/catalog.js +90 -0
  7. package/dist/catalog.js.map +1 -0
  8. package/dist/index.d.ts +11 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +9 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/middleware/request-validation.d.ts +65 -0
  13. package/dist/middleware/request-validation.d.ts.map +1 -0
  14. package/dist/middleware/request-validation.js +353 -0
  15. package/dist/middleware/request-validation.js.map +1 -0
  16. package/dist/mock-mode-plugin.d.ts +5 -0
  17. package/dist/mock-mode-plugin.d.ts.map +1 -0
  18. package/dist/mock-mode-plugin.js +20 -0
  19. package/dist/mock-mode-plugin.js.map +1 -0
  20. package/dist/mock-mode.d.ts +76 -0
  21. package/dist/mock-mode.d.ts.map +1 -0
  22. package/dist/mock-mode.js +93 -0
  23. package/dist/mock-mode.js.map +1 -0
  24. package/dist/openapi/auto-schema.d.ts +3 -0
  25. package/dist/openapi/auto-schema.d.ts.map +1 -0
  26. package/dist/openapi/auto-schema.js +10 -0
  27. package/dist/openapi/auto-schema.js.map +1 -0
  28. package/dist/openapi/generate.d.ts +8 -0
  29. package/dist/openapi/generate.d.ts.map +1 -0
  30. package/dist/openapi/generate.js +121 -0
  31. package/dist/openapi/generate.js.map +1 -0
  32. package/dist/openapi/loader.d.ts +18 -0
  33. package/dist/openapi/loader.d.ts.map +1 -0
  34. package/dist/openapi/loader.js +32 -0
  35. package/dist/openapi/loader.js.map +1 -0
  36. package/dist/openapi/seed.d.ts +17 -0
  37. package/dist/openapi/seed.d.ts.map +1 -0
  38. package/dist/openapi/seed.js +58 -0
  39. package/dist/openapi/seed.js.map +1 -0
  40. package/dist/openapi/translate.d.ts +14 -0
  41. package/dist/openapi/translate.d.ts.map +1 -0
  42. package/dist/openapi/translate.js +312 -0
  43. package/dist/openapi/translate.js.map +1 -0
  44. package/dist/openapi/walker.d.ts +37 -0
  45. package/dist/openapi/walker.d.ts.map +1 -0
  46. package/dist/openapi/walker.js +2 -0
  47. package/dist/openapi/walker.js.map +1 -0
  48. package/dist/placeholder.d.ts +7 -0
  49. package/dist/placeholder.d.ts.map +1 -0
  50. package/dist/placeholder.js +17 -0
  51. package/dist/placeholder.js.map +1 -0
  52. package/dist/plugin.d.ts +10 -0
  53. package/dist/plugin.d.ts.map +1 -0
  54. package/dist/plugin.js +43 -0
  55. package/dist/plugin.js.map +1 -0
  56. package/dist/request-validation-plugin.d.ts +8 -0
  57. package/dist/request-validation-plugin.d.ts.map +1 -0
  58. package/dist/request-validation-plugin.js +24 -0
  59. package/dist/request-validation-plugin.js.map +1 -0
  60. package/dist/schema.d.ts +18 -0
  61. package/dist/schema.d.ts.map +1 -0
  62. package/dist/schema.js +26 -0
  63. package/dist/schema.js.map +1 -0
  64. package/dist/validation/validate.d.ts +40 -0
  65. package/dist/validation/validate.d.ts.map +1 -0
  66. package/dist/validation/validate.js +378 -0
  67. package/dist/validation/validate.js.map +1 -0
  68. package/package.json +55 -3
@@ -0,0 +1,37 @@
1
+ /** Supported OpenAPI schema keywords; extension keywords remain available to conformance validation. */
2
+ export type OasNode = {
3
+ [keyword: string]: unknown;
4
+ $ref?: string;
5
+ type?: string | string[];
6
+ format?: string;
7
+ enum?: unknown[];
8
+ const?: unknown;
9
+ example?: unknown;
10
+ examples?: unknown[];
11
+ properties?: Record<string, OasNode>;
12
+ required?: string[];
13
+ items?: OasNode;
14
+ additionalProperties?: boolean | OasNode;
15
+ nullable?: boolean;
16
+ allOf?: OasNode[];
17
+ oneOf?: OasNode[];
18
+ anyOf?: OasNode[];
19
+ minimum?: number;
20
+ maximum?: number;
21
+ minLength?: number;
22
+ maxLength?: number;
23
+ minItems?: number;
24
+ maxItems?: number;
25
+ pattern?: string;
26
+ title?: string;
27
+ };
28
+ /** Parsed document shared by all OpenAPI plugins. */
29
+ export type OasDoc = {
30
+ [key: string]: unknown;
31
+ paths?: Record<string, Record<string, unknown>>;
32
+ components?: {
33
+ schemas?: Record<string, OasNode>;
34
+ [key: string]: unknown;
35
+ };
36
+ };
37
+ //# sourceMappingURL=walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/openapi/walker.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,oBAAoB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qDAAqD;AACrD,MAAM,MAAM,MAAM,GAAG;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC/C,UAAU,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAC3E,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/openapi/walker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { Plugin } from '@databehave/core';
2
+ import type { OpenApiGenerator } from './catalog.js';
3
+ /** Structural deterministic placeholders, with diagnostic fallback for unsupported schemas. */
4
+ export declare const placeholderGenerator: () => OpenApiGenerator;
5
+ /** Explicit default provider; omit it when supplying a replacement provider. */
6
+ export declare const placeholderGeneratorPlugin: () => Plugin;
7
+ //# sourceMappingURL=placeholder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.d.ts","sourceRoot":"","sources":["../src/placeholder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGpD,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB,QAAO,gBAMtC,CAAA;AAEF,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,QAAO,MAI5C,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { openapiGeneratorCapability } from './catalog.js';
2
+ import { generateFromOasSchema } from './openapi/generate.js';
3
+ /** Structural deterministic placeholders, with diagnostic fallback for unsupported schemas. */
4
+ export const placeholderGenerator = () => ({
5
+ failureMode: 'fallback',
6
+ compile(schema, { document }) {
7
+ const body = generateFromOasSchema(schema, document);
8
+ return () => body;
9
+ },
10
+ });
11
+ /** Explicit default provider; omit it when supplying a replacement provider. */
12
+ export const placeholderGeneratorPlugin = () => ({
13
+ id: 'databehave.openapi.placeholder', apiVersion: 1,
14
+ provides: [openapiGeneratorCapability],
15
+ setup(ctx) { ctx.provide(openapiGeneratorCapability, placeholderGenerator()); },
16
+ });
17
+ //# sourceMappingURL=placeholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../src/placeholder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAE7D,+FAA+F;AAC/F,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAqB,EAAE,CAAC,CAAC;IAC3D,WAAW,EAAE,UAAU;IACvB,OAAO,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE;QAC1B,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACpD,OAAO,GAAG,EAAE,CAAC,IAAI,CAAA;IACnB,CAAC;CACF,CAAC,CAAA;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAW,EAAE,CAAC,CAAC;IACvD,EAAE,EAAE,gCAAgC,EAAE,UAAU,EAAE,CAAC;IACnD,QAAQ,EAAE,CAAC,0BAA0B,CAAC;IACtC,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,0BAA0B,EAAE,oBAAoB,EAAE,CAAC,CAAA,CAAC,CAAC;CAC/E,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { Capability, Plugin } from '@databehave/core';
2
+ import type { OpenApiDiagnostics, OpenApiGenerator } from './catalog.js';
3
+ /** Raw JSON document text; applications explicitly own filesystem and network loading. */
4
+ export interface OpenApiOptions extends OpenApiDiagnostics {
5
+ readonly document: string;
6
+ readonly generator?: Capability<OpenApiGenerator>;
7
+ }
8
+ /** Publish a catalog and generated HTTP routes after all sources have prepared. */
9
+ export declare const openapiPlugin: (options: OpenApiOptions) => Plugin;
10
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAI1D,OAAO,KAAK,EAAkB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGxF,0FAA0F;AAC1F,MAAM,WAAW,cAAe,SAAQ,kBAAkB;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;CAClD;AAED,mFAAmF;AACnF,eAAO,MAAM,aAAa,GAAI,SAAS,cAAc,KAAG,MAmCvD,CAAA"}
package/dist/plugin.js ADDED
@@ -0,0 +1,43 @@
1
+ import { httpCapability } from '@databehave/server';
2
+ import { openapiCapability, openapiGeneratorCapability, prepareCatalog } from './catalog.js';
3
+ import { parseOpenApi } from './openapi/loader.js';
4
+ /** Publish a catalog and generated HTTP routes after all sources have prepared. */
5
+ export const openapiPlugin = (options) => {
6
+ let catalog;
7
+ const prepared = () => {
8
+ if (!catalog)
9
+ throw new Error('OpenAPI catalog is unavailable before preparation');
10
+ return catalog;
11
+ };
12
+ const generator = options.generator ?? openapiGeneratorCapability;
13
+ return {
14
+ id: 'databehave.openapi', apiVersion: 1,
15
+ requires: [httpCapability, generator], provides: [openapiCapability],
16
+ setup(ctx) {
17
+ ctx.provide(openapiCapability, {
18
+ get document() { return prepared().document; },
19
+ get operations() { return prepared().operations; },
20
+ find: (method, path) => prepared().find(method, path),
21
+ body: (operation, status, request) => prepared().body(operation, status, request),
22
+ });
23
+ ctx.use(httpCapability).registerRoutes({
24
+ owner: 'databehave.openapi', order: ctx.order,
25
+ materialize: () => prepared().operations.map((operation) => ({
26
+ key: operation.key, priority: 'generated', source: 'openapi',
27
+ metadata: { summary: operation.definition.summary, operationId: operation.definition.operationId, responseStatuses: operation.responses.map(response => response.status) },
28
+ handler: request => {
29
+ const status = operation.successStatus;
30
+ if (status === 204 || status === 205)
31
+ return { status, empty: true };
32
+ const body = prepared().body(operation, status, request);
33
+ return { status, json: body === undefined ? (operation.method === 'get' || operation.method === 'head' ? {} : { success: true, message: null }) : body };
34
+ },
35
+ })),
36
+ });
37
+ },
38
+ async prepare(ctx) {
39
+ catalog = await prepareCatalog(parseOpenApi(options.document), ctx.use(generator), options);
40
+ },
41
+ };
42
+ };
43
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from '@databehave/core';
2
+ /** Request-conformance policy, independent from the selected response generator. */
3
+ export interface RequestValidationOptions {
4
+ /** UTF-8 byte limit for declared bodies; nonnegative safe integer. Default 102400; zero allows no bytes. */
5
+ readonly maxBodyBytes?: number;
6
+ }
7
+ export declare const requestValidationPlugin: (options?: RequestValidationOptions) => Plugin;
8
+ //# sourceMappingURL=request-validation-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-validation-plugin.d.ts","sourceRoot":"","sources":["../src/request-validation-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAM9C,oFAAoF;AACpF,MAAM,WAAW,wBAAwB;IACvC,4GAA4G;IAC5G,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,eAAO,MAAM,uBAAuB,GAAI,UAAS,wBAA6B,KAAG,MAiBhF,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { httpCapability } from '@databehave/server';
2
+ import { openapiCapability } from './catalog.js';
3
+ import { createRequestValidationContext, validateRequest } from './middleware/request-validation.js';
4
+ export const requestValidationPlugin = (options = {}) => {
5
+ let validation;
6
+ return {
7
+ id: 'databehave.openapi.request-validation', apiVersion: 1,
8
+ requires: [httpCapability, openapiCapability],
9
+ setup(ctx) {
10
+ ctx.use(httpCapability).registerMiddleware({
11
+ owner: 'databehave.openapi.request-validation', order: ctx.order, stage: 'validation',
12
+ async handle(request) {
13
+ if (!validation)
14
+ throw new Error('Request validation is unavailable before preparation');
15
+ const result = await validateRequest(request.raw(), validation, request.effectiveMethod);
16
+ if (result)
17
+ return { status: result.status, text: await result.text(), headers: Object.fromEntries(result.headers) };
18
+ },
19
+ });
20
+ },
21
+ prepare(ctx) { validation = createRequestValidationContext(ctx.use(openapiCapability), options); },
22
+ };
23
+ };
24
+ //# sourceMappingURL=request-validation-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-validation-plugin.js","sourceRoot":"","sources":["../src/request-validation-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,8BAA8B,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AASpG,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,UAAoC,EAAE,EAAU,EAAE;IACxF,IAAI,UAAgD,CAAA;IACpD,OAAO;QACL,EAAE,EAAE,uCAAuC,EAAE,UAAU,EAAE,CAAC;QAC1D,QAAQ,EAAE,CAAC,cAAc,EAAE,iBAAiB,CAAC;QAC7C,KAAK,CAAC,GAAG;YACP,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,kBAAkB,CAAC;gBACzC,KAAK,EAAE,uCAAuC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY;gBACrF,KAAK,CAAC,MAAM,CAAC,OAAO;oBAClB,IAAI,CAAC,UAAU;wBAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;oBACxF,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;oBACxF,IAAI,MAAM;wBAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;gBACtH,CAAC;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,IAAI,UAAU,GAAG,8BAA8B,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAA,CAAC,CAAC;KAClG,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from '@databehave/core';
2
+ import type { SchemaRuntime } from '@databehave/schema';
3
+ import type { OpenApiGenerator } from './catalog.js';
4
+ import type { SchemaBuilderApi } from './openapi/translate.js';
5
+ export type { OpenApiGenerator, OpenApiGenerationContext, OpenApiOperation, OpenApiResponse, OpenApiBodyGenerator } from './catalog.js';
6
+ export type { OasDoc, OasNode } from './openapi/walker.js';
7
+ export { translateOasToIR, type SchemaBuilderApi } from './openapi/translate.js';
8
+ /** Explicit builders plus an instance-scoped runtime; no implicit imports or standard registry. */
9
+ export interface SchemaGeneratorOptions {
10
+ readonly builders: SchemaBuilderApi;
11
+ readonly runtime: Pick<SchemaRuntime, 'mock'>;
12
+ readonly seed?: number | 'stable' | 'random';
13
+ }
14
+ /** Schema generation fails during preparation if any declared response schema is unsupported. */
15
+ export declare const schemaGenerator: (options: SchemaGeneratorOptions) => OpenApiGenerator;
16
+ /** Replace the placeholder provider with schema-backed generation for every catalog response. */
17
+ export declare const schemaGeneratorPlugin: (options: SchemaGeneratorOptions) => Plugin;
18
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAG9D,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACvI,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAEhF,mGAAmG;AACnG,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IAC7C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAC7C;AAKD,iGAAiG;AACjG,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,gBAYhE,CAAA;AAEF,iGAAiG;AACjG,eAAO,MAAM,qBAAqB,GAAI,SAAS,sBAAsB,KAAG,MAItE,CAAA"}
package/dist/schema.js ADDED
@@ -0,0 +1,26 @@
1
+ import { openapiGeneratorCapability } from './catalog.js';
2
+ import { translateOasToIR } from './openapi/translate.js';
3
+ import { hashSeed } from './openapi/auto-schema.js';
4
+ export { translateOasToIR } from './openapi/translate.js';
5
+ const sortedJoin = (record) => Object.keys(record).sort().map(key => `${key}=${record[key]}`).join('&');
6
+ /** Schema generation fails during preparation if any declared response schema is unsupported. */
7
+ export const schemaGenerator = (options) => ({
8
+ failureMode: 'throw',
9
+ async compile(schema, { document, operation }) {
10
+ const ir = await translateOasToIR(schema, document, options.builders);
11
+ return request => {
12
+ const setting = options.seed ?? 'stable';
13
+ const seed = typeof setting === 'number' ? setting >>> 0 : setting === 'random'
14
+ ? (Math.random() * 0xffffffff) >>> 0
15
+ : hashSeed(`${operation.method.toUpperCase()} ${operation.path}|${sortedJoin(request.query)}|${sortedJoin(request.params)}`);
16
+ return options.runtime.mock(ir, { seed });
17
+ };
18
+ },
19
+ });
20
+ /** Replace the placeholder provider with schema-backed generation for every catalog response. */
21
+ export const schemaGeneratorPlugin = (options) => ({
22
+ id: 'databehave.openapi.schema', apiVersion: 1,
23
+ provides: [openapiGeneratorCapability],
24
+ setup(ctx) { ctx.provide(openapiGeneratorCapability, schemaGenerator(options)); },
25
+ });
26
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAKnD,OAAO,EAAE,gBAAgB,EAAyB,MAAM,wBAAwB,CAAA;AAShF,MAAM,UAAU,GAAG,CAAC,MAAwC,EAAU,EAAE,CACtE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAE1E,iGAAiG;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAA+B,EAAoB,EAAE,CAAC,CAAC;IACrF,WAAW,EAAE,OAAO;IACpB,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;QAC3C,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QACrE,OAAO,OAAO,CAAC,EAAE;YACf,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAA;YACxC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ;gBAC7E,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC,IAAI,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC9H,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3C,CAAC,CAAA;IACH,CAAC;CACF,CAAC,CAAA;AAEF,iGAAiG;AACjG,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAA+B,EAAU,EAAE,CAAC,CAAC;IACjF,EAAE,EAAE,2BAA2B,EAAE,UAAU,EAAE,CAAC;IAC9C,QAAQ,EAAE,CAAC,0BAA0B,CAAC;IACtC,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,0BAA0B,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAA,CAAC,CAAC;CACjF,CAAC,CAAA"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Hand-rolled, zero-runtime-dependency JSON-Schema-subset validator.
3
+ *
4
+ * Audit-it-yourself moat: small, defensive, top-to-bottom readable.
5
+ * FAIL LOUD on unsupported keywords at build time — never silently
6
+ * pass an unrecognised constraint at runtime.
7
+ *
8
+ * Supported keywords (see README → "Validator scope" for the table):
9
+ * type / enum / required / properties / additionalProperties /
10
+ * items / pattern / minLength / maxLength / minimum / maximum /
11
+ * exclusiveMinimum / exclusiveMaximum / minItems / maxItems /
12
+ * $ref (intra-document only) / oneOf / anyOf / allOf /
13
+ * discriminator / format (date | date-time | email | uuid | uri) /
14
+ * nullable (OAS 3.0) and ["X","null"] (OAS 3.1).
15
+ *
16
+ * Security guarantees implemented in this file:
17
+ * - No `eval`, no `new Function`, no dynamic `require`. Pure recursion.
18
+ * - Prototype-pollution guard: input objects whose own keys include
19
+ * `__proto__` / `constructor` / `prototype` are rejected as a
20
+ * per-property violation rather than coerced or thrown on.
21
+ * - ReDoS mitigation: pattern length capped at 1024 chars; invalid
22
+ * regexes rejected at build time (never at request time).
23
+ * - Recursion bounded: hard-cap depth at 64 levels.
24
+ * - $ref cycle detection via a build-time visited-pointer set.
25
+ * - No `JSON.parse` on user input — input arrives as a JS value.
26
+ */
27
+ import type { OasDoc, OasNode } from '../openapi/walker.js';
28
+ /** One conformance failure at a JSON pointer. */
29
+ export interface Violation {
30
+ /** JSON-Pointer style path from the validation root. */
31
+ readonly path: string;
32
+ /** The JSON Schema keyword that rejected the value. */
33
+ readonly keyword: string;
34
+ /** Short, human-readable description. Never echoes user input. */
35
+ readonly message: string;
36
+ }
37
+ /** A prepared value check returning all detected violations. */
38
+ export type Validator = (value: unknown, pointer: string) => Violation[];
39
+ export declare const compileValidator: (node: OasNode, doc: OasDoc, schemaPointer?: string) => Validator;
40
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validation/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAE3D,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,gEAAgE;AAChE,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAA;AAsHxE,eAAO,MAAM,gBAAgB,GAC3B,MAAM,OAAO,EACb,KAAK,MAAM,EACX,sBAAmB,KAClB,SAAwE,CAAA"}