@contractkit/openapi-to-ck 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$ci.log +7 -7
- package/.turbo/turbo-test$colon$ci.log +30 -26
- package/CHANGELOG.md +117 -0
- package/LICENSE +21 -0
- package/README.md +30 -8
- package/dist/ast-to-ck.d.ts +32 -16
- package/dist/ast-to-ck.d.ts.map +1 -1
- package/dist/{chunk-JPI3AQ7V.js → chunk-Z53MK4FM.js} +196 -390
- package/dist/chunk-Z53MK4FM.js.map +1 -0
- package/dist/convert.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/normalize.d.ts +6 -2
- package/dist/normalize.d.ts.map +1 -1
- package/dist/paths-to-ast.d.ts +2 -0
- package/dist/paths-to-ast.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +18 -3
- package/dist/plugin.js.map +1 -1
- package/dist/schema-to-ast.d.ts +13 -1
- package/dist/schema-to-ast.d.ts.map +1 -1
- package/dist/tag-splitter.d.ts.map +1 -1
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/ast-to-ck.ts +29 -453
- package/src/convert.ts +57 -3
- package/src/normalize.ts +87 -11
- package/src/paths-to-ast.ts +92 -11
- package/src/plugin.ts +17 -2
- package/src/schema-to-ast.ts +51 -7
- package/src/tag-splitter.ts +21 -16
- package/src/types.ts +28 -0
- package/tests/__snapshots__/kitchen-sink.ck +102 -0
- package/tests/ast-to-ck.test.ts +34 -17
- package/tests/component-refs.test.ts +114 -0
- package/tests/coverage.test.ts +246 -0
- package/tests/error-responses.test.ts +94 -0
- package/tests/fixtures/kitchen-sink-3.1.json +100 -0
- package/tests/helpers.ts +40 -0
- package/tests/kitchen-sink.test.ts +116 -0
- package/tests/schema-to-ast.test.ts +11 -2
- package/dist/chunk-JPI3AQ7V.js.map +0 -1
|
@@ -4,15 +4,65 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
4
4
|
// src/normalize.ts
|
|
5
5
|
function normalize(doc, warnings) {
|
|
6
6
|
const version = detectVersion(doc);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (version === "3.0") {
|
|
11
|
-
return normalizeOas30(doc, warnings);
|
|
12
|
-
}
|
|
13
|
-
return doc;
|
|
7
|
+
const normalized = version === "2.0" ? normalizeSwagger2(doc, warnings) : version === "3.0" ? normalizeOas30(doc, warnings) : doc;
|
|
8
|
+
dereferenceComponents(normalized, warnings);
|
|
9
|
+
return normalized;
|
|
14
10
|
}
|
|
15
11
|
__name(normalize, "normalize");
|
|
12
|
+
var DEREF_SECTIONS = [
|
|
13
|
+
"parameters",
|
|
14
|
+
"requestBodies",
|
|
15
|
+
"responses",
|
|
16
|
+
"headers"
|
|
17
|
+
];
|
|
18
|
+
var MAX_REF_DEPTH = 10;
|
|
19
|
+
function dereferenceComponents(doc, warnings) {
|
|
20
|
+
const components = doc.components;
|
|
21
|
+
const resolve = /* @__PURE__ */ __name((node, path, depth = 0) => {
|
|
22
|
+
if (!node || typeof node !== "object") return node;
|
|
23
|
+
if (Array.isArray(node)) return node.map((item) => resolve(item, path, depth));
|
|
24
|
+
const obj = node;
|
|
25
|
+
const ref = obj.$ref;
|
|
26
|
+
if (typeof ref === "string") {
|
|
27
|
+
const match = /^#\/components\/([^/]+)\/(.+)$/.exec(ref);
|
|
28
|
+
const section = match?.[1];
|
|
29
|
+
if (section && section !== "schemas" && DEREF_SECTIONS.includes(section)) {
|
|
30
|
+
if (depth >= MAX_REF_DEPTH) {
|
|
31
|
+
warnings.warn(path, `$ref chain too deep to resolve: ${ref}`);
|
|
32
|
+
return obj;
|
|
33
|
+
}
|
|
34
|
+
const target = components?.[section]?.[decodeRefToken(match[2])];
|
|
35
|
+
if (target === void 0) {
|
|
36
|
+
warnings.warn(path, `unresolved $ref '${ref}' \u2014 the component is not defined`);
|
|
37
|
+
return obj;
|
|
38
|
+
}
|
|
39
|
+
const siblings = {
|
|
40
|
+
...obj
|
|
41
|
+
};
|
|
42
|
+
delete siblings.$ref;
|
|
43
|
+
const resolved = resolve(target, path, depth + 1);
|
|
44
|
+
return {
|
|
45
|
+
...resolved,
|
|
46
|
+
...siblings
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return obj;
|
|
50
|
+
}
|
|
51
|
+
const out = {};
|
|
52
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
53
|
+
out[key] = key === "schema" || key === "schemas" ? value : resolve(value, `${path}/${key}`, depth);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}, "resolve");
|
|
57
|
+
for (const [path, pathItem] of Object.entries(doc.paths ?? {})) {
|
|
58
|
+
doc.paths[path] = resolve(pathItem, `#/paths/${path}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
__name(dereferenceComponents, "dereferenceComponents");
|
|
62
|
+
function decodeRefToken(token) {
|
|
63
|
+
return decodeURIComponent(token).replace(/~1/g, "/").replace(/~0/g, "~");
|
|
64
|
+
}
|
|
65
|
+
__name(decodeRefToken, "decodeRefToken");
|
|
16
66
|
function detectVersion(doc) {
|
|
17
67
|
if (typeof doc.swagger === "string" && doc.swagger.startsWith("2")) return "2.0";
|
|
18
68
|
if (typeof doc.openapi === "string") {
|
|
@@ -82,7 +132,8 @@ function normalizePathItem2(pathItem, globalConsumes, globalProduces, warnings)
|
|
|
82
132
|
"patch",
|
|
83
133
|
"delete",
|
|
84
134
|
"head",
|
|
85
|
-
"options"
|
|
135
|
+
"options",
|
|
136
|
+
"trace"
|
|
86
137
|
];
|
|
87
138
|
const normalized = {};
|
|
88
139
|
const pathParams = pathItem.parameters ?? [];
|
|
@@ -281,7 +332,8 @@ function normalizePathItemSchemas(pathItem) {
|
|
|
281
332
|
"patch",
|
|
282
333
|
"delete",
|
|
283
334
|
"head",
|
|
284
|
-
"options"
|
|
335
|
+
"options",
|
|
336
|
+
"trace"
|
|
285
337
|
];
|
|
286
338
|
for (const method of methods) {
|
|
287
339
|
const op = pathItem[method];
|
|
@@ -419,12 +471,17 @@ var LOC = {
|
|
|
419
471
|
};
|
|
420
472
|
var FORMAT_TO_SCALAR = {
|
|
421
473
|
email: "email",
|
|
474
|
+
"idn-email": "email",
|
|
422
475
|
uri: "url",
|
|
476
|
+
"uri-reference": "url",
|
|
477
|
+
iri: "url",
|
|
478
|
+
"iri-reference": "url",
|
|
423
479
|
url: "url",
|
|
424
480
|
uuid: "uuid",
|
|
425
481
|
date: "date",
|
|
426
482
|
"date-time": "datetime",
|
|
427
483
|
time: "time",
|
|
484
|
+
duration: "duration",
|
|
428
485
|
binary: "binary",
|
|
429
486
|
int64: "bigint"
|
|
430
487
|
};
|
|
@@ -472,6 +529,11 @@ function schemaToModel(name, schema, ctx) {
|
|
|
472
529
|
kind: "model",
|
|
473
530
|
name,
|
|
474
531
|
fields,
|
|
532
|
+
// `additionalProperties: true` says unknown keys are allowed, which is `mode(loose)`.
|
|
533
|
+
// `false` and absent both match `.ck`'s `strict` default, so neither needs a mode.
|
|
534
|
+
...schema.additionalProperties === true ? {
|
|
535
|
+
mode: "loose"
|
|
536
|
+
} : {},
|
|
475
537
|
description,
|
|
476
538
|
loc: LOC
|
|
477
539
|
};
|
|
@@ -488,10 +550,11 @@ function schemaToModel(name, schema, ctx) {
|
|
|
488
550
|
}
|
|
489
551
|
__name(schemaToModel, "schemaToModel");
|
|
490
552
|
function schemaToTypeNode(schema, ctx) {
|
|
553
|
+
warnUnrepresentableConstraints(schema, ctx);
|
|
491
554
|
if (schema.$ref) {
|
|
492
555
|
const refName = extractRefName(schema.$ref);
|
|
493
556
|
if (refName) {
|
|
494
|
-
if (ctx.circularRefs.has(refName)) {
|
|
557
|
+
if (ctx.insideModel && ctx.circularRefs.has(refName)) {
|
|
495
558
|
return {
|
|
496
559
|
kind: "lazy",
|
|
497
560
|
inner: {
|
|
@@ -623,7 +686,7 @@ function stringSchemaToType(schema) {
|
|
|
623
686
|
if (schema.minLength !== void 0) mods.min = schema.minLength;
|
|
624
687
|
if (schema.maxLength !== void 0) mods.max = schema.maxLength;
|
|
625
688
|
}
|
|
626
|
-
if (schema.pattern) mods.regex =
|
|
689
|
+
if (schema.pattern) mods.regex = schema.pattern;
|
|
627
690
|
if (schema.format && !FORMAT_TO_SCALAR[schema.format]) mods.format = schema.format;
|
|
628
691
|
return {
|
|
629
692
|
kind: "scalar",
|
|
@@ -793,12 +856,24 @@ function toDiscriminatedUnion(schemas, discriminator, ctx) {
|
|
|
793
856
|
};
|
|
794
857
|
}
|
|
795
858
|
__name(toDiscriminatedUnion, "toDiscriminatedUnion");
|
|
859
|
+
var UNREPRESENTABLE_KEYWORDS = [
|
|
860
|
+
"exclusiveMinimum",
|
|
861
|
+
"exclusiveMaximum",
|
|
862
|
+
"multipleOf",
|
|
863
|
+
"uniqueItems"
|
|
864
|
+
];
|
|
796
865
|
function warnUnsupported(schema, ctx) {
|
|
797
866
|
if (schema.xml) ctx.warnings.warn(ctx.path, "xml metadata is not supported, skipping");
|
|
798
867
|
if (schema.externalDocs) ctx.warnings.info(ctx.path, "externalDocs is not supported, skipping");
|
|
799
868
|
if (schema.not) ctx.warnings.warn(ctx.path, "not keyword is not supported, skipping");
|
|
800
869
|
}
|
|
801
870
|
__name(warnUnsupported, "warnUnsupported");
|
|
871
|
+
function warnUnrepresentableConstraints(schema, ctx) {
|
|
872
|
+
for (const keyword of UNREPRESENTABLE_KEYWORDS) {
|
|
873
|
+
if (schema[keyword] !== void 0) ctx.warnings.warn(ctx.path, `${keyword} has no .ck equivalent, dropping the constraint`);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
__name(warnUnrepresentableConstraints, "warnUnrepresentableConstraints");
|
|
802
877
|
function extractInlineModel(schema, suggestedName, ctx) {
|
|
803
878
|
if (schema.$ref) {
|
|
804
879
|
return {
|
|
@@ -806,7 +881,10 @@ function extractInlineModel(schema, suggestedName, ctx) {
|
|
|
806
881
|
};
|
|
807
882
|
}
|
|
808
883
|
if (schema.properties || schema.type === "object" && schema.additionalProperties === void 0) {
|
|
809
|
-
const fields = schemaPropertiesToFields(schema,
|
|
884
|
+
const fields = schemaPropertiesToFields(schema, {
|
|
885
|
+
...ctx,
|
|
886
|
+
insideModel: true
|
|
887
|
+
});
|
|
810
888
|
const model = {
|
|
811
889
|
kind: "model",
|
|
812
890
|
name: suggestedName,
|
|
@@ -829,10 +907,11 @@ function extractInlineModel(schema, suggestedName, ctx) {
|
|
|
829
907
|
__name(extractInlineModel, "extractInlineModel");
|
|
830
908
|
function sanitizeName(name, warnings) {
|
|
831
909
|
const cleaned = name.replace(/[^a-zA-Z0-9_$]/g, " ").split(/\s+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
832
|
-
|
|
833
|
-
|
|
910
|
+
const safe = /^[0-9]/.test(cleaned) ? `_${cleaned}` : cleaned;
|
|
911
|
+
if (safe !== name) {
|
|
912
|
+
warnings.info(`#/components/schemas/${name}`, `Schema name sanitized: "${name}" \u2192 "${safe}"`);
|
|
834
913
|
}
|
|
835
|
-
return
|
|
914
|
+
return safe || "UnnamedSchema";
|
|
836
915
|
}
|
|
837
916
|
__name(sanitizeName, "sanitizeName");
|
|
838
917
|
|
|
@@ -841,6 +920,11 @@ var LOC2 = {
|
|
|
841
920
|
file: "",
|
|
842
921
|
line: 0
|
|
843
922
|
};
|
|
923
|
+
var MIME_RE = /^[a-z0-9][a-z0-9.+_-]*\/[a-z0-9][a-z0-9.+_-]*$/i;
|
|
924
|
+
function toNameText(summary) {
|
|
925
|
+
return summary.replace(/[}#]/g, " ").replace(/\s+/g, " ").trim();
|
|
926
|
+
}
|
|
927
|
+
__name(toNameText, "toNameText");
|
|
844
928
|
var HTTP_METHODS = [
|
|
845
929
|
"get",
|
|
846
930
|
"post",
|
|
@@ -848,6 +932,11 @@ var HTTP_METHODS = [
|
|
|
848
932
|
"patch",
|
|
849
933
|
"delete"
|
|
850
934
|
];
|
|
935
|
+
var UNSUPPORTED_METHODS = [
|
|
936
|
+
"head",
|
|
937
|
+
"options",
|
|
938
|
+
"trace"
|
|
939
|
+
];
|
|
851
940
|
function pathsToRoutes(doc, ctx) {
|
|
852
941
|
const routes = [];
|
|
853
942
|
const routeTags = /* @__PURE__ */ new Map();
|
|
@@ -870,6 +959,11 @@ function pathItemToRoute(path, pathItem, ctx) {
|
|
|
870
959
|
const operations = [];
|
|
871
960
|
let primaryTag = "default";
|
|
872
961
|
const pathParams = (pathItem.parameters ?? []).filter((p) => p.in === "path");
|
|
962
|
+
for (const method of UNSUPPORTED_METHODS) {
|
|
963
|
+
if (pathItem[method]) {
|
|
964
|
+
ctx.warnings.warn(`#/paths/${encodePathSegment2(path)}/${method}`, `\`${method}\` operations have no .ck equivalent; dropped`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
873
967
|
for (const method of HTTP_METHODS) {
|
|
874
968
|
const op = pathItem[method];
|
|
875
969
|
if (!op) continue;
|
|
@@ -912,6 +1006,11 @@ function operationToNode(method, op, path, ctx) {
|
|
|
912
1006
|
if (op.operationId) {
|
|
913
1007
|
node.sdk = op.operationId;
|
|
914
1008
|
}
|
|
1009
|
+
if (op.summary) {
|
|
1010
|
+
const name = toNameText(op.summary);
|
|
1011
|
+
if (name) node.name = name;
|
|
1012
|
+
else ctx.warnings.warn(`${pathPrefix}/summary`, "summary has no content `.ck` can carry as a name; dropped");
|
|
1013
|
+
}
|
|
915
1014
|
if (op.description && ctx.includeComments) {
|
|
916
1015
|
node.description = op.description;
|
|
917
1016
|
}
|
|
@@ -923,10 +1022,16 @@ function operationToNode(method, op, path, ctx) {
|
|
|
923
1022
|
const queryParams = [];
|
|
924
1023
|
const headerParams = [];
|
|
925
1024
|
for (const param of op.parameters ?? []) {
|
|
1025
|
+
if (!param?.name) {
|
|
1026
|
+
ctx.warnings.warn(`${pathPrefix}/parameters`, "skipped a parameter with no name (an unresolved $ref?)");
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
926
1029
|
if (param.in === "query") {
|
|
927
1030
|
queryParams.push(parameterToNode(param, schemaCtx));
|
|
928
1031
|
} else if (param.in === "header") {
|
|
929
1032
|
headerParams.push(parameterToNode(param, schemaCtx));
|
|
1033
|
+
} else if (param.in === "cookie") {
|
|
1034
|
+
ctx.warnings.warn(`${pathPrefix}/parameters/${param.name}`, "cookie parameters have no `.ck` equivalent; dropped");
|
|
930
1035
|
}
|
|
931
1036
|
}
|
|
932
1037
|
if (queryParams.length > 0) {
|
|
@@ -946,13 +1051,17 @@ function operationToNode(method, op, path, ctx) {
|
|
|
946
1051
|
}
|
|
947
1052
|
const responses = op.responses ?? {};
|
|
948
1053
|
for (const [code, resp] of Object.entries(responses)) {
|
|
1054
|
+
if (!/^\d{3}$/.test(code)) {
|
|
1055
|
+
ctx.warnings.warn(`${pathPrefix}/responses/${code}`, `response key '${code}' is not a numeric status code; dropped`);
|
|
1056
|
+
continue;
|
|
1057
|
+
}
|
|
949
1058
|
const statusCode = parseInt(code, 10);
|
|
950
|
-
if (isNaN(statusCode)) continue;
|
|
951
1059
|
const respNode = responseToNode(statusCode, resp, op.operationId ?? `${method}${toPascalCase(path)}`, schemaCtx, ctx);
|
|
952
1060
|
node.responses.push(respNode);
|
|
953
1061
|
}
|
|
954
|
-
|
|
955
|
-
|
|
1062
|
+
const security = op.security ?? ctx.globalSecurity;
|
|
1063
|
+
if (security !== void 0) {
|
|
1064
|
+
node.security = convertSecurity(security);
|
|
956
1065
|
}
|
|
957
1066
|
return node;
|
|
958
1067
|
}
|
|
@@ -1011,14 +1120,13 @@ __name(parameterToNode, "parameterToNode");
|
|
|
1011
1120
|
function requestBodyToNode(reqBody, operationName, schemaCtx, ctx) {
|
|
1012
1121
|
const content = reqBody.content;
|
|
1013
1122
|
if (!content) return void 0;
|
|
1014
|
-
const supported = /* @__PURE__ */ new Set([
|
|
1015
|
-
"application/json",
|
|
1016
|
-
"application/x-www-form-urlencoded",
|
|
1017
|
-
"multipart/form-data"
|
|
1018
|
-
]);
|
|
1019
1123
|
const bodies = [];
|
|
1020
1124
|
for (const [contentType, mediaType] of Object.entries(content)) {
|
|
1021
|
-
if (!
|
|
1125
|
+
if (!MIME_RE.test(contentType)) {
|
|
1126
|
+
ctx.warnings.warn(`${schemaCtx.path}/requestBody/content`, `content type '${contentType}' is not a plain type/subtype; skipped`);
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
if (!mediaType?.schema) continue;
|
|
1022
1130
|
const { typeNode, model } = extractInlineModel(mediaType.schema, `${toPascalCase(operationName)}Request`, schemaCtx);
|
|
1023
1131
|
if (model) {
|
|
1024
1132
|
ctx.extractedModels.push(model);
|
|
@@ -1034,14 +1142,24 @@ function requestBodyToNode(reqBody, operationName, schemaCtx, ctx) {
|
|
|
1034
1142
|
};
|
|
1035
1143
|
}
|
|
1036
1144
|
__name(requestBodyToNode, "requestBodyToNode");
|
|
1145
|
+
function shouldDocument(statusCode, braced, resp, ctx) {
|
|
1146
|
+
if (!braced) return false;
|
|
1147
|
+
if (resp["x-contractkit-emit"] === "documented") return true;
|
|
1148
|
+
return statusCode >= 400 && ctx.errorResponses === "documented";
|
|
1149
|
+
}
|
|
1150
|
+
__name(shouldDocument, "shouldDocument");
|
|
1037
1151
|
function responseToNode(statusCode, resp, operationName, schemaCtx, ctx) {
|
|
1038
1152
|
const headers = convertResponseHeaders(resp.headers, schemaCtx);
|
|
1153
|
+
const documented = /* @__PURE__ */ __name((braced) => shouldDocument(statusCode, braced, resp, ctx) ? {
|
|
1154
|
+
emit: "documented"
|
|
1155
|
+
} : {}, "documented");
|
|
1039
1156
|
const empty = /* @__PURE__ */ __name(() => ({
|
|
1040
1157
|
statusCode,
|
|
1041
1158
|
bodies: [],
|
|
1042
1159
|
...headers ? {
|
|
1043
1160
|
headers,
|
|
1044
|
-
hasBlock: true
|
|
1161
|
+
hasBlock: true,
|
|
1162
|
+
...documented(true)
|
|
1045
1163
|
} : {}
|
|
1046
1164
|
}), "empty");
|
|
1047
1165
|
if (!resp.content) return empty();
|
|
@@ -1063,7 +1181,8 @@ function responseToNode(statusCode, resp, operationName, schemaCtx, ctx) {
|
|
|
1063
1181
|
hasBlock: true,
|
|
1064
1182
|
...headers ? {
|
|
1065
1183
|
headers
|
|
1066
|
-
} : {}
|
|
1184
|
+
} : {},
|
|
1185
|
+
...documented(true)
|
|
1067
1186
|
};
|
|
1068
1187
|
}
|
|
1069
1188
|
__name(responseToNode, "responseToNode");
|
|
@@ -1103,7 +1222,9 @@ function makeSchemaCtx(ctx, path) {
|
|
|
1103
1222
|
includeComments: ctx.includeComments,
|
|
1104
1223
|
namedSchemas: ctx.namedSchemas,
|
|
1105
1224
|
extractedModels: ctx.extractedModels,
|
|
1106
|
-
inlineCounter: 0
|
|
1225
|
+
inlineCounter: 0,
|
|
1226
|
+
// A response body, request body, param or header names an already-imported model.
|
|
1227
|
+
insideModel: false
|
|
1107
1228
|
};
|
|
1108
1229
|
}
|
|
1109
1230
|
__name(makeSchemaCtx, "makeSchemaCtx");
|
|
@@ -1224,20 +1345,16 @@ function collectRouteRefs(route, refs) {
|
|
|
1224
1345
|
}
|
|
1225
1346
|
__name(collectRouteRefs, "collectRouteRefs");
|
|
1226
1347
|
function collectParamSourceRefs(source, refs) {
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1239
|
-
if (source && typeof source === "object" && "kind" in source) {
|
|
1240
|
-
collectTypeRefs(source, refs);
|
|
1348
|
+
switch (source.kind) {
|
|
1349
|
+
case "ref":
|
|
1350
|
+
refs.add(source.name);
|
|
1351
|
+
return;
|
|
1352
|
+
case "params":
|
|
1353
|
+
for (const param of source.nodes) collectTypeRefs(param.type, refs);
|
|
1354
|
+
return;
|
|
1355
|
+
case "type":
|
|
1356
|
+
collectTypeRefs(source.node, refs);
|
|
1357
|
+
return;
|
|
1241
1358
|
}
|
|
1242
1359
|
}
|
|
1243
1360
|
__name(collectParamSourceRefs, "collectParamSourceRefs");
|
|
@@ -1284,347 +1401,12 @@ function sanitizeFilename(tag) {
|
|
|
1284
1401
|
__name(sanitizeFilename, "sanitizeFilename");
|
|
1285
1402
|
|
|
1286
1403
|
// src/ast-to-ck.ts
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
return text.replace(/\s+/g, " ").trim();
|
|
1291
|
-
}
|
|
1292
|
-
__name(singleLineComment, "singleLineComment");
|
|
1293
|
-
function quoteEnumValue(value) {
|
|
1294
|
-
if (IDENT_RE.test(value)) return value;
|
|
1295
|
-
if (!value.includes('"')) return `"${value}"`;
|
|
1296
|
-
if (!value.includes("'")) return `'${value}'`;
|
|
1297
|
-
return `"${value}"`;
|
|
1298
|
-
}
|
|
1299
|
-
__name(quoteEnumValue, "quoteEnumValue");
|
|
1300
|
-
function astToCk(root, options = {}) {
|
|
1301
|
-
const { includeComments = true } = options;
|
|
1302
|
-
const ctx = {
|
|
1303
|
-
includeComments
|
|
1304
|
-
};
|
|
1305
|
-
const parts = [];
|
|
1306
|
-
const optionsBlock = serializeOptions(root);
|
|
1307
|
-
if (optionsBlock) parts.push(optionsBlock);
|
|
1308
|
-
for (const model of root.models) {
|
|
1309
|
-
parts.push(serializeModel(model, ctx));
|
|
1310
|
-
}
|
|
1311
|
-
for (const route of root.routes) {
|
|
1312
|
-
parts.push(serializeRoute(route, ctx));
|
|
1313
|
-
}
|
|
1314
|
-
return parts.join("\n\n") + "\n";
|
|
1404
|
+
import { printCk, printType } from "@contractkit/core";
|
|
1405
|
+
function astToCk(root, _options = {}) {
|
|
1406
|
+
return printCk(root);
|
|
1315
1407
|
}
|
|
1316
1408
|
__name(astToCk, "astToCk");
|
|
1317
|
-
|
|
1318
|
-
const hasKeys = Object.keys(root.meta).length > 0;
|
|
1319
|
-
const hasServices = root.services && Object.keys(root.services).length > 0;
|
|
1320
|
-
const hasSecurity = root.security !== void 0;
|
|
1321
|
-
if (!hasKeys && !hasServices && !hasSecurity) return null;
|
|
1322
|
-
const lines = [
|
|
1323
|
-
"options {"
|
|
1324
|
-
];
|
|
1325
|
-
if (hasKeys) {
|
|
1326
|
-
lines.push(`${INDENT}keys: {`);
|
|
1327
|
-
for (const [key, value] of Object.entries(root.meta)) {
|
|
1328
|
-
lines.push(`${INDENT}${INDENT}${key}: ${value}`);
|
|
1329
|
-
}
|
|
1330
|
-
lines.push(`${INDENT}}`);
|
|
1331
|
-
}
|
|
1332
|
-
if (hasServices) {
|
|
1333
|
-
lines.push(`${INDENT}services: {`);
|
|
1334
|
-
for (const [name, path] of Object.entries(root.services)) {
|
|
1335
|
-
lines.push(`${INDENT}${INDENT}${name}: "${path}"`);
|
|
1336
|
-
}
|
|
1337
|
-
lines.push(`${INDENT}}`);
|
|
1338
|
-
}
|
|
1339
|
-
if (hasSecurity) {
|
|
1340
|
-
lines.push(`${INDENT}security: {`);
|
|
1341
|
-
if (root.security === "none") {
|
|
1342
|
-
lines.push(`${INDENT}${INDENT}none`);
|
|
1343
|
-
} else {
|
|
1344
|
-
const sec = root.security;
|
|
1345
|
-
if (sec.policy !== void 0) {
|
|
1346
|
-
const value = sec.policy === false ? "none" : sec.policy;
|
|
1347
|
-
lines.push(`${INDENT}${INDENT}policy: ${value}`);
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
lines.push(`${INDENT}}`);
|
|
1351
|
-
}
|
|
1352
|
-
lines.push("}");
|
|
1353
|
-
return lines.join("\n");
|
|
1354
|
-
}
|
|
1355
|
-
__name(serializeOptions, "serializeOptions");
|
|
1356
|
-
function serializeModel(model, ctx) {
|
|
1357
|
-
const parts = [];
|
|
1358
|
-
const prefixes = [];
|
|
1359
|
-
if (model.inputCase && model.inputCase !== "camel") {
|
|
1360
|
-
prefixes.push(`format(input=${model.inputCase})`);
|
|
1361
|
-
}
|
|
1362
|
-
if (model.mode && model.mode !== "strict") {
|
|
1363
|
-
prefixes.push(`mode(${model.mode})`);
|
|
1364
|
-
}
|
|
1365
|
-
if (model.deprecated) {
|
|
1366
|
-
prefixes.push("deprecated");
|
|
1367
|
-
}
|
|
1368
|
-
const prefix = prefixes.length > 0 ? prefixes.join(" ") + " " : "";
|
|
1369
|
-
const comment = ctx.includeComments && model.description ? ` # ${singleLineComment(model.description)}` : "";
|
|
1370
|
-
if (model.type) {
|
|
1371
|
-
parts.push(`contract ${prefix}${model.name}: ${serializeType(model.type)}${comment}`);
|
|
1372
|
-
return parts.join("");
|
|
1373
|
-
}
|
|
1374
|
-
if (model.bases && model.bases.length > 0) {
|
|
1375
|
-
parts.push(`contract ${prefix}${model.name}: ${model.bases.join(" & ")} & {${comment}`);
|
|
1376
|
-
} else {
|
|
1377
|
-
parts.push(`contract ${prefix}${model.name}: {${comment}`);
|
|
1378
|
-
}
|
|
1379
|
-
for (const field of model.fields) {
|
|
1380
|
-
parts.push(serializeField(field, 1, ctx));
|
|
1381
|
-
}
|
|
1382
|
-
parts.push("}");
|
|
1383
|
-
return parts.join("\n");
|
|
1384
|
-
}
|
|
1385
|
-
__name(serializeModel, "serializeModel");
|
|
1386
|
-
function serializeField(field, depth, ctx) {
|
|
1387
|
-
const indent = INDENT.repeat(depth);
|
|
1388
|
-
const optional = field.optional ? "?" : "";
|
|
1389
|
-
const visibility = field.visibility !== "normal" ? `${field.visibility} ` : "";
|
|
1390
|
-
const deprecated = field.deprecated ? "deprecated " : "";
|
|
1391
|
-
let typeStr = serializeType(field.type);
|
|
1392
|
-
if (field.nullable && !typeContainsNull(field.type)) {
|
|
1393
|
-
typeStr = `${typeStr} | null`;
|
|
1394
|
-
}
|
|
1395
|
-
const defaultVal = field.default !== void 0 ? ` = ${serializeDefault(field.default)}` : "";
|
|
1396
|
-
const comment = ctx.includeComments && field.description ? ` # ${singleLineComment(field.description)}` : "";
|
|
1397
|
-
return `${indent}${field.name}${optional}: ${deprecated}${visibility}${typeStr}${defaultVal}${comment}`;
|
|
1398
|
-
}
|
|
1399
|
-
__name(serializeField, "serializeField");
|
|
1400
|
-
function typeContainsNull(type) {
|
|
1401
|
-
if (type.kind === "scalar" && type.name === "null") return true;
|
|
1402
|
-
if (type.kind === "union") return type.members.some(typeContainsNull);
|
|
1403
|
-
return false;
|
|
1404
|
-
}
|
|
1405
|
-
__name(typeContainsNull, "typeContainsNull");
|
|
1406
|
-
function serializeDefault(value) {
|
|
1407
|
-
if (typeof value === "string") {
|
|
1408
|
-
if (/^[a-zA-Z_$][a-zA-Z0-9_$\-.]*$/.test(value)) return value;
|
|
1409
|
-
return `"${value}"`;
|
|
1410
|
-
}
|
|
1411
|
-
return String(value);
|
|
1412
|
-
}
|
|
1413
|
-
__name(serializeDefault, "serializeDefault");
|
|
1414
|
-
function serializeType(type) {
|
|
1415
|
-
switch (type.kind) {
|
|
1416
|
-
case "scalar":
|
|
1417
|
-
return serializeScalar(type);
|
|
1418
|
-
case "array":
|
|
1419
|
-
return serializeArray(type);
|
|
1420
|
-
case "tuple":
|
|
1421
|
-
return `tuple(${type.items.map(serializeType).join(", ")})`;
|
|
1422
|
-
case "record":
|
|
1423
|
-
return `record(${serializeType(type.key)}, ${serializeType(type.value)})`;
|
|
1424
|
-
case "enum":
|
|
1425
|
-
return `enum(${type.values.map(quoteEnumValue).join(", ")})`;
|
|
1426
|
-
case "literal":
|
|
1427
|
-
return serializeLiteral(type);
|
|
1428
|
-
case "union":
|
|
1429
|
-
return type.members.map(serializeType).join(" | ");
|
|
1430
|
-
case "discriminatedUnion":
|
|
1431
|
-
return `discriminated(by=${type.discriminator}, ${type.members.map(serializeType).join(" | ")})`;
|
|
1432
|
-
case "intersection":
|
|
1433
|
-
return type.members.map(serializeType).join(" & ");
|
|
1434
|
-
case "ref":
|
|
1435
|
-
return type.name;
|
|
1436
|
-
case "inlineObject":
|
|
1437
|
-
return serializeInlineObject(type);
|
|
1438
|
-
case "lazy":
|
|
1439
|
-
return `lazy(${serializeType(type.inner)})`;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
__name(serializeType, "serializeType");
|
|
1443
|
-
function serializeScalar(type) {
|
|
1444
|
-
const args = [];
|
|
1445
|
-
if (type.len !== void 0) args.push(`length=${type.len}`);
|
|
1446
|
-
if (type.min !== void 0) args.push(typeof type.min === "string" ? `min="${type.min}"` : `min=${type.min}`);
|
|
1447
|
-
if (type.max !== void 0) args.push(typeof type.max === "string" ? `max="${type.max}"` : `max=${type.max}`);
|
|
1448
|
-
if (type.regex !== void 0) args.push(`regex=${type.regex}`);
|
|
1449
|
-
if (type.format !== void 0) args.push(`format=${type.format}`);
|
|
1450
|
-
if (args.length === 0) return type.name;
|
|
1451
|
-
return `${type.name}(${args.join(", ")})`;
|
|
1452
|
-
}
|
|
1453
|
-
__name(serializeScalar, "serializeScalar");
|
|
1454
|
-
function serializeArray(type) {
|
|
1455
|
-
const args = [
|
|
1456
|
-
serializeType(type.item)
|
|
1457
|
-
];
|
|
1458
|
-
if (type.min !== void 0) args.push(`min=${type.min}`);
|
|
1459
|
-
if (type.max !== void 0) args.push(`max=${type.max}`);
|
|
1460
|
-
return `array(${args.join(", ")})`;
|
|
1461
|
-
}
|
|
1462
|
-
__name(serializeArray, "serializeArray");
|
|
1463
|
-
function serializeLiteral(type) {
|
|
1464
|
-
if (typeof type.value === "string") return `literal("${type.value}")`;
|
|
1465
|
-
return `literal(${type.value})`;
|
|
1466
|
-
}
|
|
1467
|
-
__name(serializeLiteral, "serializeLiteral");
|
|
1468
|
-
function serializeInlineObject(type) {
|
|
1469
|
-
const modePrefix = type.mode ? `mode(${type.mode}) ` : "";
|
|
1470
|
-
if (type.fields.length === 0) return `${modePrefix}{}`;
|
|
1471
|
-
const lines = [
|
|
1472
|
-
`${modePrefix}{`
|
|
1473
|
-
];
|
|
1474
|
-
for (const field of type.fields) {
|
|
1475
|
-
lines.push(serializeField(field, 2, {
|
|
1476
|
-
includeComments: true
|
|
1477
|
-
}));
|
|
1478
|
-
}
|
|
1479
|
-
lines.push(`${INDENT}}`);
|
|
1480
|
-
return lines.join("\n");
|
|
1481
|
-
}
|
|
1482
|
-
__name(serializeInlineObject, "serializeInlineObject");
|
|
1483
|
-
function serializeRoute(route, ctx) {
|
|
1484
|
-
const lines = [];
|
|
1485
|
-
const modStr = serializeModifiers(route.modifiers);
|
|
1486
|
-
const comment = ctx.includeComments && route.description ? ` # ${singleLineComment(route.description)}` : "";
|
|
1487
|
-
lines.push(`operation${modStr} ${route.path}: {${comment}`);
|
|
1488
|
-
if (route.params) {
|
|
1489
|
-
serializeParamSource(lines, "params", route.params, route.paramsMode, 1, ctx);
|
|
1490
|
-
}
|
|
1491
|
-
if (route.security !== void 0) {
|
|
1492
|
-
serializeSecurityBlock(lines, route.security, 1, ctx);
|
|
1493
|
-
}
|
|
1494
|
-
for (const op of route.operations) {
|
|
1495
|
-
serializeOperation(lines, op, 1, ctx);
|
|
1496
|
-
}
|
|
1497
|
-
lines.push("}");
|
|
1498
|
-
return lines.join("\n");
|
|
1499
|
-
}
|
|
1500
|
-
__name(serializeRoute, "serializeRoute");
|
|
1501
|
-
function serializeOperation(lines, op, depth, ctx) {
|
|
1502
|
-
const indent = INDENT.repeat(depth);
|
|
1503
|
-
const modStr = serializeModifiers(op.modifiers);
|
|
1504
|
-
const comment = ctx.includeComments && op.description ? ` # ${singleLineComment(op.description)}` : "";
|
|
1505
|
-
lines.push(`${indent}${op.method}${modStr}: {${comment}`);
|
|
1506
|
-
const inner = INDENT.repeat(depth + 1);
|
|
1507
|
-
if (op.service) {
|
|
1508
|
-
lines.push(`${inner}service: ${op.service}`);
|
|
1509
|
-
}
|
|
1510
|
-
if (op.sdk) {
|
|
1511
|
-
lines.push(`${inner}sdk: ${op.sdk}`);
|
|
1512
|
-
}
|
|
1513
|
-
if (op.signature) {
|
|
1514
|
-
const sigComment = ctx.includeComments && op.signatureDescription ? ` # ${singleLineComment(op.signatureDescription)}` : "";
|
|
1515
|
-
if (op.signaturePolicy) {
|
|
1516
|
-
lines.push(`${inner}signature: {`);
|
|
1517
|
-
lines.push(`${inner} options: ${op.signature}${sigComment}`);
|
|
1518
|
-
lines.push(`${inner} policy: ${op.signaturePolicy}`);
|
|
1519
|
-
lines.push(`${inner}}`);
|
|
1520
|
-
} else {
|
|
1521
|
-
lines.push(`${inner}signature: ${op.signature}${sigComment}`);
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
if (op.security !== void 0) {
|
|
1525
|
-
serializeSecurityBlock(lines, op.security, depth + 1, ctx);
|
|
1526
|
-
}
|
|
1527
|
-
if (op.query) {
|
|
1528
|
-
serializeParamSource(lines, "query", op.query, op.queryMode, depth + 1, ctx);
|
|
1529
|
-
}
|
|
1530
|
-
if (op.headers) {
|
|
1531
|
-
serializeParamSource(lines, "headers", op.headers, op.headersMode, depth + 1, ctx);
|
|
1532
|
-
}
|
|
1533
|
-
if (op.request) {
|
|
1534
|
-
serializeRequest(lines, op.request, depth + 1);
|
|
1535
|
-
}
|
|
1536
|
-
if (op.responses.length > 0) {
|
|
1537
|
-
serializeResponses(lines, op.responses, depth + 1);
|
|
1538
|
-
}
|
|
1539
|
-
lines.push(`${indent}}`);
|
|
1540
|
-
return lines;
|
|
1541
|
-
}
|
|
1542
|
-
__name(serializeOperation, "serializeOperation");
|
|
1543
|
-
function serializeModifiers(modifiers) {
|
|
1544
|
-
if (!modifiers || modifiers.length === 0) return "";
|
|
1545
|
-
return `(${modifiers.join(", ")})`;
|
|
1546
|
-
}
|
|
1547
|
-
__name(serializeModifiers, "serializeModifiers");
|
|
1548
|
-
function serializeParamSource(lines, keyword, source, mode, depth, ctx) {
|
|
1549
|
-
const indent = INDENT.repeat(depth);
|
|
1550
|
-
if (source.kind === "ref") {
|
|
1551
|
-
lines.push(`${indent}${keyword}: ${source.name}`);
|
|
1552
|
-
return;
|
|
1553
|
-
}
|
|
1554
|
-
if (source.kind === "type") {
|
|
1555
|
-
lines.push(`${indent}${keyword}: ${serializeType(source.node)}`);
|
|
1556
|
-
return;
|
|
1557
|
-
}
|
|
1558
|
-
const modeStr = mode ? `mode(${mode}) ` : "";
|
|
1559
|
-
lines.push(`${indent}${keyword}: ${modeStr}{`);
|
|
1560
|
-
for (const param of source.nodes) {
|
|
1561
|
-
const optional = param.optional ? "?" : "";
|
|
1562
|
-
let typeStr = serializeType(param.type);
|
|
1563
|
-
if (param.nullable && !typeContainsNull(param.type)) {
|
|
1564
|
-
typeStr = `${typeStr} | null`;
|
|
1565
|
-
}
|
|
1566
|
-
const defaultVal = param.default !== void 0 ? ` = ${serializeDefault(param.default)}` : "";
|
|
1567
|
-
const comment = ctx.includeComments && param.description ? ` # ${singleLineComment(param.description)}` : "";
|
|
1568
|
-
lines.push(`${INDENT.repeat(depth + 1)}${param.name}${optional}: ${typeStr}${defaultVal}${comment}`);
|
|
1569
|
-
}
|
|
1570
|
-
lines.push(`${indent}}`);
|
|
1571
|
-
}
|
|
1572
|
-
__name(serializeParamSource, "serializeParamSource");
|
|
1573
|
-
function serializeRequest(lines, request, depth) {
|
|
1574
|
-
const indent = INDENT.repeat(depth);
|
|
1575
|
-
lines.push(`${indent}request: {`);
|
|
1576
|
-
for (const body of request.bodies) {
|
|
1577
|
-
lines.push(`${INDENT.repeat(depth + 1)}${body.contentType}: ${serializeType(body.bodyType)}`);
|
|
1578
|
-
}
|
|
1579
|
-
lines.push(`${indent}}`);
|
|
1580
|
-
}
|
|
1581
|
-
__name(serializeRequest, "serializeRequest");
|
|
1582
|
-
function serializeResponses(lines, responses, depth) {
|
|
1583
|
-
const indent = INDENT.repeat(depth);
|
|
1584
|
-
lines.push(`${indent}response: {`);
|
|
1585
|
-
for (const resp of responses) {
|
|
1586
|
-
const bodies = resp.bodies;
|
|
1587
|
-
const hasHeaders = resp.headers && resp.headers.length > 0;
|
|
1588
|
-
if (bodies.length > 0 || hasHeaders) {
|
|
1589
|
-
lines.push(`${INDENT.repeat(depth + 1)}${resp.statusCode}: {`);
|
|
1590
|
-
for (const body of bodies) {
|
|
1591
|
-
lines.push(`${INDENT.repeat(depth + 2)}${body.contentType}: ${serializeType(body.bodyType)}`);
|
|
1592
|
-
}
|
|
1593
|
-
if (hasHeaders) {
|
|
1594
|
-
lines.push(`${INDENT.repeat(depth + 2)}headers: {`);
|
|
1595
|
-
for (const h of resp.headers) {
|
|
1596
|
-
const opt = h.optional ? "?" : "";
|
|
1597
|
-
const trail = h.description ? ` # ${singleLineComment(h.description)}` : "";
|
|
1598
|
-
lines.push(`${INDENT.repeat(depth + 3)}${h.name}${opt}: ${serializeType(h.type)}${trail}`);
|
|
1599
|
-
}
|
|
1600
|
-
lines.push(`${INDENT.repeat(depth + 2)}}`);
|
|
1601
|
-
}
|
|
1602
|
-
lines.push(`${INDENT.repeat(depth + 1)}}`);
|
|
1603
|
-
} else {
|
|
1604
|
-
lines.push(`${INDENT.repeat(depth + 1)}${resp.statusCode}:`);
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
lines.push(`${indent}}`);
|
|
1608
|
-
}
|
|
1609
|
-
__name(serializeResponses, "serializeResponses");
|
|
1610
|
-
function serializeSecurityBlock(lines, security, depth, ctx) {
|
|
1611
|
-
const indent = INDENT.repeat(depth);
|
|
1612
|
-
if (security === "none") {
|
|
1613
|
-
lines.push(`${indent}security: none`);
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
const sec = security;
|
|
1617
|
-
if (sec.policy !== void 0) {
|
|
1618
|
-
const comment = ctx.includeComments && sec.policyDescription ? ` # ${singleLineComment(sec.policyDescription)}` : "";
|
|
1619
|
-
const value = sec.policy === false ? "none" : sec.policy;
|
|
1620
|
-
lines.push(`${indent}security: {`);
|
|
1621
|
-
lines.push(`${INDENT.repeat(depth + 1)}policy: ${value}${comment}`);
|
|
1622
|
-
lines.push(`${indent}}`);
|
|
1623
|
-
} else {
|
|
1624
|
-
lines.push(`${indent}security: {}`);
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
__name(serializeSecurityBlock, "serializeSecurityBlock");
|
|
1409
|
+
var serializeType = printType;
|
|
1628
1410
|
|
|
1629
1411
|
// src/convert.ts
|
|
1630
1412
|
import { readFileSync } from "fs";
|
|
@@ -1661,8 +1443,9 @@ var WarningCollector = class {
|
|
|
1661
1443
|
};
|
|
1662
1444
|
|
|
1663
1445
|
// src/convert.ts
|
|
1446
|
+
import { parseCk, decomposeCk, validateRefs, DiagnosticCollector } from "@contractkit/core";
|
|
1664
1447
|
async function convertOpenApiToCk(options) {
|
|
1665
|
-
const { split = "by-tag", includeComments = true } = options;
|
|
1448
|
+
const { split = "by-tag", includeComments = true, errorResponses = "documented" } = options;
|
|
1666
1449
|
const warnings = new WarningCollector(options.onWarning);
|
|
1667
1450
|
const rawDoc = await parseInput(options.input);
|
|
1668
1451
|
const doc = normalize(rawDoc, warnings);
|
|
@@ -1676,7 +1459,8 @@ async function convertOpenApiToCk(options) {
|
|
|
1676
1459
|
includeComments,
|
|
1677
1460
|
namedSchemas: schemas,
|
|
1678
1461
|
extractedModels,
|
|
1679
|
-
inlineCounter: 0
|
|
1462
|
+
inlineCounter: 0,
|
|
1463
|
+
insideModel: true
|
|
1680
1464
|
};
|
|
1681
1465
|
const models = schemasToModels(schemas, schemaCtx);
|
|
1682
1466
|
const { routes, routeTags } = pathsToRoutes(doc, {
|
|
@@ -1685,28 +1469,50 @@ async function convertOpenApiToCk(options) {
|
|
|
1685
1469
|
includeComments,
|
|
1686
1470
|
namedSchemas: schemas,
|
|
1687
1471
|
extractedModels,
|
|
1688
|
-
globalSecurity: doc.security
|
|
1472
|
+
globalSecurity: doc.security,
|
|
1473
|
+
errorResponses
|
|
1689
1474
|
});
|
|
1475
|
+
const known = new Set(models.map((m) => m.name));
|
|
1476
|
+
for (const extracted of extractedModels) {
|
|
1477
|
+
if (known.has(extracted.name)) continue;
|
|
1478
|
+
known.add(extracted.name);
|
|
1479
|
+
models.push(extracted);
|
|
1480
|
+
}
|
|
1690
1481
|
const files = /* @__PURE__ */ new Map();
|
|
1691
1482
|
if (split === "by-tag") {
|
|
1692
1483
|
const ckRoots = splitByTag(models, routes, routeTags);
|
|
1693
1484
|
for (const [filename, root] of ckRoots) {
|
|
1694
|
-
files.set(filename, astToCk(root
|
|
1695
|
-
includeComments
|
|
1696
|
-
}));
|
|
1485
|
+
files.set(filename, astToCk(root));
|
|
1697
1486
|
}
|
|
1698
1487
|
} else {
|
|
1699
1488
|
const root = mergeIntoSingle(models, routes);
|
|
1700
|
-
files.set("api.ck", astToCk(root
|
|
1701
|
-
includeComments
|
|
1702
|
-
}));
|
|
1489
|
+
files.set("api.ck", astToCk(root));
|
|
1703
1490
|
}
|
|
1491
|
+
checkGeneratedFiles(files, warnings);
|
|
1704
1492
|
return {
|
|
1705
1493
|
files,
|
|
1706
1494
|
warnings: warnings.warnings
|
|
1707
1495
|
};
|
|
1708
1496
|
}
|
|
1709
1497
|
__name(convertOpenApiToCk, "convertOpenApiToCk");
|
|
1498
|
+
function checkGeneratedFiles(files, warnings) {
|
|
1499
|
+
const diag = new DiagnosticCollector();
|
|
1500
|
+
const roots = [];
|
|
1501
|
+
for (const [filename, text] of files) {
|
|
1502
|
+
const before = diag.getAll().length;
|
|
1503
|
+
const root = parseCk(text, filename, diag);
|
|
1504
|
+
if (diag.getAll().length === before) roots.push(root);
|
|
1505
|
+
}
|
|
1506
|
+
if (roots.length === files.size) {
|
|
1507
|
+
const decomposed = roots.map(decomposeCk);
|
|
1508
|
+
validateRefs(decomposed.map((d) => d.contract), decomposed.map((d) => d.op), diag);
|
|
1509
|
+
}
|
|
1510
|
+
for (const d of diag.getAll()) {
|
|
1511
|
+
if (d.severity !== "error") continue;
|
|
1512
|
+
warnings.warn(d.file, `generated .ck is not valid (line ${d.line}): ${d.message}`);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
__name(checkGeneratedFiles, "checkGeneratedFiles");
|
|
1710
1516
|
async function parseInput(input) {
|
|
1711
1517
|
if (typeof input === "object") {
|
|
1712
1518
|
return input;
|
|
@@ -1784,4 +1590,4 @@ export {
|
|
|
1784
1590
|
serializeType,
|
|
1785
1591
|
convertOpenApiToCk
|
|
1786
1592
|
};
|
|
1787
|
-
//# sourceMappingURL=chunk-
|
|
1593
|
+
//# sourceMappingURL=chunk-Z53MK4FM.js.map
|