@f3liz/rescript-autogen-openapi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +98 -0
  3. package/lib/es6/src/Codegen.mjs +423 -0
  4. package/lib/es6/src/Types.mjs +20 -0
  5. package/lib/es6/src/core/CodegenUtils.mjs +186 -0
  6. package/lib/es6/src/core/DocOverride.mjs +399 -0
  7. package/lib/es6/src/core/FileSystem.mjs +78 -0
  8. package/lib/es6/src/core/IRBuilder.mjs +201 -0
  9. package/lib/es6/src/core/OpenAPIParser.mjs +168 -0
  10. package/lib/es6/src/core/Pipeline.mjs +150 -0
  11. package/lib/es6/src/core/ReferenceResolver.mjs +41 -0
  12. package/lib/es6/src/core/Result.mjs +378 -0
  13. package/lib/es6/src/core/SchemaIR.mjs +355 -0
  14. package/lib/es6/src/core/SchemaIRParser.mjs +490 -0
  15. package/lib/es6/src/core/SchemaRefResolver.mjs +146 -0
  16. package/lib/es6/src/core/SchemaRegistry.mjs +92 -0
  17. package/lib/es6/src/core/SpecDiffer.mjs +251 -0
  18. package/lib/es6/src/core/SpecMerger.mjs +237 -0
  19. package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +125 -0
  20. package/lib/es6/src/generators/DiffReportGenerator.mjs +155 -0
  21. package/lib/es6/src/generators/EndpointGenerator.mjs +172 -0
  22. package/lib/es6/src/generators/IRToSuryGenerator.mjs +233 -0
  23. package/lib/es6/src/generators/IRToTypeGenerator.mjs +241 -0
  24. package/lib/es6/src/generators/IRToTypeScriptGenerator.mjs +143 -0
  25. package/lib/es6/src/generators/ModuleGenerator.mjs +285 -0
  26. package/lib/es6/src/generators/SchemaCodeGenerator.mjs +77 -0
  27. package/lib/es6/src/generators/ThinWrapperGenerator.mjs +97 -0
  28. package/lib/es6/src/generators/TypeScriptDtsGenerator.mjs +172 -0
  29. package/lib/es6/src/generators/TypeScriptWrapperGenerator.mjs +145 -0
  30. package/lib/es6/src/types/CodegenError.mjs +79 -0
  31. package/lib/es6/src/types/Config.mjs +42 -0
  32. package/lib/es6/src/types/GenerationContext.mjs +24 -0
  33. package/package.json +44 -0
  34. package/rescript.json +20 -0
  35. package/src/Codegen.res +222 -0
  36. package/src/Types.res +195 -0
  37. package/src/core/CodegenUtils.res +130 -0
  38. package/src/core/DocOverride.res +504 -0
  39. package/src/core/FileSystem.res +62 -0
  40. package/src/core/IRBuilder.res +66 -0
  41. package/src/core/OpenAPIParser.res +144 -0
  42. package/src/core/Pipeline.res +51 -0
  43. package/src/core/ReferenceResolver.res +41 -0
  44. package/src/core/Result.res +187 -0
  45. package/src/core/SchemaIR.res +258 -0
  46. package/src/core/SchemaIRParser.res +360 -0
  47. package/src/core/SchemaRefResolver.res +143 -0
  48. package/src/core/SchemaRegistry.res +107 -0
  49. package/src/core/SpecDiffer.res +270 -0
  50. package/src/core/SpecMerger.res +245 -0
  51. package/src/generators/ComponentSchemaGenerator.res +127 -0
  52. package/src/generators/DiffReportGenerator.res +152 -0
  53. package/src/generators/EndpointGenerator.res +172 -0
  54. package/src/generators/IRToSuryGenerator.res +199 -0
  55. package/src/generators/IRToTypeGenerator.res +199 -0
  56. package/src/generators/IRToTypeScriptGenerator.res +72 -0
  57. package/src/generators/ModuleGenerator.res +362 -0
  58. package/src/generators/SchemaCodeGenerator.res +83 -0
  59. package/src/generators/ThinWrapperGenerator.res +124 -0
  60. package/src/generators/TypeScriptDtsGenerator.res +193 -0
  61. package/src/generators/TypeScriptWrapperGenerator.res +166 -0
  62. package/src/types/CodegenError.res +82 -0
  63. package/src/types/Config.res +89 -0
  64. package/src/types/GenerationContext.res +23 -0
@@ -0,0 +1,155 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as SpecDiffer from "../core/SpecDiffer.mjs";
4
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
5
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
+ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
7
+
8
+ function formatEndpointName(endpoint) {
9
+ let methodPart = endpoint.method.toUpperCase();
10
+ let operationIdPart = Stdlib_Option.mapOr(endpoint.operationId, "", id => ` (` + id + `)`);
11
+ return methodPart + ` ` + endpoint.path + operationIdPart;
12
+ }
13
+
14
+ function formatTags(tags) {
15
+ return Stdlib_Option.mapOr(tags, "", tagList => {
16
+ if (tagList.length === 0) {
17
+ return "";
18
+ } else {
19
+ return ` [` + tagList.join(", ") + `]`;
20
+ }
21
+ });
22
+ }
23
+
24
+ function generateMarkdownReport(diff, baseName, forkName) {
25
+ let generateSection = (title, items, formatter) => {
26
+ if (items.length === 0) {
27
+ return "";
28
+ } else {
29
+ return `\n### ` + title + `\n\n` + items.map(formatter).join("\n") + `\n`;
30
+ }
31
+ };
32
+ let totalChanges = SpecDiffer.countChanges(diff);
33
+ let breakingChangesText = SpecDiffer.hasBreakingChanges(diff) ? "⚠️ Yes" : "✓ No";
34
+ let summaryLines = [
35
+ `- **Total Changes**: ` + totalChanges.toString(),
36
+ `- **Added Endpoints**: ` + diff.addedEndpoints.length.toString(),
37
+ `- **Removed Endpoints**: ` + diff.removedEndpoints.length.toString(),
38
+ `- **Modified Endpoints**: ` + diff.modifiedEndpoints.length.toString(),
39
+ `- **Added Schemas**: ` + diff.addedSchemas.length.toString(),
40
+ `- **Removed Schemas**: ` + diff.removedSchemas.length.toString(),
41
+ `- **Modified Schemas**: ` + diff.modifiedSchemas.length.toString(),
42
+ `- **Breaking Changes**: ` + breakingChangesText
43
+ ].join("\n");
44
+ let reportParts = [
45
+ `# API Diff Report: ` + baseName + ` → ` + forkName + `\n\n## Summary\n\n` + summaryLines,
46
+ generateSection("Added Endpoints", diff.addedEndpoints, endpoint => {
47
+ let endpointName = formatEndpointName(endpoint);
48
+ let tags = formatTags(endpoint.tags);
49
+ let summary = Stdlib_Option.mapOr(endpoint.summary, "", summary => `\n ` + summary);
50
+ return `- **` + endpointName + `**` + tags + summary;
51
+ }),
52
+ generateSection("Removed Endpoints", diff.removedEndpoints, endpoint => {
53
+ let endpointName = formatEndpointName(endpoint);
54
+ let tags = formatTags(endpoint.tags);
55
+ return `- **` + endpointName + `**` + tags;
56
+ }),
57
+ generateSection("Modified Endpoints", diff.modifiedEndpoints, endpointDiff => {
58
+ let methodPart = endpointDiff.method.toUpperCase();
59
+ let breakingText = endpointDiff.breakingChange ? " **⚠️ BREAKING**" : "";
60
+ let changes = [
61
+ endpointDiff.requestBodyChanged ? "body" : "",
62
+ endpointDiff.responseChanged ? "response" : ""
63
+ ].filter(x => x !== "").join(", ");
64
+ return `- **` + methodPart + ` ` + endpointDiff.path + `**` + breakingText + `: Changed ` + changes;
65
+ }),
66
+ generateSection("Added Schemas", diff.addedSchemas, schemaName => `- \`` + schemaName + `\``),
67
+ generateSection("Removed Schemas", diff.removedSchemas, schemaName => `- \`` + schemaName + `\``),
68
+ generateSection("Modified Schemas", diff.modifiedSchemas, schemaDiff => {
69
+ let breakingText = schemaDiff.breakingChange ? " **⚠️ BREAKING**" : "";
70
+ return `- \`` + schemaDiff.name + `\`` + breakingText;
71
+ }),
72
+ `\n---\n*Generated on ` + new Date().toISOString() + `*`
73
+ ];
74
+ return reportParts.filter(part => part !== "").join("\n");
75
+ }
76
+
77
+ function generateCompactSummary(diff) {
78
+ let totalChanges = SpecDiffer.countChanges(diff);
79
+ let addedCount = diff.addedEndpoints.length;
80
+ let removedCount = diff.removedEndpoints.length;
81
+ let modifiedCount = diff.modifiedEndpoints.length;
82
+ let breakingText = SpecDiffer.hasBreakingChanges(diff) ? " (BREAKING)" : "";
83
+ return `Found ` + totalChanges.toString() + ` changes: +` + addedCount.toString() + ` -` + removedCount.toString() + ` ~` + modifiedCount.toString() + ` endpoints` + breakingText;
84
+ }
85
+
86
+ function generateMergeReport(stats, baseName, forkName) {
87
+ let sharedEndpoints = stats.sharedEndpointCount.toString();
88
+ let sharedSchemas = stats.sharedSchemaCount.toString();
89
+ let extensionEndpoints = stats.forkExtensionCount.toString();
90
+ let extensionSchemas = stats.forkSchemaCount.toString();
91
+ return CodegenUtils.trimMargin(`
92
+ |# Merge Report: ` + baseName + ` + ` + forkName + `
93
+ |
94
+ |## Shared Code
95
+ |
96
+ |- **Shared Endpoints**: ` + sharedEndpoints + `
97
+ |- **Shared Schemas**: ` + sharedSchemas + `
98
+ |
99
+ |## ` + forkName + ` Extensions
100
+ |
101
+ |- **Extension Endpoints**: ` + extensionEndpoints + `
102
+ |- **Extension Schemas**: ` + extensionSchemas + `
103
+ |
104
+ |## Summary
105
+ |
106
+ |The shared base contains ` + sharedEndpoints + ` endpoints and ` + sharedSchemas + ` schemas.
107
+ |
108
+ |` + forkName + ` adds ` + extensionEndpoints + ` endpoints and ` + extensionSchemas + ` schemas.
109
+ |
110
+ |---
111
+ |*Generated on ` + new Date().toISOString() + `*
112
+ |`, undefined);
113
+ }
114
+
115
+ function generateEndpointsByTagReport(endpoints) {
116
+ let endpointsByTag = {};
117
+ let untaggedEndpoints = [];
118
+ endpoints.forEach(endpoint => {
119
+ let tags = endpoint.tags;
120
+ if (tags !== undefined && tags.length !== 0) {
121
+ tags.forEach(tag => {
122
+ let existing = Stdlib_Option.getOr(endpointsByTag[tag], []);
123
+ existing.push(endpoint);
124
+ endpointsByTag[tag] = existing;
125
+ });
126
+ } else {
127
+ untaggedEndpoints.push(endpoint);
128
+ }
129
+ });
130
+ let tagSections = Object.keys(endpointsByTag).toSorted(Primitive_string.compare).map(tag => {
131
+ let tagEndpoints = Stdlib_Option.getOr(endpointsByTag[tag], []);
132
+ let count = tagEndpoints.length.toString();
133
+ let endpointList = tagEndpoints.map(endpoint => `- ` + formatEndpointName(endpoint)).join("\n");
134
+ return `### ` + tag + ` (` + count + `)\n\n` + endpointList;
135
+ }).join("\n\n");
136
+ let untaggedSection;
137
+ if (untaggedEndpoints.length !== 0) {
138
+ let count = untaggedEndpoints.length.toString();
139
+ let endpointList = untaggedEndpoints.map(endpoint => `- ` + formatEndpointName(endpoint)).join("\n");
140
+ untaggedSection = `\n\n### Untagged (` + count + `)\n\n` + endpointList;
141
+ } else {
142
+ untaggedSection = "";
143
+ }
144
+ return `## Endpoints by Tag\n\n` + tagSections + untaggedSection;
145
+ }
146
+
147
+ export {
148
+ formatEndpointName,
149
+ formatTags,
150
+ generateMarkdownReport,
151
+ generateCompactSummary,
152
+ generateMergeReport,
153
+ generateEndpointsByTagReport,
154
+ }
155
+ /* CodegenUtils Not a pure module */
@@ -0,0 +1,172 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Text from "@std/text";
4
+ import * as DocOverride from "../core/DocOverride.mjs";
5
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
6
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
+ import * as SchemaIRParser from "../core/SchemaIRParser.mjs";
9
+ import * as IRToSuryGenerator from "./IRToSuryGenerator.mjs";
10
+ import * as IRToTypeGenerator from "./IRToTypeGenerator.mjs";
11
+
12
+ function getJsonSchemaFromRequestBody(requestBody) {
13
+ return Stdlib_Option.flatMap(requestBody, body => Stdlib_Option.flatMap(Object.entries(body.content)[0], param => param[1].schema));
14
+ }
15
+
16
+ function generateTypeCodeAndSchemaCode(jsonSchema, typeName, schemaName, modulePrefixOpt) {
17
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
18
+ let match = SchemaIRParser.parseJsonSchema(undefined, jsonSchema);
19
+ let ir = match[0];
20
+ let match$1 = IRToTypeGenerator.generateNamedType({
21
+ name: typeName,
22
+ description: jsonSchema.description,
23
+ type_: ir
24
+ }, undefined, undefined, modulePrefix);
25
+ let match$2 = IRToSuryGenerator.generateNamedSchema({
26
+ name: schemaName,
27
+ description: jsonSchema.description,
28
+ type_: ir
29
+ }, undefined, undefined, modulePrefix);
30
+ return [
31
+ match$1[0],
32
+ match$2[0]
33
+ ];
34
+ }
35
+
36
+ function generateEndpointFunction(endpoint, overrideDir, moduleName) {
37
+ let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
38
+ let requestTypeName = functionName + `Request`;
39
+ let hasRequestBody = Stdlib_Option.isSome(endpoint.requestBody);
40
+ let requestBody = Stdlib_Option.getOr(endpoint.requestBody, {
41
+ description: undefined,
42
+ content: {},
43
+ required: false
44
+ });
45
+ let isRequestBodyRequired = Stdlib_Option.getOr(requestBody.required, false);
46
+ let bodyParam = hasRequestBody ? (
47
+ isRequestBodyRequired ? `~body: ` + requestTypeName : `~body: option<` + requestTypeName + `>=?`
48
+ ) : "~body as _";
49
+ let bodyValueConversion = hasRequestBody ? (
50
+ isRequestBodyRequired ? ` let jsonBody = body->S.reverseConvertToJsonOrThrow(` + functionName + `RequestSchema)` : ` let jsonBody = body->Option.map(b => b->S.reverseConvertToJsonOrThrow(` + functionName + `RequestSchema))`
51
+ ) : "";
52
+ let successResponse = Stdlib_Array.filterMap([
53
+ "200",
54
+ "201",
55
+ "202",
56
+ "204"
57
+ ], code => endpoint.responses[code])[0];
58
+ let responseHandling = Stdlib_Option.mapOr(successResponse, " response", response => Stdlib_Option.mapOr(response.content, " let _ = response\n ()", content => {
59
+ if (Object.entries(content).length !== 0) {
60
+ return ` let value = response->S.parseOrThrow(` + functionName + `ResponseSchema)\n value`;
61
+ } else {
62
+ return " response";
63
+ }
64
+ }));
65
+ let description;
66
+ if (overrideDir !== undefined && moduleName !== undefined) {
67
+ let overrideResult = DocOverride.readOverrideWithValidation(overrideDir, moduleName, functionName, DocOverride.generateEndpointHash(endpoint));
68
+ if (typeof overrideResult !== "object") {
69
+ description = endpoint.description;
70
+ } else {
71
+ switch (overrideResult.TAG) {
72
+ case "ValidOverride" :
73
+ description = overrideResult._0;
74
+ break;
75
+ case "InvalidHash" :
76
+ description = overrideResult.override;
77
+ break;
78
+ case "FileError" :
79
+ description = endpoint.description;
80
+ break;
81
+ }
82
+ }
83
+ } else {
84
+ description = endpoint.description;
85
+ }
86
+ let docComment = CodegenUtils.generateDocString(endpoint.summary, description, undefined);
87
+ let code = `
88
+ |` + docComment.trimEnd() + `
89
+ |let ` + functionName + ` = (` + bodyParam + `, ~fetch: ` + CodegenUtils.fetchTypeSignature + `): promise<` + functionName + `Response> => {
90
+ |` + bodyValueConversion + `
91
+ | fetch(
92
+ | ~url="` + endpoint.path + `",
93
+ | ~method_="` + endpoint.method.toUpperCase() + `",
94
+ | ~body=` + (
95
+ hasRequestBody ? "Some(jsonBody)" : "None"
96
+ ) + `,
97
+ | )->Promise.then(response => {
98
+ |` + responseHandling + `
99
+ | ->Promise.resolve
100
+ | })
101
+ |}`;
102
+ return CodegenUtils.trimMargin(code, undefined);
103
+ }
104
+
105
+ function generateEndpointCode(endpoint, overrideDir, moduleName, modulePrefixOpt) {
106
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
107
+ let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
108
+ let requestJsonSchema = getJsonSchemaFromRequestBody(endpoint.requestBody);
109
+ let responseJsonSchema = Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Array.filterMap([
110
+ "200",
111
+ "201",
112
+ "202",
113
+ "204"
114
+ ], code => endpoint.responses[code])[0], resp => resp.content), content => Stdlib_Option.flatMap(Object.entries(content)[0], param => param[1].schema));
115
+ let requestPart = Stdlib_Option.mapOr(requestJsonSchema, "", schema => {
116
+ let match = generateTypeCodeAndSchemaCode(schema, functionName + `Request`, functionName + `Request`, modulePrefix);
117
+ return match[0] + `\n\n` + match[1];
118
+ });
119
+ let responsePart = Stdlib_Option.mapOr(responseJsonSchema, `type ` + functionName + `Response = unit`, schema => {
120
+ let match = generateTypeCodeAndSchemaCode(schema, functionName + `Response`, functionName + `Response`, modulePrefix);
121
+ return match[0] + `\n\n` + match[1];
122
+ });
123
+ return [
124
+ requestPart,
125
+ responsePart,
126
+ generateEndpointFunction(endpoint, overrideDir, moduleName)
127
+ ].filter(s => s !== "").join("\n\n");
128
+ }
129
+
130
+ function generateEndpointModule(endpoint, modulePrefixOpt) {
131
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
132
+ let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
133
+ let header = CodegenUtils.generateFileHeader(Stdlib_Option.getOr(endpoint.summary, `API: ` + endpoint.path));
134
+ return CodegenUtils.trimMargin(`
135
+ |` + header.trimEnd() + `
136
+ |
137
+ |module ` + Text.toPascalCase(functionName) + ` = {
138
+ |` + CodegenUtils.indent(generateEndpointCode(endpoint, undefined, undefined, modulePrefix), 2) + `
139
+ |}
140
+ |`, undefined);
141
+ }
142
+
143
+ function generateEndpointsModule(moduleName, endpoints, description, overrideDir, modulePrefixOpt) {
144
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
145
+ let header = CodegenUtils.generateFileHeader(Stdlib_Option.getOr(description, `API for ` + moduleName));
146
+ let body = endpoints.map(ep => CodegenUtils.indent(generateEndpointCode(ep, overrideDir, moduleName, modulePrefix), 2)).join("\n\n");
147
+ return CodegenUtils.trimMargin(`
148
+ |` + header.trimEnd() + `
149
+ |
150
+ |module ` + moduleName + ` = {
151
+ |` + body + `
152
+ |}
153
+ |`, undefined);
154
+ }
155
+
156
+ function generateEndpointSignature(endpoint) {
157
+ let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method);
158
+ let summaryPrefix = Stdlib_Option.mapOr(endpoint.summary, "", s => `// ` + s + `\n`);
159
+ let bodyParam = Stdlib_Option.isSome(endpoint.requestBody) ? "~body: 'body, " : "";
160
+ return summaryPrefix + `let ` + functionName + `: (` + bodyParam + `~fetch: fetchFn) => promise<` + functionName + `Response>`;
161
+ }
162
+
163
+ export {
164
+ getJsonSchemaFromRequestBody,
165
+ generateTypeCodeAndSchemaCode,
166
+ generateEndpointFunction,
167
+ generateEndpointCode,
168
+ generateEndpointModule,
169
+ generateEndpointsModule,
170
+ generateEndpointSignature,
171
+ }
172
+ /* @std/text Not a pure module */
@@ -0,0 +1,233 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as SchemaIR from "../core/SchemaIR.mjs";
4
+ import * as Text from "@std/text";
5
+ import * as CodegenUtils from "../core/CodegenUtils.mjs";
6
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
+ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
10
+ import * as GenerationContext from "../types/GenerationContext.mjs";
11
+ import * as ReferenceResolver from "../core/ReferenceResolver.mjs";
12
+
13
+ function applyConstraints(base, min, max, toString) {
14
+ let s1 = min !== undefined ? base + `->S.min(` + toString(Primitive_option.valFromOption(min)) + `)` : base;
15
+ if (max !== undefined) {
16
+ return s1 + `->S.max(` + toString(Primitive_option.valFromOption(max)) + `)`;
17
+ } else {
18
+ return s1;
19
+ }
20
+ }
21
+
22
+ function generateSchemaWithContext(ctx, depthOpt, irType) {
23
+ let depth = depthOpt !== undefined ? depthOpt : 0;
24
+ if (depth > 100) {
25
+ GenerationContext.addWarning(ctx, {
26
+ TAG: "DepthLimitReached",
27
+ depth: depth,
28
+ path: ctx.path
29
+ });
30
+ return "S.json";
31
+ }
32
+ let recurse = nextIrType => generateSchemaWithContext(ctx, depth + 1 | 0, nextIrType);
33
+ if (typeof irType !== "object") {
34
+ switch (irType) {
35
+ case "Boolean" :
36
+ return "S.bool";
37
+ case "Null" :
38
+ return "S.null";
39
+ case "Unknown" :
40
+ return "S.json";
41
+ }
42
+ } else {
43
+ switch (irType.TAG) {
44
+ case "String" :
45
+ let c = irType.constraints;
46
+ let s = applyConstraints("S.string", c.minLength, c.maxLength, v => v.toString());
47
+ let p = c.pattern;
48
+ if (p !== undefined) {
49
+ return s + `->S.pattern(%re("/` + CodegenUtils.escapeString(p) + `/"))`;
50
+ } else {
51
+ return s;
52
+ }
53
+ case "Number" :
54
+ let c$1 = irType.constraints;
55
+ return applyConstraints("S.float", c$1.minimum, c$1.maximum, v => (v | 0).toString());
56
+ case "Integer" :
57
+ let c$2 = irType.constraints;
58
+ return applyConstraints("S.int", c$2.minimum, c$2.maximum, v => (v | 0).toString());
59
+ case "Array" :
60
+ let c$3 = irType.constraints;
61
+ return applyConstraints(`S.array(` + recurse(irType.items) + `)`, c$3.minItems, c$3.maxItems, v => v.toString());
62
+ case "Object" :
63
+ let additionalProperties = irType.additionalProperties;
64
+ let properties = irType.properties;
65
+ if (properties.length === 0) {
66
+ if (additionalProperties !== undefined) {
67
+ return `S.dict(` + recurse(additionalProperties) + `)`;
68
+ } else {
69
+ return "S.json";
70
+ }
71
+ }
72
+ let fields = properties.map(param => {
73
+ let name = param[0];
74
+ let schemaCode = recurse(param[1]);
75
+ let camelName = CodegenUtils.escapeKeyword(Text.toCamelCase(name));
76
+ if (param[2]) {
77
+ return ` ` + camelName + `: s.field("` + name + `", ` + schemaCode + `),`;
78
+ } else {
79
+ return ` ` + camelName + `: s.fieldOr("` + name + `", S.nullableAsOption(` + schemaCode + `), None),`;
80
+ }
81
+ }).join("\n");
82
+ return `S.object(s => {\n` + fields + `\n })`;
83
+ case "Literal" :
84
+ let value = irType._0;
85
+ if (typeof value !== "object") {
86
+ return "S.literal(null)";
87
+ }
88
+ switch (value.TAG) {
89
+ case "StringLiteral" :
90
+ return `S.literal("` + CodegenUtils.escapeString(value._0) + `")`;
91
+ case "NumberLiteral" :
92
+ return `S.literal(` + value._0.toString() + `)`;
93
+ case "BooleanLiteral" :
94
+ return `S.literal(` + (
95
+ value._0 ? "true" : "false"
96
+ ) + `)`;
97
+ }
98
+ case "Union" :
99
+ let types = irType._0;
100
+ let match = Stdlib_Array.reduce(types, [
101
+ false,
102
+ false,
103
+ undefined,
104
+ undefined
105
+ ], (param, t) => {
106
+ let arrItem = param[2];
107
+ let hArr = param[0];
108
+ if (typeof t !== "object" || t.TAG !== "Array") {
109
+ return [
110
+ hArr,
111
+ true,
112
+ arrItem,
113
+ t
114
+ ];
115
+ } else {
116
+ return [
117
+ true,
118
+ param[1],
119
+ t.items,
120
+ param[3]
121
+ ];
122
+ }
123
+ });
124
+ let arrayItemType = match[2];
125
+ if (match[0] && match[1] && SchemaIR.equals(Stdlib_Option.getOr(arrayItemType, "Unknown"), Stdlib_Option.getOr(match[3], "Unknown"))) {
126
+ return `S.array(` + recurse(Stdlib_Option.getOr(arrayItemType, "Unknown")) + `)`;
127
+ } else if (types.every(t => {
128
+ if (typeof t !== "object") {
129
+ return false;
130
+ }
131
+ if (t.TAG !== "Literal") {
132
+ return false;
133
+ }
134
+ let tmp = t._0;
135
+ return typeof tmp !== "object" ? false : tmp.TAG === "StringLiteral";
136
+ }) && types.length !== 0 && types.length <= 50) {
137
+ return `S.union([` + types.map(recurse).join(", ") + `])`;
138
+ } else {
139
+ GenerationContext.addWarning(ctx, {
140
+ TAG: "ComplexUnionSimplified",
141
+ location: ctx.path,
142
+ types: types.map(SchemaIR.toString).join(" | ")
143
+ });
144
+ return "S.json";
145
+ }
146
+ case "Intersection" :
147
+ let types$1 = irType._0;
148
+ if (types$1.every(t => typeof t !== "object" ? false : t.TAG === "Reference") && types$1.length !== 0) {
149
+ return recurse(Stdlib_Option.getOr(types$1[types$1.length - 1 | 0], "Unknown"));
150
+ } else {
151
+ GenerationContext.addWarning(ctx, {
152
+ TAG: "IntersectionNotFullySupported",
153
+ location: ctx.path,
154
+ note: "Complex intersection"
155
+ });
156
+ return "S.json";
157
+ }
158
+ case "Reference" :
159
+ let ref = irType._0;
160
+ let available = ctx.availableSchemas;
161
+ let schemaPath;
162
+ if (available !== undefined) {
163
+ let name = Stdlib_Option.getOr(ref.split("/")[ref.split("/").length - 1 | 0], "");
164
+ schemaPath = available.includes(name) ? Text.toPascalCase(name) + `.schema` : `ComponentSchemas.` + Text.toPascalCase(name) + `.schema`;
165
+ } else {
166
+ schemaPath = Stdlib_Option.getOr(ReferenceResolver.refToSchemaPath(ctx.insideComponentSchemas, ctx.modulePrefix, ref), "S.json");
167
+ }
168
+ if (schemaPath === "S.json") {
169
+ GenerationContext.addWarning(ctx, {
170
+ TAG: "FallbackToJson",
171
+ reason: `Unresolved ref: ` + ref,
172
+ context: {
173
+ path: ctx.path,
174
+ operation: "gen ref",
175
+ schema: undefined
176
+ }
177
+ });
178
+ }
179
+ return schemaPath;
180
+ case "Option" :
181
+ return `S.nullableAsOption(` + recurse(irType._0) + `)`;
182
+ }
183
+ }
184
+ }
185
+
186
+ function generateSchema(depthOpt, pathOpt, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt, irType) {
187
+ let depth = depthOpt !== undefined ? depthOpt : 0;
188
+ let path = pathOpt !== undefined ? pathOpt : "";
189
+ let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
190
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
191
+ let ctx = GenerationContext.make(path, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
192
+ return [
193
+ generateSchemaWithContext(ctx, depth, irType),
194
+ ctx.warnings
195
+ ];
196
+ }
197
+
198
+ function generateNamedSchema(namedSchema, insideComponentSchemasOpt, availableSchemas, modulePrefixOpt) {
199
+ let insideComponentSchemas = insideComponentSchemasOpt !== undefined ? insideComponentSchemasOpt : false;
200
+ let modulePrefix = modulePrefixOpt !== undefined ? modulePrefixOpt : "";
201
+ let ctx = GenerationContext.make(`schema.` + namedSchema.name, insideComponentSchemas, availableSchemas, modulePrefix, undefined);
202
+ let d = namedSchema.description;
203
+ let doc = d !== undefined ? CodegenUtils.generateDocComment(undefined, d, undefined) : "";
204
+ return [
205
+ doc + `let ` + namedSchema.name + `Schema = ` + generateSchemaWithContext(ctx, 0, namedSchema.type_),
206
+ ctx.warnings
207
+ ];
208
+ }
209
+
210
+ function generateAllSchemas(context) {
211
+ let warnings = [];
212
+ let schemas = Object.values(context.schemas).toSorted((a, b) => Primitive_string.compare(a.name, b.name)).map(s => {
213
+ let match = generateNamedSchema(s, undefined, undefined, undefined);
214
+ warnings.push(...match[1]);
215
+ return match[0];
216
+ });
217
+ return [
218
+ schemas,
219
+ warnings
220
+ ];
221
+ }
222
+
223
+ let addWarning = GenerationContext.addWarning;
224
+
225
+ export {
226
+ addWarning,
227
+ applyConstraints,
228
+ generateSchemaWithContext,
229
+ generateSchema,
230
+ generateNamedSchema,
231
+ generateAllSchemas,
232
+ }
233
+ /* @std/text Not a pure module */