@lssm/lib.contracts-transformers 0.0.0-canary-20251220041653 → 0.0.0-canary-20251221132705
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 +2 -2
- package/dist/common/index.d.ts +2 -2
- package/dist/common/types.d.ts +16 -10
- package/dist/common/types.d.ts.map +1 -1
- package/dist/index.d.ts +15 -6
- package/dist/index.js +13 -4
- package/dist/openapi/differ.d.ts +6 -6
- package/dist/openapi/differ.d.ts.map +1 -1
- package/dist/openapi/differ.js +11 -4
- package/dist/openapi/differ.js.map +1 -1
- package/dist/openapi/exporter/data-views.d.ts +38 -0
- package/dist/openapi/exporter/data-views.d.ts.map +1 -0
- package/dist/openapi/exporter/data-views.js +47 -0
- package/dist/openapi/exporter/data-views.js.map +1 -0
- package/dist/openapi/exporter/events.d.ts +28 -0
- package/dist/openapi/exporter/events.d.ts.map +1 -0
- package/dist/openapi/exporter/events.js +39 -0
- package/dist/openapi/exporter/events.js.map +1 -0
- package/dist/openapi/exporter/features.d.ts +37 -0
- package/dist/openapi/exporter/features.d.ts.map +1 -0
- package/dist/openapi/exporter/features.js +46 -0
- package/dist/openapi/exporter/features.js.map +1 -0
- package/dist/openapi/exporter/forms.d.ts +30 -0
- package/dist/openapi/exporter/forms.d.ts.map +1 -0
- package/dist/openapi/exporter/forms.js +49 -0
- package/dist/openapi/exporter/forms.js.map +1 -0
- package/dist/openapi/exporter/index.js +8 -0
- package/dist/openapi/exporter/operations.d.ts +65 -0
- package/dist/openapi/exporter/operations.d.ts.map +1 -0
- package/dist/openapi/exporter/operations.js +142 -0
- package/dist/openapi/exporter/operations.js.map +1 -0
- package/dist/openapi/exporter/presentations.d.ts +48 -0
- package/dist/openapi/exporter/presentations.d.ts.map +1 -0
- package/dist/openapi/exporter/presentations.js +66 -0
- package/dist/openapi/exporter/presentations.js.map +1 -0
- package/dist/openapi/exporter/registries.d.ts +23 -0
- package/dist/openapi/exporter/registries.d.ts.map +1 -0
- package/dist/openapi/exporter/registries.js +29 -0
- package/dist/openapi/exporter/registries.js.map +1 -0
- package/dist/openapi/exporter/workflows.d.ts +36 -0
- package/dist/openapi/exporter/workflows.d.ts.map +1 -0
- package/dist/openapi/exporter/workflows.js +54 -0
- package/dist/openapi/exporter/workflows.js.map +1 -0
- package/dist/openapi/exporter.d.ts +35 -15
- package/dist/openapi/exporter.d.ts.map +1 -1
- package/dist/openapi/exporter.js +78 -104
- package/dist/openapi/exporter.js.map +1 -1
- package/dist/openapi/importer/analyzer.js +28 -0
- package/dist/openapi/importer/analyzer.js.map +1 -0
- package/dist/openapi/importer/events.js +36 -0
- package/dist/openapi/importer/events.js.map +1 -0
- package/dist/openapi/importer/generator.js +71 -0
- package/dist/openapi/importer/generator.js.map +1 -0
- package/dist/openapi/importer/grouping.js +73 -0
- package/dist/openapi/importer/grouping.js.map +1 -0
- package/dist/openapi/importer/index.d.ts +17 -0
- package/dist/openapi/importer/index.d.ts.map +1 -0
- package/dist/openapi/importer/index.js +161 -0
- package/dist/openapi/importer/index.js.map +1 -0
- package/dist/openapi/importer/models.js +19 -0
- package/dist/openapi/importer/models.js.map +1 -0
- package/dist/openapi/importer/schemas.js +80 -0
- package/dist/openapi/importer/schemas.js.map +1 -0
- package/dist/openapi/index.d.ts +14 -5
- package/dist/openapi/index.js +15 -4
- package/dist/openapi/parser/document.d.ts +20 -0
- package/dist/openapi/parser/document.d.ts.map +1 -0
- package/dist/openapi/parser/document.js +95 -0
- package/dist/openapi/parser/document.js.map +1 -0
- package/dist/openapi/parser/index.js +5 -0
- package/dist/openapi/parser/operation.js +59 -0
- package/dist/openapi/parser/operation.js.map +1 -0
- package/dist/openapi/parser/parameters.js +37 -0
- package/dist/openapi/parser/parameters.js.map +1 -0
- package/dist/openapi/parser/resolvers.js +63 -0
- package/dist/openapi/parser/resolvers.js.map +1 -0
- package/dist/openapi/parser/utils.d.ts +19 -0
- package/dist/openapi/parser/utils.d.ts.map +1 -0
- package/dist/openapi/parser/utils.js +48 -0
- package/dist/openapi/parser/utils.js.map +1 -0
- package/dist/openapi/parser.js +6 -232
- package/dist/openapi/schema-converter.d.ts +7 -1
- package/dist/openapi/schema-converter.d.ts.map +1 -1
- package/dist/openapi/schema-converter.js +117 -20
- package/dist/openapi/schema-converter.js.map +1 -1
- package/dist/openapi/types.d.ts +75 -20
- package/dist/openapi/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/openapi/importer.d.ts +0 -16
- package/dist/openapi/importer.d.ts.map +0 -1
- package/dist/openapi/importer.js +0 -265
- package/dist/openapi/importer.js.map +0 -1
- package/dist/openapi/parser.d.ts +0 -32
- package/dist/openapi/parser.d.ts.map +0 -1
- package/dist/openapi/parser.js.map +0 -1
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ bun add @lssm/lib.contracts-transformers
|
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
20
|
import { openApiForRegistry } from '@lssm/lib.contracts-transformers/openapi';
|
|
21
|
-
import {
|
|
21
|
+
import { OperationSpecRegistry } from '@lssm/lib.contracts';
|
|
22
22
|
|
|
23
|
-
const registry = new
|
|
23
|
+
const registry = new OperationSpecRegistry();
|
|
24
24
|
// ... register your specs ...
|
|
25
25
|
|
|
26
26
|
const openApiDoc = openApiForRegistry(registry, {
|
package/dist/common/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { DiffChange, DiffChangeType, ImportResult,
|
|
1
|
+
import { DiffChange, DiffChangeType, ImportResult, ImportedOperationSpec, SpecDiff, SpecSource, SyncResult, TransportHints, ValidationResult } from "./types.js";
|
|
2
2
|
import { deepEqual, extractPathParams, getByPath, normalizePath, toCamelCase, toFileName, toKebabCase, toPascalCase, toSnakeCase, toSpecName, toValidIdentifier } from "./utils.js";
|
|
3
|
-
export { DiffChange, DiffChangeType, ImportResult,
|
|
3
|
+
export { DiffChange, DiffChangeType, ImportResult, ImportedOperationSpec, SpecDiff, SpecSource, SyncResult, TransportHints, ValidationResult, deepEqual, extractPathParams, getByPath, normalizePath, toCamelCase, toFileName, toKebabCase, toPascalCase, toSnakeCase, toSpecName, toValidIdentifier };
|
package/dist/common/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AnyOperationSpec } from "@lssm/lib.contracts";
|
|
2
2
|
|
|
3
3
|
//#region src/common/types.d.ts
|
|
4
4
|
|
|
@@ -40,13 +40,19 @@ interface TransportHints {
|
|
|
40
40
|
/**
|
|
41
41
|
* Result of importing a single spec from an external format.
|
|
42
42
|
*/
|
|
43
|
-
interface
|
|
44
|
-
/**
|
|
45
|
-
|
|
43
|
+
interface ImportedOperationSpec {
|
|
44
|
+
/**
|
|
45
|
+
* The generated ContractSpec.
|
|
46
|
+
* Optional because during code generation the actual spec object is not
|
|
47
|
+
* available until the generated code is executed at runtime.
|
|
48
|
+
*/
|
|
49
|
+
operationSpec?: AnyOperationSpec;
|
|
46
50
|
/** Generated TypeScript code for the spec */
|
|
47
51
|
code: string;
|
|
48
52
|
/** Suggested file name for the spec */
|
|
49
53
|
fileName: string;
|
|
54
|
+
/** Group folder for organizing the file (based on grouping config) */
|
|
55
|
+
groupFolder?: string;
|
|
50
56
|
/** Source information for provenance tracking */
|
|
51
57
|
source: SpecSource;
|
|
52
58
|
/** Transport hints for accurate round-trips */
|
|
@@ -57,7 +63,7 @@ interface ImportedSpec {
|
|
|
57
63
|
*/
|
|
58
64
|
interface ImportResult {
|
|
59
65
|
/** Successfully imported specs */
|
|
60
|
-
|
|
66
|
+
operationSpecs: ImportedOperationSpec[];
|
|
61
67
|
/** Specs that were skipped (e.g., unsupported features) */
|
|
62
68
|
skipped: {
|
|
63
69
|
sourceId: string;
|
|
@@ -102,9 +108,9 @@ interface SpecDiff {
|
|
|
102
108
|
/** Identifier for the operation */
|
|
103
109
|
operationId: string;
|
|
104
110
|
/** Existing ContractSpec (if any) */
|
|
105
|
-
existing?:
|
|
111
|
+
existing?: AnyOperationSpec;
|
|
106
112
|
/** Incoming imported spec */
|
|
107
|
-
incoming:
|
|
113
|
+
incoming: ImportedOperationSpec;
|
|
108
114
|
/** List of detected changes */
|
|
109
115
|
changes: DiffChange[];
|
|
110
116
|
/** Whether specs are semantically equivalent */
|
|
@@ -117,10 +123,10 @@ interface SpecDiff {
|
|
|
117
123
|
*/
|
|
118
124
|
interface SyncResult {
|
|
119
125
|
/** Specs that were added (new imports) */
|
|
120
|
-
added:
|
|
126
|
+
added: ImportedOperationSpec[];
|
|
121
127
|
/** Specs that were updated */
|
|
122
128
|
updated: {
|
|
123
|
-
spec:
|
|
129
|
+
spec: ImportedOperationSpec;
|
|
124
130
|
changes: DiffChange[];
|
|
125
131
|
}[];
|
|
126
132
|
/** Specs that were kept unchanged */
|
|
@@ -149,5 +155,5 @@ interface ValidationResult {
|
|
|
149
155
|
warnings: string[];
|
|
150
156
|
}
|
|
151
157
|
//#endregion
|
|
152
|
-
export { DiffChange, DiffChangeType, ImportResult,
|
|
158
|
+
export { DiffChange, DiffChangeType, ImportResult, ImportedOperationSpec, SpecDiff, SpecSource, SyncResult, TransportHints, ValidationResult };
|
|
153
159
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/common/types.ts"],"sourcesContent":[],"mappings":";;;;AA0BA;AAoBA;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/common/types.ts"],"sourcesContent":[],"mappings":";;;;AA0BA;AAoBA;;AAcU,UAnDO,UAAA,CAmDP;EAEQ;EAAc,IAAA,EAAA,SAAA,GAAA,UAAA,GAAA,SAAA,GAAA,UAAA;EAMf;EAyBL,GAAA,CAAA,EAAA,MAAA;EAUK;EAgBA,IAAA,CAAA,EAAA,MAAQ;EAIZ;EAED,QAAA,EAAA,MAAA;EAED;EAAU,UAAA,EA5GP,IA4GO;AAUrB;;;;;AAWqB,UA1HJ,cAAA,CA0HI;EAaJ,IAAA,CAAA,EAAA;;;;;;;;;;;;;;;;;;UAnHA,qBAAA;;;;;;kBAMC;;;;;;;;UAQR;;kBAEQ;;;;;UAMD,YAAA;;kBAEC;;;;;;;;;;;;;;;;;;;;;;KAuBN,cAAA;;;;UAUK,UAAA;;;;QAIT;;;;;;;;;;;UAYS,QAAA;;;;aAIJ;;YAED;;WAED;;;;;;;;;UAUM,UAAA;;SAER;;;UAGC;aACG;;;;;aAKA;;;;;;;;;;;;UAaI,gBAAA;;;;SAIR"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { DiffChange, DiffChangeType, ImportResult,
|
|
1
|
+
import { DiffChange, DiffChangeType, ImportResult, ImportedOperationSpec, SpecDiff, SpecSource, SyncResult, TransportHints, ValidationResult } from "./common/types.js";
|
|
2
2
|
import { deepEqual, extractPathParams, getByPath, normalizePath, toCamelCase, toFileName, toKebabCase, toPascalCase, toSnakeCase, toSpecName, toValidIdentifier } from "./common/utils.js";
|
|
3
|
-
import { ContractSpecOpenApiDocument, HttpMethod, OpenApiDocument, OpenApiExportOptions,
|
|
4
|
-
import { detectFormat, detectVersion,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { ContractSpecOpenApiDocument, HttpMethod, OpenApiDocument, OpenApiExportOptions, OpenApiOperation, OpenApiParameter, OpenApiParseOptions, OpenApiSchema, OpenApiServer, OpenApiSource, OpenApiTransportHints, OpenApiVersion, ParameterLocation, ParseResult, ParsedOperation, ParsedParameter } from "./openapi/types.js";
|
|
4
|
+
import { detectFormat, detectVersion, parseOpenApiString } from "./openapi/parser/utils.js";
|
|
5
|
+
import { parseOpenApi, parseOpenApiDocument } from "./openapi/parser/document.js";
|
|
6
|
+
import { OperationsExportResult, defaultRestPath, exportOperations, generateOperationsRegistry, jsonSchemaForSpec, schemaModelToJsonSchema, toHttpMethod, toOperationId, toRestPath, toSchemaName } from "./openapi/exporter/operations.js";
|
|
7
|
+
import { ContractSpecRegistries, contractSpecToJson, contractSpecToYaml, exportContractSpec, openApiForRegistry, openApiToJson, openApiToYaml } from "./openapi/exporter.js";
|
|
8
|
+
import { ExportedEvent, exportEvents, generateEventsExports } from "./openapi/exporter/events.js";
|
|
9
|
+
import { ExportedFeature, exportFeatures, generateFeaturesRegistry } from "./openapi/exporter/features.js";
|
|
10
|
+
import { ExportedPresentation, ExportedPresentationV2, exportPresentations, exportPresentationsV1, exportPresentationsV2, generatePresentationsRegistry } from "./openapi/exporter/presentations.js";
|
|
11
|
+
import { ExportedForm, exportForms, generateFormsRegistry } from "./openapi/exporter/forms.js";
|
|
12
|
+
import { ExportedDataView, exportDataViews, generateDataViewsRegistry } from "./openapi/exporter/data-views.js";
|
|
13
|
+
import { ExportedWorkflow, exportWorkflows, generateWorkflowsRegistry } from "./openapi/exporter/workflows.js";
|
|
14
|
+
import { RegistryGenerationOptions, generateRegistryIndex } from "./openapi/exporter/registries.js";
|
|
7
15
|
import { GeneratedModel, SchemaField, TypescriptType, generateImports, generateSchemaModelCode, getScalarType, jsonSchemaToField, jsonSchemaToType } from "./openapi/schema-converter.js";
|
|
16
|
+
import { importFromOpenApi, importOperation } from "./openapi/importer/index.js";
|
|
8
17
|
import { DiffOptions, createSpecDiff, diffAll, diffSpecVsOperation, diffSpecs, formatDiffChanges } from "./openapi/differ.js";
|
|
9
|
-
export { ContractSpecOpenApiDocument, DiffChange, DiffChangeType, DiffOptions, GeneratedModel, HttpMethod, ImportResult,
|
|
18
|
+
export { ContractSpecOpenApiDocument, ContractSpecRegistries, DiffChange, DiffChangeType, DiffOptions, ExportedDataView, ExportedEvent, ExportedFeature, ExportedForm, ExportedPresentation, ExportedPresentationV2, ExportedWorkflow, GeneratedModel, HttpMethod, ImportResult, ImportedOperationSpec, OpenApiDocument, OpenApiExportOptions, OpenApiOperation, OpenApiParameter, OpenApiParseOptions, OpenApiSchema, OpenApiServer, OpenApiSource, OpenApiTransportHints, OpenApiVersion, OperationsExportResult, ParameterLocation, ParseResult, ParsedOperation, ParsedParameter, RegistryGenerationOptions, SchemaField, SpecDiff, SpecSource, SyncResult, TransportHints, TypescriptType, ValidationResult, contractSpecToJson, contractSpecToYaml, createSpecDiff, deepEqual, defaultRestPath, detectFormat, detectVersion, diffAll, diffSpecVsOperation, diffSpecs, exportContractSpec, exportDataViews, exportEvents, exportFeatures, exportForms, exportOperations, exportPresentations, exportPresentationsV1, exportPresentationsV2, exportWorkflows, extractPathParams, formatDiffChanges, generateDataViewsRegistry, generateEventsExports, generateFeaturesRegistry, generateFormsRegistry, generateImports, generateOperationsRegistry, generatePresentationsRegistry, generateRegistryIndex, generateSchemaModelCode, generateWorkflowsRegistry, getByPath, getScalarType, importFromOpenApi, importOperation, jsonSchemaForSpec, jsonSchemaToField, jsonSchemaToType, normalizePath, openApiForRegistry, openApiToJson, openApiToYaml, parseOpenApi, parseOpenApiDocument, parseOpenApiString, schemaModelToJsonSchema, toCamelCase, toFileName, toHttpMethod, toKebabCase, toOperationId, toPascalCase, toRestPath, toSchemaName, toSnakeCase, toSpecName, toValidIdentifier };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { detectFormat, detectVersion,
|
|
2
|
-
import {
|
|
1
|
+
import { detectFormat, detectVersion, parseOpenApiString } from "./openapi/parser/utils.js";
|
|
2
|
+
import { parseOpenApi, parseOpenApiDocument } from "./openapi/parser/document.js";
|
|
3
|
+
import { defaultRestPath, exportOperations, generateOperationsRegistry, jsonSchemaForSpec, schemaModelToJsonSchema, toHttpMethod, toOperationId, toRestPath, toSchemaName } from "./openapi/exporter/operations.js";
|
|
4
|
+
import { exportEvents, generateEventsExports } from "./openapi/exporter/events.js";
|
|
5
|
+
import { exportFeatures, generateFeaturesRegistry } from "./openapi/exporter/features.js";
|
|
6
|
+
import { exportPresentations, exportPresentationsV1, exportPresentationsV2, generatePresentationsRegistry } from "./openapi/exporter/presentations.js";
|
|
7
|
+
import { exportForms, generateFormsRegistry } from "./openapi/exporter/forms.js";
|
|
8
|
+
import { exportDataViews, generateDataViewsRegistry } from "./openapi/exporter/data-views.js";
|
|
9
|
+
import { exportWorkflows, generateWorkflowsRegistry } from "./openapi/exporter/workflows.js";
|
|
10
|
+
import { generateRegistryIndex } from "./openapi/exporter/registries.js";
|
|
11
|
+
import { contractSpecToJson, contractSpecToYaml, exportContractSpec, openApiForRegistry, openApiToJson, openApiToYaml } from "./openapi/exporter.js";
|
|
3
12
|
import { deepEqual, extractPathParams, getByPath, normalizePath, toCamelCase, toFileName, toKebabCase, toPascalCase, toSnakeCase, toSpecName, toValidIdentifier } from "./common/utils.js";
|
|
4
13
|
import { generateImports, generateSchemaModelCode, getScalarType, jsonSchemaToField, jsonSchemaToType } from "./openapi/schema-converter.js";
|
|
5
|
-
import { importFromOpenApi, importOperation } from "./openapi/importer.js";
|
|
14
|
+
import { importFromOpenApi, importOperation } from "./openapi/importer/index.js";
|
|
6
15
|
import { createSpecDiff, diffAll, diffSpecVsOperation, diffSpecs, formatDiffChanges } from "./openapi/differ.js";
|
|
7
16
|
import "./openapi/index.js";
|
|
8
17
|
|
|
9
|
-
export { createSpecDiff, deepEqual, defaultRestPath, detectFormat, detectVersion, diffAll, diffSpecVsOperation, diffSpecs, extractPathParams, formatDiffChanges, generateImports, generateSchemaModelCode, getByPath, getScalarType, importFromOpenApi, importOperation, jsonSchemaToField, jsonSchemaToType, normalizePath, openApiForRegistry, openApiToJson, openApiToYaml, parseOpenApi, parseOpenApiDocument, parseOpenApiString, toCamelCase, toFileName, toKebabCase, toPascalCase, toSnakeCase, toSpecName, toValidIdentifier };
|
|
18
|
+
export { contractSpecToJson, contractSpecToYaml, createSpecDiff, deepEqual, defaultRestPath, detectFormat, detectVersion, diffAll, diffSpecVsOperation, diffSpecs, exportContractSpec, exportDataViews, exportEvents, exportFeatures, exportForms, exportOperations, exportPresentations, exportPresentationsV1, exportPresentationsV2, exportWorkflows, extractPathParams, formatDiffChanges, generateDataViewsRegistry, generateEventsExports, generateFeaturesRegistry, generateFormsRegistry, generateImports, generateOperationsRegistry, generatePresentationsRegistry, generateRegistryIndex, generateSchemaModelCode, generateWorkflowsRegistry, getByPath, getScalarType, importFromOpenApi, importOperation, jsonSchemaForSpec, jsonSchemaToField, jsonSchemaToType, normalizePath, openApiForRegistry, openApiToJson, openApiToYaml, parseOpenApi, parseOpenApiDocument, parseOpenApiString, schemaModelToJsonSchema, toCamelCase, toFileName, toHttpMethod, toKebabCase, toOperationId, toPascalCase, toRestPath, toSchemaName, toSnakeCase, toSpecName, toValidIdentifier };
|
package/dist/openapi/differ.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DiffChange,
|
|
1
|
+
import { DiffChange, ImportedOperationSpec, SpecDiff } from "../common/types.js";
|
|
2
2
|
import { ParsedOperation } from "./types.js";
|
|
3
|
-
import {
|
|
3
|
+
import { AnyOperationSpec } from "@lssm/lib.contracts";
|
|
4
4
|
|
|
5
5
|
//#region src/openapi/differ.d.ts
|
|
6
6
|
|
|
@@ -20,19 +20,19 @@ interface DiffOptions {
|
|
|
20
20
|
/**
|
|
21
21
|
* Diff a ContractSpec against an OpenAPI operation.
|
|
22
22
|
*/
|
|
23
|
-
declare function diffSpecVsOperation(spec:
|
|
23
|
+
declare function diffSpecVsOperation(spec: AnyOperationSpec, operation: ParsedOperation, options?: DiffOptions): DiffChange[];
|
|
24
24
|
/**
|
|
25
25
|
* Diff two ContractSpecs.
|
|
26
26
|
*/
|
|
27
|
-
declare function diffSpecs(oldSpec:
|
|
27
|
+
declare function diffSpecs(oldSpec: AnyOperationSpec, newSpec: AnyOperationSpec, options?: DiffOptions): DiffChange[];
|
|
28
28
|
/**
|
|
29
29
|
* Create a SpecDiff from an existing spec and an imported spec.
|
|
30
30
|
*/
|
|
31
|
-
declare function createSpecDiff(operationId: string, existing:
|
|
31
|
+
declare function createSpecDiff(operationId: string, existing: AnyOperationSpec | undefined, incoming: ImportedOperationSpec, options?: DiffOptions): SpecDiff;
|
|
32
32
|
/**
|
|
33
33
|
* Batch diff multiple specs against OpenAPI operations.
|
|
34
34
|
*/
|
|
35
|
-
declare function diffAll(existingSpecs: Map<string,
|
|
35
|
+
declare function diffAll(existingSpecs: Map<string, AnyOperationSpec>, importedSpecs: ImportedOperationSpec[], options?: DiffOptions): SpecDiff[];
|
|
36
36
|
/**
|
|
37
37
|
* Format diff changes for display.
|
|
38
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"differ.d.ts","names":[],"sources":["../../src/openapi/differ.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAwIG,UAtHc,WAAA,CAsHd;EAAU;EA2EG,kBAAS,CAAA,EAAA,OAAA;EACd;EACA,UAAA,CAAA,EAAA,OAAA;EACA;EACR,eAAA,CAAA,EAAA,OAAA;EAAU;EA+CG,WAAA,CAAA,EAAA,MAAc,EAAA;;;;;AAKnB,iBAvIK,mBAAA,CAuIL,IAAA,EAtIH,
|
|
1
|
+
{"version":3,"file":"differ.d.ts","names":[],"sources":["../../src/openapi/differ.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAwIG,UAtHc,WAAA,CAsHd;EAAU;EA2EG,kBAAS,CAAA,EAAA,OAAA;EACd;EACA,UAAA,CAAA,EAAA,OAAA;EACA;EACR,eAAA,CAAA,EAAA,OAAA;EAAU;EA+CG,WAAA,CAAA,EAAA,MAAc,EAAA;;;;;AAKnB,iBAvIK,mBAAA,CAuIL,IAAA,EAtIH,gBAsIG,EAAA,SAAA,EArIE,eAqIF,EAAA,OAAA,CAAA,EApIA,WAoIA,CAAA,EAnIR,UAmIQ,EAAA;AA4CX;;;AAEiB,iBAtGD,SAAA,CAsGC,OAAA,EArGN,gBAqGM,EAAA,OAAA,EApGN,gBAoGM,EAAA,OAAA,CAAA,EAnGN,WAmGM,CAAA,EAlGd,UAkGc,EAAA;;;;AAsDD,iBAzGA,cAAA,CAyG2B,WAAU,EAAA,MAAA,EAAA,QAAA,EAvGzC,gBAuGyC,GAAA,SAAA,EAAA,QAAA,EAtGzC,qBAsGyC,EAAA,OAAA,CAAA,EArG1C,WAqG0C,CAAA,EApGlD,QAoGkD;;;;iBAxDrC,OAAA,gBACC,YAAY,kCACZ,mCACN,cACR;;;;iBAoDa,iBAAA,UAA2B"}
|
package/dist/openapi/differ.js
CHANGED
|
@@ -136,13 +136,20 @@ function diffSpecs(oldSpec, newSpec, options = {}) {
|
|
|
136
136
|
function createSpecDiff(operationId, existing, incoming, options = {}) {
|
|
137
137
|
let changes = [];
|
|
138
138
|
let isEquivalent = false;
|
|
139
|
-
if (existing) {
|
|
140
|
-
changes = diffSpecs(existing, incoming.
|
|
139
|
+
if (existing && incoming.operationSpec) {
|
|
140
|
+
changes = diffSpecs(existing, incoming.operationSpec, options);
|
|
141
141
|
isEquivalent = changes.length === 0;
|
|
142
|
-
} else changes = [{
|
|
142
|
+
} else if (existing && !incoming.operationSpec) changes = [{
|
|
143
|
+
path: "",
|
|
144
|
+
type: "modified",
|
|
145
|
+
oldValue: existing,
|
|
146
|
+
newValue: incoming.code,
|
|
147
|
+
description: "Spec code imported from OpenAPI (runtime comparison not available)"
|
|
148
|
+
}];
|
|
149
|
+
else changes = [{
|
|
143
150
|
path: "",
|
|
144
151
|
type: "added",
|
|
145
|
-
newValue: incoming.
|
|
152
|
+
newValue: incoming.operationSpec ?? incoming.code,
|
|
146
153
|
description: "New spec imported from OpenAPI"
|
|
147
154
|
}];
|
|
148
155
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"differ.js","names":["changeType: DiffChangeType","changes: DiffChange[]","diffs: SpecDiff[]","existing: AnyContractSpec | undefined","lines: string[]"],"sources":["../../src/openapi/differ.ts"],"sourcesContent":["/**\n * Diff ContractSpec specs against OpenAPI operations.\n * Used for sync operations to detect changes.\n */\n\nimport type { AnyContractSpec } from '@lssm/lib.contracts';\nimport type { ParsedOperation } from './types';\nimport type {\n SpecDiff,\n DiffChange,\n DiffChangeType,\n ImportedSpec,\n} from '../common/types';\nimport { deepEqual } from '../common/utils';\n\n/**\n * Options for diffing specs.\n */\nexport interface DiffOptions {\n /** Ignore description changes */\n ignoreDescriptions?: boolean;\n /** Ignore tag changes */\n ignoreTags?: boolean;\n /** Ignore transport changes (path, method) */\n ignoreTransport?: boolean;\n /** Custom paths to ignore */\n ignorePaths?: string[];\n}\n\n/**\n * Compare two values and generate a diff change if different.\n */\nfunction compareValues(\n path: string,\n oldValue: unknown,\n newValue: unknown,\n description: string\n): DiffChange | null {\n if (deepEqual(oldValue, newValue)) {\n return null;\n }\n\n let changeType: DiffChangeType = 'modified';\n if (oldValue === undefined || oldValue === null) {\n changeType = 'added';\n } else if (newValue === undefined || newValue === null) {\n changeType = 'removed';\n } else if (typeof oldValue !== typeof newValue) {\n changeType = 'type_changed';\n }\n\n return {\n path,\n type: changeType,\n oldValue,\n newValue,\n description,\n };\n}\n\n/**\n * Diff two objects recursively.\n */\nfunction diffObjects(\n path: string,\n oldObj: Record<string, unknown> | undefined,\n newObj: Record<string, unknown> | undefined,\n options: DiffOptions\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n if (!oldObj && !newObj) return changes;\n if (!oldObj) {\n changes.push({\n path,\n type: 'added',\n newValue: newObj,\n description: `Added ${path}`,\n });\n return changes;\n }\n if (!newObj) {\n changes.push({\n path,\n type: 'removed',\n oldValue: oldObj,\n description: `Removed ${path}`,\n });\n return changes;\n }\n\n const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n\n // Skip ignored paths\n if (options.ignorePaths?.some((p) => keyPath.startsWith(p))) {\n continue;\n }\n\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (typeof oldVal === 'object' && typeof newVal === 'object') {\n changes.push(\n ...diffObjects(\n keyPath,\n oldVal as Record<string, unknown>,\n newVal as Record<string, unknown>,\n options\n )\n );\n } else {\n const change = compareValues(\n keyPath,\n oldVal,\n newVal,\n `Changed ${keyPath}`\n );\n if (change) {\n changes.push(change);\n }\n }\n }\n\n return changes;\n}\n\n/**\n * Diff a ContractSpec against an OpenAPI operation.\n */\nexport function diffSpecVsOperation(\n spec: AnyContractSpec,\n operation: ParsedOperation,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare basic metadata\n if (!options.ignoreDescriptions) {\n const descChange = compareValues(\n 'meta.description',\n spec.meta.description,\n operation.summary ?? operation.description,\n 'Description changed'\n );\n if (descChange) changes.push(descChange);\n }\n\n if (!options.ignoreTags) {\n const oldTags = [...(spec.meta.tags ?? [])].sort();\n const newTags = [...operation.tags].sort();\n if (!deepEqual(oldTags, newTags)) {\n changes.push({\n path: 'meta.tags',\n type: 'modified',\n oldValue: oldTags,\n newValue: newTags,\n description: 'Tags changed',\n });\n }\n }\n\n // Compare transport\n if (!options.ignoreTransport) {\n const specMethod =\n spec.transport?.rest?.method ??\n (spec.meta.kind === 'query' ? 'GET' : 'POST');\n const opMethod = operation.method.toUpperCase();\n\n if (specMethod !== opMethod) {\n changes.push({\n path: 'transport.rest.method',\n type: 'modified',\n oldValue: specMethod,\n newValue: opMethod,\n description: 'HTTP method changed',\n });\n }\n\n const specPath = spec.transport?.rest?.path;\n if (specPath && specPath !== operation.path) {\n changes.push({\n path: 'transport.rest.path',\n type: 'modified',\n oldValue: specPath,\n newValue: operation.path,\n description: 'Path changed',\n });\n }\n }\n\n // Compare deprecation status\n const specDeprecated = spec.meta.stability === 'deprecated';\n if (specDeprecated !== operation.deprecated) {\n changes.push({\n path: 'meta.stability',\n type: 'modified',\n oldValue: spec.meta.stability,\n newValue: operation.deprecated ? 'deprecated' : 'stable',\n description: 'Deprecation status changed',\n });\n }\n\n return changes;\n}\n\n/**\n * Diff two ContractSpecs.\n */\nexport function diffSpecs(\n oldSpec: AnyContractSpec,\n newSpec: AnyContractSpec,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare meta\n const metaChanges = diffObjects(\n 'meta',\n oldSpec.meta as unknown as Record<string, unknown>,\n newSpec.meta as unknown as Record<string, unknown>,\n {\n ...options,\n ignorePaths: [\n ...(options.ignorePaths ?? []),\n ...(options.ignoreDescriptions\n ? ['meta.description', 'meta.goal', 'meta.context']\n : []),\n ...(options.ignoreTags ? ['meta.tags'] : []),\n ],\n }\n );\n changes.push(...metaChanges);\n\n // Compare transport\n if (!options.ignoreTransport) {\n const transportChanges = diffObjects(\n 'transport',\n oldSpec.transport as unknown as Record<string, unknown>,\n newSpec.transport as unknown as Record<string, unknown>,\n options\n );\n changes.push(...transportChanges);\n }\n\n // Compare policy\n const policyChanges = diffObjects(\n 'policy',\n oldSpec.policy as unknown as Record<string, unknown>,\n newSpec.policy as unknown as Record<string, unknown>,\n options\n );\n changes.push(...policyChanges);\n\n return changes;\n}\n\n/**\n * Create a SpecDiff from an existing spec and an imported spec.\n */\nexport function createSpecDiff(\n operationId: string,\n existing: AnyContractSpec | undefined,\n incoming: ImportedSpec,\n options: DiffOptions = {}\n): SpecDiff {\n let changes: DiffChange[] = [];\n let isEquivalent = false;\n\n if (existing) {\n // Compare existing vs incoming\n changes = diffSpecs(existing, incoming.spec, options);\n isEquivalent = changes.length === 0;\n } else {\n // New spec - mark as added\n changes = [\n {\n path: '',\n type: 'added',\n newValue: incoming.spec,\n description: 'New spec imported from OpenAPI',\n },\n ];\n }\n\n return {\n operationId,\n existing,\n incoming,\n changes,\n isEquivalent,\n };\n}\n\n/**\n * Batch diff multiple specs against OpenAPI operations.\n */\nexport function diffAll(\n existingSpecs: Map<string, AnyContractSpec>,\n importedSpecs: ImportedSpec[],\n options: DiffOptions = {}\n): SpecDiff[] {\n const diffs: SpecDiff[] = [];\n\n // Track which existing specs have been matched\n const matchedExisting = new Set<string>();\n\n for (const imported of importedSpecs) {\n const operationId = imported.source.sourceId;\n\n // Try to find matching existing spec\n // Match by operationId in x-contractspec extension or by name\n let existing: AnyContractSpec | undefined;\n\n for (const [key, spec] of existingSpecs) {\n // Check x-contractspec match or name match\n const specName = spec.meta.name;\n if (key === operationId || specName.includes(operationId)) {\n existing = spec;\n matchedExisting.add(key);\n break;\n }\n }\n\n diffs.push(createSpecDiff(operationId, existing, imported, options));\n }\n\n // Add diffs for existing specs that weren't matched (removed from OpenAPI)\n for (const [key, spec] of existingSpecs) {\n if (!matchedExisting.has(key)) {\n diffs.push({\n operationId: key,\n existing: spec,\n incoming: undefined as unknown as ImportedSpec,\n changes: [\n {\n path: '',\n type: 'removed',\n oldValue: spec,\n description: 'Spec no longer exists in OpenAPI source',\n },\n ],\n isEquivalent: false,\n });\n }\n }\n\n return diffs;\n}\n\n/**\n * Format diff changes for display.\n */\nexport function formatDiffChanges(changes: DiffChange[]): string {\n if (changes.length === 0) {\n return 'No changes detected';\n }\n\n const lines: string[] = [];\n\n for (const change of changes) {\n const prefix = {\n added: '+',\n removed: '-',\n modified: '~',\n type_changed: '!',\n required_changed: '?',\n }[change.type];\n\n lines.push(`${prefix} ${change.path}: ${change.description}`);\n\n if (change.type === 'modified' || change.type === 'type_changed') {\n lines.push(` old: ${JSON.stringify(change.oldValue)}`);\n lines.push(` new: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'added') {\n lines.push(` value: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'removed') {\n lines.push(` was: ${JSON.stringify(change.oldValue)}`);\n }\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"differ.js","names":["changeType: DiffChangeType","changes: DiffChange[]","diffs: SpecDiff[]","existing: AnyOperationSpec | undefined","lines: string[]"],"sources":["../../src/openapi/differ.ts"],"sourcesContent":["/**\n * Diff ContractSpec specs against OpenAPI operations.\n * Used for sync operations to detect changes.\n */\n\nimport type { AnyOperationSpec } from '@lssm/lib.contracts';\nimport type { ParsedOperation } from './types';\nimport type {\n DiffChange,\n DiffChangeType,\n ImportedOperationSpec,\n SpecDiff,\n} from '../common/types';\nimport { deepEqual } from '../common/utils';\n\n/**\n * Options for diffing specs.\n */\nexport interface DiffOptions {\n /** Ignore description changes */\n ignoreDescriptions?: boolean;\n /** Ignore tag changes */\n ignoreTags?: boolean;\n /** Ignore transport changes (path, method) */\n ignoreTransport?: boolean;\n /** Custom paths to ignore */\n ignorePaths?: string[];\n}\n\n/**\n * Compare two values and generate a diff change if different.\n */\nfunction compareValues(\n path: string,\n oldValue: unknown,\n newValue: unknown,\n description: string\n): DiffChange | null {\n if (deepEqual(oldValue, newValue)) {\n return null;\n }\n\n let changeType: DiffChangeType = 'modified';\n if (oldValue === undefined || oldValue === null) {\n changeType = 'added';\n } else if (newValue === undefined || newValue === null) {\n changeType = 'removed';\n } else if (typeof oldValue !== typeof newValue) {\n changeType = 'type_changed';\n }\n\n return {\n path,\n type: changeType,\n oldValue,\n newValue,\n description,\n };\n}\n\n/**\n * Diff two objects recursively.\n */\nfunction diffObjects(\n path: string,\n oldObj: Record<string, unknown> | undefined,\n newObj: Record<string, unknown> | undefined,\n options: DiffOptions\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n if (!oldObj && !newObj) return changes;\n if (!oldObj) {\n changes.push({\n path,\n type: 'added',\n newValue: newObj,\n description: `Added ${path}`,\n });\n return changes;\n }\n if (!newObj) {\n changes.push({\n path,\n type: 'removed',\n oldValue: oldObj,\n description: `Removed ${path}`,\n });\n return changes;\n }\n\n const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n\n // Skip ignored paths\n if (options.ignorePaths?.some((p) => keyPath.startsWith(p))) {\n continue;\n }\n\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (typeof oldVal === 'object' && typeof newVal === 'object') {\n changes.push(\n ...diffObjects(\n keyPath,\n oldVal as Record<string, unknown>,\n newVal as Record<string, unknown>,\n options\n )\n );\n } else {\n const change = compareValues(\n keyPath,\n oldVal,\n newVal,\n `Changed ${keyPath}`\n );\n if (change) {\n changes.push(change);\n }\n }\n }\n\n return changes;\n}\n\n/**\n * Diff a ContractSpec against an OpenAPI operation.\n */\nexport function diffSpecVsOperation(\n spec: AnyOperationSpec,\n operation: ParsedOperation,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare basic metadata\n if (!options.ignoreDescriptions) {\n const descChange = compareValues(\n 'meta.description',\n spec.meta.description,\n operation.summary ?? operation.description,\n 'Description changed'\n );\n if (descChange) changes.push(descChange);\n }\n\n if (!options.ignoreTags) {\n const oldTags = [...(spec.meta.tags ?? [])].sort();\n const newTags = [...operation.tags].sort();\n if (!deepEqual(oldTags, newTags)) {\n changes.push({\n path: 'meta.tags',\n type: 'modified',\n oldValue: oldTags,\n newValue: newTags,\n description: 'Tags changed',\n });\n }\n }\n\n // Compare transport\n if (!options.ignoreTransport) {\n const specMethod =\n spec.transport?.rest?.method ??\n (spec.meta.kind === 'query' ? 'GET' : 'POST');\n const opMethod = operation.method.toUpperCase();\n\n if (specMethod !== opMethod) {\n changes.push({\n path: 'transport.rest.method',\n type: 'modified',\n oldValue: specMethod,\n newValue: opMethod,\n description: 'HTTP method changed',\n });\n }\n\n const specPath = spec.transport?.rest?.path;\n if (specPath && specPath !== operation.path) {\n changes.push({\n path: 'transport.rest.path',\n type: 'modified',\n oldValue: specPath,\n newValue: operation.path,\n description: 'Path changed',\n });\n }\n }\n\n // Compare deprecation status\n const specDeprecated = spec.meta.stability === 'deprecated';\n if (specDeprecated !== operation.deprecated) {\n changes.push({\n path: 'meta.stability',\n type: 'modified',\n oldValue: spec.meta.stability,\n newValue: operation.deprecated ? 'deprecated' : 'stable',\n description: 'Deprecation status changed',\n });\n }\n\n return changes;\n}\n\n/**\n * Diff two ContractSpecs.\n */\nexport function diffSpecs(\n oldSpec: AnyOperationSpec,\n newSpec: AnyOperationSpec,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare meta\n const metaChanges = diffObjects(\n 'meta',\n oldSpec.meta as unknown as Record<string, unknown>,\n newSpec.meta as unknown as Record<string, unknown>,\n {\n ...options,\n ignorePaths: [\n ...(options.ignorePaths ?? []),\n ...(options.ignoreDescriptions\n ? ['meta.description', 'meta.goal', 'meta.context']\n : []),\n ...(options.ignoreTags ? ['meta.tags'] : []),\n ],\n }\n );\n changes.push(...metaChanges);\n\n // Compare transport\n if (!options.ignoreTransport) {\n const transportChanges = diffObjects(\n 'transport',\n oldSpec.transport as unknown as Record<string, unknown>,\n newSpec.transport as unknown as Record<string, unknown>,\n options\n );\n changes.push(...transportChanges);\n }\n\n // Compare policy\n const policyChanges = diffObjects(\n 'policy',\n oldSpec.policy as unknown as Record<string, unknown>,\n newSpec.policy as unknown as Record<string, unknown>,\n options\n );\n changes.push(...policyChanges);\n\n return changes;\n}\n\n/**\n * Create a SpecDiff from an existing spec and an imported spec.\n */\nexport function createSpecDiff(\n operationId: string,\n existing: AnyOperationSpec | undefined,\n incoming: ImportedOperationSpec,\n options: DiffOptions = {}\n): SpecDiff {\n let changes: DiffChange[] = [];\n let isEquivalent = false;\n\n if (existing && incoming.operationSpec) {\n // Compare existing vs incoming\n changes = diffSpecs(existing, incoming.operationSpec, options);\n isEquivalent = changes.length === 0;\n } else if (existing && !incoming.operationSpec) {\n // Incoming has code but no runtime spec - can't compare directly\n changes = [\n {\n path: '',\n type: 'modified',\n oldValue: existing,\n newValue: incoming.code,\n description:\n 'Spec code imported from OpenAPI (runtime comparison not available)',\n },\n ];\n } else {\n // New spec - mark as added\n changes = [\n {\n path: '',\n type: 'added',\n newValue: incoming.operationSpec ?? incoming.code,\n description: 'New spec imported from OpenAPI',\n },\n ];\n }\n\n return {\n operationId,\n existing,\n incoming,\n changes,\n isEquivalent,\n };\n}\n\n/**\n * Batch diff multiple specs against OpenAPI operations.\n */\nexport function diffAll(\n existingSpecs: Map<string, AnyOperationSpec>,\n importedSpecs: ImportedOperationSpec[],\n options: DiffOptions = {}\n): SpecDiff[] {\n const diffs: SpecDiff[] = [];\n\n // Track which existing specs have been matched\n const matchedExisting = new Set<string>();\n\n for (const imported of importedSpecs) {\n const operationId = imported.source.sourceId;\n\n // Try to find matching existing spec\n // Match by operationId in x-contractspec extension or by name\n let existing: AnyOperationSpec | undefined;\n\n for (const [key, spec] of existingSpecs) {\n // Check x-contractspec match or name match\n const specName = spec.meta.name;\n if (key === operationId || specName.includes(operationId)) {\n existing = spec;\n matchedExisting.add(key);\n break;\n }\n }\n\n diffs.push(createSpecDiff(operationId, existing, imported, options));\n }\n\n // Add diffs for existing specs that weren't matched (removed from OpenAPI)\n for (const [key, spec] of existingSpecs) {\n if (!matchedExisting.has(key)) {\n diffs.push({\n operationId: key,\n existing: spec,\n incoming: undefined as unknown as ImportedOperationSpec,\n changes: [\n {\n path: '',\n type: 'removed',\n oldValue: spec,\n description: 'Spec no longer exists in OpenAPI source',\n },\n ],\n isEquivalent: false,\n });\n }\n }\n\n return diffs;\n}\n\n/**\n * Format diff changes for display.\n */\nexport function formatDiffChanges(changes: DiffChange[]): string {\n if (changes.length === 0) {\n return 'No changes detected';\n }\n\n const lines: string[] = [];\n\n for (const change of changes) {\n const prefix = {\n added: '+',\n removed: '-',\n modified: '~',\n type_changed: '!',\n required_changed: '?',\n }[change.type];\n\n lines.push(`${prefix} ${change.path}: ${change.description}`);\n\n if (change.type === 'modified' || change.type === 'type_changed') {\n lines.push(` old: ${JSON.stringify(change.oldValue)}`);\n lines.push(` new: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'added') {\n lines.push(` value: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'removed') {\n lines.push(` was: ${JSON.stringify(change.oldValue)}`);\n }\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { GeneratedRegistryCode } from "../types.js";
|
|
2
|
+
import { DataViewRegistry } from "@lssm/lib.contracts";
|
|
3
|
+
|
|
4
|
+
//#region src/openapi/exporter/data-views.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Exported data view structure for OpenAPI extensions.
|
|
8
|
+
*/
|
|
9
|
+
interface ExportedDataView {
|
|
10
|
+
name: string;
|
|
11
|
+
version: number;
|
|
12
|
+
description?: string;
|
|
13
|
+
stability?: string;
|
|
14
|
+
entity: string;
|
|
15
|
+
kind: 'list' | 'detail' | 'table' | 'grid';
|
|
16
|
+
source: {
|
|
17
|
+
primary: {
|
|
18
|
+
name: string;
|
|
19
|
+
version: number;
|
|
20
|
+
};
|
|
21
|
+
item?: {
|
|
22
|
+
name: string;
|
|
23
|
+
version: number;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
fields: unknown[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Export data views to OpenAPI extension format.
|
|
30
|
+
*/
|
|
31
|
+
declare function exportDataViews(registry: DataViewRegistry): ExportedDataView[];
|
|
32
|
+
/**
|
|
33
|
+
* Generate TypeScript code for data views registry.
|
|
34
|
+
*/
|
|
35
|
+
declare function generateDataViewsRegistry(registry: DataViewRegistry): GeneratedRegistryCode;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { ExportedDataView, exportDataViews, generateDataViewsRegistry };
|
|
38
|
+
//# sourceMappingURL=data-views.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-views.d.ts","names":[],"sources":["../../../src/openapi/exporter/data-views.ts"],"sourcesContent":[],"mappings":";;;;;AA0BA;AAkBA;;UAnCiB,gBAAA;;;;;;;;;;;;;;;;;;;;;;iBAiBD,eAAA,WACJ,mBACT;;;;iBAgBa,yBAAA,WACJ,mBACT"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/openapi/exporter/data-views.ts
|
|
2
|
+
/**
|
|
3
|
+
* Export data views to OpenAPI extension format.
|
|
4
|
+
*/
|
|
5
|
+
function exportDataViews(registry) {
|
|
6
|
+
return registry.list().map((dv) => ({
|
|
7
|
+
name: dv.meta.name,
|
|
8
|
+
version: dv.meta.version,
|
|
9
|
+
description: dv.meta.description,
|
|
10
|
+
stability: dv.meta.stability,
|
|
11
|
+
entity: dv.meta.entity,
|
|
12
|
+
kind: dv.view.kind,
|
|
13
|
+
source: dv.source,
|
|
14
|
+
fields: dv.view.fields
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate TypeScript code for data views registry.
|
|
19
|
+
*/
|
|
20
|
+
function generateDataViewsRegistry(registry) {
|
|
21
|
+
const dataViews = registry.list();
|
|
22
|
+
const imports = /* @__PURE__ */ new Set();
|
|
23
|
+
const registrations = [];
|
|
24
|
+
for (const dv of dataViews) {
|
|
25
|
+
const dvVarName = dv.meta.name.replace(/\./g, "_") + `_v${dv.meta.version}`;
|
|
26
|
+
imports.add(`import { ${dvVarName} } from './${dv.meta.name.split(".")[0]}';`);
|
|
27
|
+
registrations.push(` .register(${dvVarName})`);
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
code: `/**
|
|
31
|
+
* Auto-generated data views registry.
|
|
32
|
+
* DO NOT EDIT - This file is generated by ContractSpec exporter.
|
|
33
|
+
*/
|
|
34
|
+
import { DataViewRegistry } from '@lssm/lib.contracts';
|
|
35
|
+
|
|
36
|
+
${Array.from(imports).join("\n")}
|
|
37
|
+
|
|
38
|
+
export const dataViewsRegistry = new DataViewRegistry()
|
|
39
|
+
${registrations.join("\n")};
|
|
40
|
+
`,
|
|
41
|
+
fileName: "dataviews-registry.ts"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { exportDataViews, generateDataViewsRegistry };
|
|
47
|
+
//# sourceMappingURL=data-views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-views.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/data-views.ts"],"sourcesContent":["/**\n * Data views exporter - exports DataViewSpec to OpenAPI extensions.\n */\nimport type { DataViewRegistry, DataViewSpec } from '@lssm/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported data view structure for OpenAPI extensions.\n */\nexport interface ExportedDataView {\n name: string;\n version: number;\n description?: string;\n stability?: string;\n entity: string;\n kind: 'list' | 'detail' | 'table' | 'grid';\n source: {\n primary: { name: string; version: number };\n item?: { name: string; version: number };\n };\n fields: unknown[];\n}\n\n/**\n * Export data views to OpenAPI extension format.\n */\nexport function exportDataViews(\n registry: DataViewRegistry\n): ExportedDataView[] {\n return registry.list().map((dv) => ({\n name: dv.meta.name,\n version: dv.meta.version,\n description: dv.meta.description,\n stability: dv.meta.stability,\n entity: dv.meta.entity,\n kind: dv.view.kind,\n source: dv.source,\n fields: dv.view.fields,\n }));\n}\n\n/**\n * Generate TypeScript code for data views registry.\n */\nexport function generateDataViewsRegistry(\n registry: DataViewRegistry\n): GeneratedRegistryCode {\n const dataViews = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const dv of dataViews) {\n const dvVarName = dv.meta.name.replace(/\\./g, '_') + `_v${dv.meta.version}`;\n imports.add(\n `import { ${dvVarName} } from './${dv.meta.name.split('.')[0]}';`\n );\n registrations.push(` .register(${dvVarName})`);\n }\n\n const code = `/**\n * Auto-generated data views registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { DataViewRegistry } from '@lssm/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const dataViewsRegistry = new DataViewRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'dataviews-registry.ts',\n };\n}\n"],"mappings":";;;;AA0BA,SAAgB,gBACd,UACoB;AACpB,QAAO,SAAS,MAAM,CAAC,KAAK,QAAQ;EAClC,MAAM,GAAG,KAAK;EACd,SAAS,GAAG,KAAK;EACjB,aAAa,GAAG,KAAK;EACrB,WAAW,GAAG,KAAK;EACnB,QAAQ,GAAG,KAAK;EAChB,MAAM,GAAG,KAAK;EACd,QAAQ,GAAG;EACX,QAAQ,GAAG,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,0BACd,UACuB;CACvB,MAAM,YAAY,SAAS,MAAM;CACjC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,KAAK,KAAK,QAAQ,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK;AAClE,UAAQ,IACN,YAAY,UAAU,aAAa,GAAG,KAAK,KAAK,MAAM,IAAI,CAAC,GAAG,IAC/D;AACD,gBAAc,KAAK,eAAe,UAAU,GAAG;;AAejD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { GeneratedRegistryCode } from "../types.js";
|
|
2
|
+
import { EventSpec } from "@lssm/lib.contracts";
|
|
3
|
+
import { AnySchemaModel } from "@lssm/lib.schema";
|
|
4
|
+
|
|
5
|
+
//#region src/openapi/exporter/events.d.ts
|
|
6
|
+
|
|
7
|
+
type OpenApiSchemaObject = Record<string, unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* Exported event structure for OpenAPI extensions.
|
|
10
|
+
*/
|
|
11
|
+
interface ExportedEvent {
|
|
12
|
+
name: string;
|
|
13
|
+
version: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
payload: OpenApiSchemaObject | null;
|
|
16
|
+
pii?: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Export events to OpenAPI extension format.
|
|
20
|
+
*/
|
|
21
|
+
declare function exportEvents(events: EventSpec<AnySchemaModel>[]): ExportedEvent[];
|
|
22
|
+
/**
|
|
23
|
+
* Generate TypeScript code for events exports.
|
|
24
|
+
*/
|
|
25
|
+
declare function generateEventsExports(events: EventSpec<AnySchemaModel>[]): GeneratedRegistryCode;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { ExportedEvent, exportEvents, generateEventsExports };
|
|
28
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","names":[],"sources":["../../../src/openapi/exporter/events.ts"],"sourcesContent":[],"mappings":";;;;;;AAaA,KALK,mBAAA,GAAsB,MAShB,CAAA,MAAA,EAAA,OAAA,CAAA;AAOX;;;AAEG,UAbc,aAAA,CAad;EAAa,IAAA,EAAA,MAAA;EAeA,OAAA,EAAA,MAAA;EACI,WAAA,CAAA,EAAA,MAAA;EAAV,OAAA,EAzBC,mBAyBD,GAAA,IAAA;EACP,GAAA,CAAA,EAAA,MAAA,EAAA;;;;;iBAnBa,YAAA,SACN,UAAU,oBACjB;;;;iBAea,qBAAA,SACN,UAAU,oBACjB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/openapi/exporter/events.ts
|
|
4
|
+
/**
|
|
5
|
+
* Export events to OpenAPI extension format.
|
|
6
|
+
*/
|
|
7
|
+
function exportEvents(events) {
|
|
8
|
+
return events.map((event) => ({
|
|
9
|
+
name: event.name,
|
|
10
|
+
version: event.version,
|
|
11
|
+
description: event.description,
|
|
12
|
+
payload: event.payload ? z.toJSONSchema(event.payload.getZod()) : null,
|
|
13
|
+
pii: event.pii
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate TypeScript code for events exports.
|
|
18
|
+
*/
|
|
19
|
+
function generateEventsExports(events) {
|
|
20
|
+
const eventExports = [];
|
|
21
|
+
for (const event of events) {
|
|
22
|
+
const eventVarName = event.name.replace(/\./g, "_") + `_v${event.version}`;
|
|
23
|
+
eventExports.push(`export { ${eventVarName} } from './${event.name.split(".")[0]}';`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
code: `/**
|
|
27
|
+
* Auto-generated events exports.
|
|
28
|
+
* DO NOT EDIT - This file is generated by ContractSpec exporter.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
${eventExports.join("\n")}
|
|
32
|
+
`,
|
|
33
|
+
fileName: "events-exports.ts"
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
export { exportEvents, generateEventsExports };
|
|
39
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","names":["eventExports: string[]"],"sources":["../../../src/openapi/exporter/events.ts"],"sourcesContent":["/**\n * Events exporter - exports EventSpec to OpenAPI extensions.\n */\nimport type { EventSpec } from '@lssm/lib.contracts';\nimport type { AnySchemaModel } from '@lssm/lib.schema';\nimport { z } from 'zod';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Exported event structure for OpenAPI extensions.\n */\nexport interface ExportedEvent {\n name: string;\n version: number;\n description?: string;\n payload: OpenApiSchemaObject | null;\n pii?: string[];\n}\n\n/**\n * Export events to OpenAPI extension format.\n */\nexport function exportEvents(\n events: EventSpec<AnySchemaModel>[]\n): ExportedEvent[] {\n return events.map((event) => ({\n name: event.name,\n version: event.version,\n description: event.description,\n payload: event.payload\n ? (z.toJSONSchema(event.payload.getZod()) as OpenApiSchemaObject)\n : null,\n pii: event.pii,\n }));\n}\n\n/**\n * Generate TypeScript code for events exports.\n */\nexport function generateEventsExports(\n events: EventSpec<AnySchemaModel>[]\n): GeneratedRegistryCode {\n const eventExports: string[] = [];\n\n for (const event of events) {\n const eventVarName = event.name.replace(/\\./g, '_') + `_v${event.version}`;\n eventExports.push(`export { ${eventVarName} } from './${event.name.split('.')[0]}';`);\n }\n\n const code = `/**\n * Auto-generated events exports.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\n\n${eventExports.join('\\n')}\n`;\n\n return {\n code,\n fileName: 'events-exports.ts',\n };\n}\n"],"mappings":";;;;;;AAwBA,SAAgB,aACd,QACiB;AACjB,QAAO,OAAO,KAAK,WAAW;EAC5B,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,aAAa,MAAM;EACnB,SAAS,MAAM,UACV,EAAE,aAAa,MAAM,QAAQ,QAAQ,CAAC,GACvC;EACJ,KAAK,MAAM;EACZ,EAAE;;;;;AAML,SAAgB,sBACd,QACuB;CACvB,MAAMA,eAAyB,EAAE;AAEjC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,eAAe,MAAM,KAAK,QAAQ,OAAO,IAAI,GAAG,KAAK,MAAM;AACjE,eAAa,KAAK,YAAY,aAAa,aAAa,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG,IAAI;;AAWvF,QAAO;EACL,MATW;;;;;EAKb,aAAa,KAAK,KAAK,CAAC;;EAKtB,UAAU;EACX"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { GeneratedRegistryCode } from "../types.js";
|
|
2
|
+
import { FeatureRegistry } from "@lssm/lib.contracts";
|
|
3
|
+
|
|
4
|
+
//#region src/openapi/exporter/features.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Exported feature structure for OpenAPI extensions.
|
|
8
|
+
*/
|
|
9
|
+
interface ExportedFeature {
|
|
10
|
+
key: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
owners?: string[];
|
|
13
|
+
stability?: string;
|
|
14
|
+
operations?: {
|
|
15
|
+
name: string;
|
|
16
|
+
version: number;
|
|
17
|
+
}[];
|
|
18
|
+
events?: {
|
|
19
|
+
name: string;
|
|
20
|
+
version: number;
|
|
21
|
+
}[];
|
|
22
|
+
presentations?: {
|
|
23
|
+
name: string;
|
|
24
|
+
version: number;
|
|
25
|
+
}[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Export features to OpenAPI extension format.
|
|
29
|
+
*/
|
|
30
|
+
declare function exportFeatures(registry: FeatureRegistry): ExportedFeature[];
|
|
31
|
+
/**
|
|
32
|
+
* Generate TypeScript code for features registry.
|
|
33
|
+
*/
|
|
34
|
+
declare function generateFeaturesRegistry(registry: FeatureRegistry): GeneratedRegistryCode;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { ExportedFeature, exportFeatures, generateFeaturesRegistry };
|
|
37
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","names":[],"sources":["../../../src/openapi/exporter/features.ts"],"sourcesContent":[],"mappings":";;;;;AAsBA;AAeA;;UA5BiB,eAAA;;;;;;;;;;;;;;;;;;;;;iBAaD,cAAA,WAAyB,kBAAkB;;;;iBAe3C,wBAAA,WACJ,kBACT"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/openapi/exporter/features.ts
|
|
2
|
+
/**
|
|
3
|
+
* Export features to OpenAPI extension format.
|
|
4
|
+
*/
|
|
5
|
+
function exportFeatures(registry) {
|
|
6
|
+
return registry.list().map((feature) => ({
|
|
7
|
+
key: feature.meta.key,
|
|
8
|
+
description: feature.meta.description,
|
|
9
|
+
owners: feature.meta.owners,
|
|
10
|
+
stability: feature.meta.stability,
|
|
11
|
+
operations: feature.operations,
|
|
12
|
+
events: feature.events,
|
|
13
|
+
presentations: feature.presentations
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate TypeScript code for features registry.
|
|
18
|
+
*/
|
|
19
|
+
function generateFeaturesRegistry(registry) {
|
|
20
|
+
const features = registry.list();
|
|
21
|
+
const imports = /* @__PURE__ */ new Set();
|
|
22
|
+
const registrations = [];
|
|
23
|
+
for (const feature of features) {
|
|
24
|
+
const featureVarName = feature.meta.key.replace(/-/g, "_");
|
|
25
|
+
imports.add(`import { ${featureVarName} } from './${feature.meta.key}';`);
|
|
26
|
+
registrations.push(` .register(${featureVarName})`);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
code: `/**
|
|
30
|
+
* Auto-generated features registry.
|
|
31
|
+
* DO NOT EDIT - This file is generated by ContractSpec exporter.
|
|
32
|
+
*/
|
|
33
|
+
import { FeatureRegistry } from '@lssm/lib.contracts';
|
|
34
|
+
|
|
35
|
+
${Array.from(imports).join("\n")}
|
|
36
|
+
|
|
37
|
+
export const featuresRegistry = new FeatureRegistry()
|
|
38
|
+
${registrations.join("\n")};
|
|
39
|
+
`,
|
|
40
|
+
fileName: "features-registry.ts"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { exportFeatures, generateFeaturesRegistry };
|
|
46
|
+
//# sourceMappingURL=features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/features.ts"],"sourcesContent":["/**\n * Features exporter - exports FeatureModuleSpec to OpenAPI extensions.\n */\nimport type { FeatureModuleSpec, FeatureRegistry } from '@lssm/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported feature structure for OpenAPI extensions.\n */\nexport interface ExportedFeature {\n key: string;\n description?: string;\n owners?: string[];\n stability?: string;\n operations?: { name: string; version: number }[];\n events?: { name: string; version: number }[];\n presentations?: { name: string; version: number }[];\n}\n\n/**\n * Export features to OpenAPI extension format.\n */\nexport function exportFeatures(registry: FeatureRegistry): ExportedFeature[] {\n return registry.list().map((feature) => ({\n key: feature.meta.key,\n description: feature.meta.description,\n owners: feature.meta.owners,\n stability: feature.meta.stability,\n operations: feature.operations,\n events: feature.events,\n presentations: feature.presentations,\n }));\n}\n\n/**\n * Generate TypeScript code for features registry.\n */\nexport function generateFeaturesRegistry(\n registry: FeatureRegistry\n): GeneratedRegistryCode {\n const features = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const feature of features) {\n const featureVarName = feature.meta.key.replace(/-/g, '_');\n imports.add(\n `import { ${featureVarName} } from './${feature.meta.key}';`\n );\n registrations.push(` .register(${featureVarName})`);\n }\n\n const code = `/**\n * Auto-generated features registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { FeatureRegistry } from '@lssm/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const featuresRegistry = new FeatureRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'features-registry.ts',\n };\n}\n"],"mappings":";;;;AAsBA,SAAgB,eAAe,UAA8C;AAC3E,QAAO,SAAS,MAAM,CAAC,KAAK,aAAa;EACvC,KAAK,QAAQ,KAAK;EAClB,aAAa,QAAQ,KAAK;EAC1B,QAAQ,QAAQ,KAAK;EACrB,WAAW,QAAQ,KAAK;EACxB,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EAChB,eAAe,QAAQ;EACxB,EAAE;;;;;AAML,SAAgB,yBACd,UACuB;CACvB,MAAM,WAAW,SAAS,MAAM;CAChC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,iBAAiB,QAAQ,KAAK,IAAI,QAAQ,MAAM,IAAI;AAC1D,UAAQ,IACN,YAAY,eAAe,aAAa,QAAQ,KAAK,IAAI,IAC1D;AACD,gBAAc,KAAK,eAAe,eAAe,GAAG;;AAetD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { GeneratedRegistryCode } from "../types.js";
|
|
2
|
+
import { FormRegistry } from "@lssm/lib.contracts";
|
|
3
|
+
|
|
4
|
+
//#region src/openapi/exporter/forms.d.ts
|
|
5
|
+
|
|
6
|
+
type OpenApiSchemaObject = Record<string, unknown>;
|
|
7
|
+
/**
|
|
8
|
+
* Exported form structure for OpenAPI extensions.
|
|
9
|
+
*/
|
|
10
|
+
interface ExportedForm {
|
|
11
|
+
key: string;
|
|
12
|
+
version: number;
|
|
13
|
+
description?: string;
|
|
14
|
+
stability?: string;
|
|
15
|
+
owners?: string[];
|
|
16
|
+
fields: unknown[];
|
|
17
|
+
model: OpenApiSchemaObject | null;
|
|
18
|
+
actions?: unknown[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Export forms to OpenAPI extension format.
|
|
22
|
+
*/
|
|
23
|
+
declare function exportForms(registry: FormRegistry): ExportedForm[];
|
|
24
|
+
/**
|
|
25
|
+
* Generate TypeScript code for forms registry.
|
|
26
|
+
*/
|
|
27
|
+
declare function generateFormsRegistry(registry: FormRegistry): GeneratedRegistryCode;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { ExportedForm, exportForms, generateFormsRegistry };
|
|
30
|
+
//# sourceMappingURL=forms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forms.d.ts","names":[],"sources":["../../../src/openapi/exporter/forms.ts"],"sourcesContent":[],"mappings":";;;;;AAaA,KALK,mBAAA,GAAsB,MAYlB,CAAA,MAAA,EAAA,OAAA,CAAA;AAOT;AAoBA;;UAlCiB,YAAA;;;;;;;SAOR;;;;;;iBAOO,WAAA,WAAsB,eAAe;;;;iBAoBrC,qBAAA,WACJ,eACT"}
|