@sdk-it/typescript 0.19.1 → 0.20.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/dist/index.d.ts +2 -2
- package/dist/index.js +400 -115
- package/dist/index.js.map +4 -4
- package/dist/lib/emitters/interface.d.ts +1 -1
- package/dist/lib/emitters/interface.d.ts.map +1 -1
- package/dist/lib/emitters/zod.d.ts +1 -1
- package/dist/lib/emitters/zod.d.ts.map +1 -1
- package/dist/lib/generate.d.ts +1 -0
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/generator.d.ts.map +1 -1
- package/dist/lib/readme.d.ts +19 -0
- package/dist/lib/readme.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3,7 +3,11 @@ import { template as template2 } from "lodash-es";
|
|
|
3
3
|
import { join as join2 } from "node:path";
|
|
4
4
|
import { npmRunPathEnv } from "npm-run-path";
|
|
5
5
|
import { spinalcase as spinalcase3 } from "stringcase";
|
|
6
|
-
import {
|
|
6
|
+
import { methods, pascalcase as pascalcase3 } from "@sdk-it/core";
|
|
7
|
+
import {
|
|
8
|
+
getFolderExports,
|
|
9
|
+
writeFiles
|
|
10
|
+
} from "@sdk-it/core/file-system.js";
|
|
7
11
|
|
|
8
12
|
// packages/typescript/src/lib/client.ts
|
|
9
13
|
import { toLitObject } from "@sdk-it/core";
|
|
@@ -132,10 +136,11 @@ export class ${spec.name} {
|
|
|
132
136
|
import { merge, template } from "lodash-es";
|
|
133
137
|
import { join } from "node:path";
|
|
134
138
|
import { camelcase as camelcase3, pascalcase as pascalcase2, spinalcase as spinalcase2 } from "stringcase";
|
|
135
|
-
import { followRef as
|
|
139
|
+
import { followRef as followRef5, isEmpty, isRef as isRef6 } from "@sdk-it/core";
|
|
136
140
|
|
|
137
141
|
// packages/spec/dist/lib/operation.js
|
|
138
142
|
import { camelcase } from "stringcase";
|
|
143
|
+
import { followRef, isRef } from "@sdk-it/core";
|
|
139
144
|
var defaults = {
|
|
140
145
|
operationId: (operation, path, method) => {
|
|
141
146
|
if (operation.operationId) {
|
|
@@ -150,9 +155,18 @@ var defaults = {
|
|
|
150
155
|
);
|
|
151
156
|
},
|
|
152
157
|
tag: (operation, path) => {
|
|
153
|
-
return operation.tags?.[0]
|
|
158
|
+
return operation.tags?.[0] ? sanitizeTag(operation.tags?.[0]) : determineGenericTag(path, operation);
|
|
154
159
|
}
|
|
155
160
|
};
|
|
161
|
+
function resolveResponses(spec, operation) {
|
|
162
|
+
const responses = operation.responses ?? {};
|
|
163
|
+
const resolved = {};
|
|
164
|
+
for (const status in responses) {
|
|
165
|
+
const response = isRef(responses[status]) ? followRef(spec, responses[status].$ref) : responses[status];
|
|
166
|
+
resolved[status] = response;
|
|
167
|
+
}
|
|
168
|
+
return resolved;
|
|
169
|
+
}
|
|
156
170
|
function forEachOperation(config, callback) {
|
|
157
171
|
const result = [];
|
|
158
172
|
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
@@ -176,7 +190,8 @@ function forEachOperation(config, callback) {
|
|
|
176
190
|
{
|
|
177
191
|
...operation,
|
|
178
192
|
parameters: [...parameters, ...operation.parameters ?? []],
|
|
179
|
-
operationId: operationName
|
|
193
|
+
operationId: operationName,
|
|
194
|
+
responses: resolveResponses(config.spec, operation)
|
|
180
195
|
}
|
|
181
196
|
)
|
|
182
197
|
);
|
|
@@ -185,15 +200,11 @@ function forEachOperation(config, callback) {
|
|
|
185
200
|
return result;
|
|
186
201
|
}
|
|
187
202
|
var reservedKeywords = /* @__PURE__ */ new Set([
|
|
188
|
-
"abstract",
|
|
189
|
-
"arguments",
|
|
190
203
|
"await",
|
|
191
|
-
|
|
204
|
+
// Reserved in async functions
|
|
192
205
|
"break",
|
|
193
|
-
"byte",
|
|
194
206
|
"case",
|
|
195
207
|
"catch",
|
|
196
|
-
"char",
|
|
197
208
|
"class",
|
|
198
209
|
"const",
|
|
199
210
|
"continue",
|
|
@@ -201,85 +212,59 @@ var reservedKeywords = /* @__PURE__ */ new Set([
|
|
|
201
212
|
"default",
|
|
202
213
|
"delete",
|
|
203
214
|
"do",
|
|
204
|
-
"double",
|
|
205
215
|
"else",
|
|
206
216
|
"enum",
|
|
207
|
-
"eval",
|
|
208
217
|
"export",
|
|
209
218
|
"extends",
|
|
210
219
|
"false",
|
|
211
|
-
"final",
|
|
212
220
|
"finally",
|
|
213
|
-
"float",
|
|
214
221
|
"for",
|
|
215
222
|
"function",
|
|
216
|
-
"goto",
|
|
217
223
|
"if",
|
|
218
224
|
"implements",
|
|
225
|
+
// Strict mode
|
|
219
226
|
"import",
|
|
220
227
|
"in",
|
|
221
228
|
"instanceof",
|
|
222
|
-
"int",
|
|
223
229
|
"interface",
|
|
230
|
+
// Strict mode
|
|
224
231
|
"let",
|
|
225
|
-
|
|
226
|
-
"native",
|
|
232
|
+
// Strict mode
|
|
227
233
|
"new",
|
|
228
234
|
"null",
|
|
229
235
|
"package",
|
|
236
|
+
// Strict mode
|
|
230
237
|
"private",
|
|
238
|
+
// Strict mode
|
|
231
239
|
"protected",
|
|
240
|
+
// Strict mode
|
|
232
241
|
"public",
|
|
242
|
+
// Strict mode
|
|
233
243
|
"return",
|
|
234
|
-
"short",
|
|
235
244
|
"static",
|
|
245
|
+
// Strict mode
|
|
236
246
|
"super",
|
|
237
247
|
"switch",
|
|
238
|
-
"synchronized",
|
|
239
248
|
"this",
|
|
240
249
|
"throw",
|
|
241
|
-
"throws",
|
|
242
|
-
"transient",
|
|
243
250
|
"true",
|
|
244
251
|
"try",
|
|
245
252
|
"typeof",
|
|
246
253
|
"var",
|
|
247
254
|
"void",
|
|
248
|
-
"volatile",
|
|
249
255
|
"while",
|
|
250
256
|
"with",
|
|
251
257
|
"yield",
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"
|
|
256
|
-
"any",
|
|
257
|
-
"unknown",
|
|
258
|
-
"never",
|
|
259
|
-
"get",
|
|
260
|
-
"list",
|
|
261
|
-
"create",
|
|
262
|
-
"update",
|
|
263
|
-
"delete",
|
|
264
|
-
"post",
|
|
265
|
-
"put",
|
|
266
|
-
"patch",
|
|
267
|
-
"do",
|
|
268
|
-
"send",
|
|
269
|
-
"add",
|
|
270
|
-
"remove",
|
|
271
|
-
"set",
|
|
272
|
-
"find",
|
|
273
|
-
"search",
|
|
274
|
-
"check",
|
|
275
|
-
"make"
|
|
276
|
-
// Added make, check
|
|
258
|
+
// Strict mode / Generator functions
|
|
259
|
+
// 'arguments' is not technically a reserved word, but it's a special identifier within functions
|
|
260
|
+
// and assigning to it or declaring it can cause issues or unexpected behavior.
|
|
261
|
+
"arguments"
|
|
277
262
|
]);
|
|
278
263
|
function sanitizeTag(camelCasedTag) {
|
|
279
264
|
if (/^\d/.test(camelCasedTag)) {
|
|
280
265
|
return `_${camelCasedTag}`;
|
|
281
266
|
}
|
|
282
|
-
return reservedKeywords.has(camelCasedTag) ? `${camelCasedTag}_` : camelCasedTag;
|
|
267
|
+
return reservedKeywords.has(camelcase(camelCasedTag)) ? `${camelCasedTag}_` : camelCasedTag;
|
|
283
268
|
}
|
|
284
269
|
function determineGenericTag(pathString, operation) {
|
|
285
270
|
const operationId = operation.operationId || "";
|
|
@@ -303,7 +288,6 @@ function determineGenericTag(pathString, operation) {
|
|
|
303
288
|
"search",
|
|
304
289
|
"check",
|
|
305
290
|
"make"
|
|
306
|
-
// Added make
|
|
307
291
|
]);
|
|
308
292
|
const segments = pathString.split("/").filter(Boolean);
|
|
309
293
|
const potentialCandidates = segments.filter(
|
|
@@ -397,9 +381,9 @@ function determineGenericTag(pathString, operation) {
|
|
|
397
381
|
}
|
|
398
382
|
|
|
399
383
|
// packages/typescript/src/lib/emitters/zod.ts
|
|
400
|
-
import { cleanRef, followRef, isRef
|
|
384
|
+
import { cleanRef, followRef as followRef2, isRef as isRef2 } from "@sdk-it/core";
|
|
401
385
|
var ZodDeserialzer = class {
|
|
402
|
-
|
|
386
|
+
generatedRefs = /* @__PURE__ */ new Set();
|
|
403
387
|
#spec;
|
|
404
388
|
#onRef;
|
|
405
389
|
constructor(spec, onRef) {
|
|
@@ -473,15 +457,14 @@ var ZodDeserialzer = class {
|
|
|
473
457
|
}
|
|
474
458
|
ref($ref, required) {
|
|
475
459
|
const schemaName = cleanRef($ref).split("/").pop();
|
|
476
|
-
if (this.
|
|
460
|
+
if (this.generatedRefs.has(schemaName)) {
|
|
477
461
|
return schemaName;
|
|
478
462
|
}
|
|
479
|
-
this.
|
|
463
|
+
this.generatedRefs.add(schemaName);
|
|
480
464
|
this.#onRef?.(
|
|
481
465
|
schemaName,
|
|
482
|
-
this.handle(
|
|
466
|
+
this.handle(followRef2(this.#spec, $ref), required)
|
|
483
467
|
);
|
|
484
|
-
this.circularRefTracker.delete(schemaName);
|
|
485
468
|
return schemaName;
|
|
486
469
|
}
|
|
487
470
|
allOf(schemas, required) {
|
|
@@ -509,15 +492,7 @@ var ZodDeserialzer = class {
|
|
|
509
492
|
return `z.union([${anyOfSchemas.join(", ")}])${appendOptional(required)}`;
|
|
510
493
|
}
|
|
511
494
|
oneOf(schemas, required) {
|
|
512
|
-
const oneOfSchemas = schemas.map((sub) =>
|
|
513
|
-
if (isRef(sub)) {
|
|
514
|
-
const { model } = parseRef(sub.$ref);
|
|
515
|
-
if (this.circularRefTracker.has(model)) {
|
|
516
|
-
return `${model}${appendOptional(required)}`;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
return this.handle(sub, true);
|
|
520
|
-
});
|
|
495
|
+
const oneOfSchemas = schemas.map((sub) => this.handle(sub, true));
|
|
521
496
|
if (oneOfSchemas.length === 1) {
|
|
522
497
|
return `${oneOfSchemas[0]}${appendOptional(required)}`;
|
|
523
498
|
}
|
|
@@ -537,6 +512,10 @@ var ZodDeserialzer = class {
|
|
|
537
512
|
*/
|
|
538
513
|
string(schema) {
|
|
539
514
|
let base = "z.string()";
|
|
515
|
+
if (schema.contentEncoding === "binary") {
|
|
516
|
+
base = "z.instanceof(Blob)";
|
|
517
|
+
return base;
|
|
518
|
+
}
|
|
540
519
|
switch (schema.format) {
|
|
541
520
|
case "date-time":
|
|
542
521
|
case "datetime":
|
|
@@ -614,7 +593,7 @@ var ZodDeserialzer = class {
|
|
|
614
593
|
return { base, defaultValue };
|
|
615
594
|
}
|
|
616
595
|
handle(schema, required) {
|
|
617
|
-
if (
|
|
596
|
+
if (isRef2(schema)) {
|
|
618
597
|
return `${this.ref(schema.$ref, true)}${appendOptional(required)}`;
|
|
619
598
|
}
|
|
620
599
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -661,12 +640,12 @@ function appendDefault(defaultValue) {
|
|
|
661
640
|
// packages/typescript/src/lib/sdk.ts
|
|
662
641
|
import { get } from "lodash-es";
|
|
663
642
|
import { camelcase as camelcase2, pascalcase, spinalcase } from "stringcase";
|
|
664
|
-
import { followRef as
|
|
643
|
+
import { followRef as followRef4, isRef as isRef5, toLitObject as toLitObject2 } from "@sdk-it/core";
|
|
665
644
|
|
|
666
645
|
// packages/typescript/src/lib/emitters/interface.ts
|
|
667
|
-
import { cleanRef as cleanRef2, followRef as
|
|
646
|
+
import { cleanRef as cleanRef2, followRef as followRef3, isRef as isRef3 } from "@sdk-it/core";
|
|
668
647
|
var TypeScriptDeserialzer = class {
|
|
669
|
-
|
|
648
|
+
generatedRefs = /* @__PURE__ */ new Set();
|
|
670
649
|
#spec;
|
|
671
650
|
#onRef;
|
|
672
651
|
constructor(spec, onRef) {
|
|
@@ -677,7 +656,7 @@ var TypeScriptDeserialzer = class {
|
|
|
677
656
|
return `'${value}'`;
|
|
678
657
|
};
|
|
679
658
|
#isInternal = (schema) => {
|
|
680
|
-
return
|
|
659
|
+
return isRef3(schema) ? false : !!schema["x-internal"];
|
|
681
660
|
};
|
|
682
661
|
/**
|
|
683
662
|
* Handle objects (properties)
|
|
@@ -739,15 +718,14 @@ var TypeScriptDeserialzer = class {
|
|
|
739
718
|
}
|
|
740
719
|
ref($ref, required) {
|
|
741
720
|
const schemaName = cleanRef2($ref).split("/").pop();
|
|
742
|
-
if (this.
|
|
721
|
+
if (this.generatedRefs.has(schemaName)) {
|
|
743
722
|
return schemaName;
|
|
744
723
|
}
|
|
745
|
-
this.
|
|
724
|
+
this.generatedRefs.add(schemaName);
|
|
746
725
|
this.#onRef?.(
|
|
747
726
|
schemaName,
|
|
748
|
-
this.handle(
|
|
727
|
+
this.handle(followRef3(this.#spec, $ref), required)
|
|
749
728
|
);
|
|
750
|
-
this.circularRefTracker.delete(schemaName);
|
|
751
729
|
return appendOptional2(schemaName, required);
|
|
752
730
|
}
|
|
753
731
|
allOf(schemas) {
|
|
@@ -763,12 +741,6 @@ var TypeScriptDeserialzer = class {
|
|
|
763
741
|
}
|
|
764
742
|
oneOf(schemas, required) {
|
|
765
743
|
const oneOfTypes = schemas.map((sub) => {
|
|
766
|
-
if (isRef2(sub)) {
|
|
767
|
-
const { model } = parseRef2(sub.$ref);
|
|
768
|
-
if (this.circularRefTracker.has(model)) {
|
|
769
|
-
return model;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
744
|
return this.handle(sub, false);
|
|
773
745
|
});
|
|
774
746
|
return appendOptional2(
|
|
@@ -785,6 +757,9 @@ var TypeScriptDeserialzer = class {
|
|
|
785
757
|
*/
|
|
786
758
|
string(schema, required) {
|
|
787
759
|
let type;
|
|
760
|
+
if (schema.contentEncoding === "binary") {
|
|
761
|
+
return appendOptional2("Blob", required);
|
|
762
|
+
}
|
|
788
763
|
switch (schema.format) {
|
|
789
764
|
case "date-time":
|
|
790
765
|
case "datetime":
|
|
@@ -811,7 +786,7 @@ var TypeScriptDeserialzer = class {
|
|
|
811
786
|
return appendOptional2(type, required);
|
|
812
787
|
}
|
|
813
788
|
handle(schema, required) {
|
|
814
|
-
if (
|
|
789
|
+
if (isRef3(schema)) {
|
|
815
790
|
return this.ref(schema.$ref, required);
|
|
816
791
|
}
|
|
817
792
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -856,7 +831,7 @@ function appendOptional2(type, isRequired) {
|
|
|
856
831
|
}
|
|
857
832
|
|
|
858
833
|
// packages/typescript/src/lib/utils.ts
|
|
859
|
-
import { isRef as
|
|
834
|
+
import { isRef as isRef4, removeDuplicates } from "@sdk-it/core";
|
|
860
835
|
function securityToOptions(security2, securitySchemes, staticIn) {
|
|
861
836
|
securitySchemes ??= {};
|
|
862
837
|
const options = {};
|
|
@@ -866,7 +841,7 @@ function securityToOptions(security2, securitySchemes, staticIn) {
|
|
|
866
841
|
continue;
|
|
867
842
|
}
|
|
868
843
|
const schema = securitySchemes[name];
|
|
869
|
-
if (
|
|
844
|
+
if (isRef4(schema)) {
|
|
870
845
|
throw new Error(`Ref security schemas are not supported`);
|
|
871
846
|
}
|
|
872
847
|
if (schema.type === "http") {
|
|
@@ -1025,7 +1000,7 @@ function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
|
1025
1000
|
return statusCode >= 200 && statusCode < 300;
|
|
1026
1001
|
}).length > 1;
|
|
1027
1002
|
for (const status in specOperation.responses) {
|
|
1028
|
-
const response =
|
|
1003
|
+
const response = isRef5(specOperation.responses[status]) ? followRef4(spec, specOperation.responses[status].$ref) : specOperation.responses[status];
|
|
1029
1004
|
const handled = handleResponse(
|
|
1030
1005
|
spec,
|
|
1031
1006
|
operation.name,
|
|
@@ -1135,7 +1110,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1135
1110
|
let responseSchema = parser === "chunked" ? "ReadableStream" : "void";
|
|
1136
1111
|
if (isJson) {
|
|
1137
1112
|
const schema = responseContent["application/json"].schema;
|
|
1138
|
-
const isObject = !
|
|
1113
|
+
const isObject = !isRef5(schema) && schema.type === "object";
|
|
1139
1114
|
if (isObject && schema.properties) {
|
|
1140
1115
|
schema.properties["[http.KIND]"] = {
|
|
1141
1116
|
"x-internal": true,
|
|
@@ -1143,7 +1118,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1143
1118
|
type: "string"
|
|
1144
1119
|
};
|
|
1145
1120
|
schema.required ??= [];
|
|
1146
|
-
schema.required.push("[KIND]");
|
|
1121
|
+
schema.required.push("[http.KIND]");
|
|
1147
1122
|
}
|
|
1148
1123
|
responseSchema = typeScriptDeserialzer.handle(schema, true);
|
|
1149
1124
|
}
|
|
@@ -1200,9 +1175,9 @@ function generateCode(config) {
|
|
|
1200
1175
|
groups[entry.groupName] ??= [];
|
|
1201
1176
|
endpoints[entry.groupName] ??= [];
|
|
1202
1177
|
const inputs = {};
|
|
1203
|
-
const additionalProperties =
|
|
1178
|
+
const additionalProperties = {};
|
|
1204
1179
|
for (const param of operation.parameters ?? []) {
|
|
1205
|
-
if (
|
|
1180
|
+
if (isRef6(param)) {
|
|
1206
1181
|
throw new Error(`Found reference in parameter ${param.$ref}`);
|
|
1207
1182
|
}
|
|
1208
1183
|
if (!param.schema) {
|
|
@@ -1212,24 +1187,22 @@ function generateCode(config) {
|
|
|
1212
1187
|
in: param.in,
|
|
1213
1188
|
schema: ""
|
|
1214
1189
|
};
|
|
1215
|
-
additionalProperties.
|
|
1190
|
+
additionalProperties[param.name] = param;
|
|
1216
1191
|
}
|
|
1217
1192
|
const security2 = operation.security ?? [];
|
|
1218
1193
|
const securitySchemes = config.spec.components?.securitySchemes ?? {};
|
|
1219
1194
|
const securityOptions = securityToOptions(security2, securitySchemes);
|
|
1220
1195
|
Object.assign(inputs, securityOptions);
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
)
|
|
1232
|
-
);
|
|
1196
|
+
Object.entries(securityOptions).forEach(([name, value]) => {
|
|
1197
|
+
additionalProperties[name] = {
|
|
1198
|
+
name,
|
|
1199
|
+
required: false,
|
|
1200
|
+
schema: {
|
|
1201
|
+
type: "string"
|
|
1202
|
+
},
|
|
1203
|
+
in: value.in
|
|
1204
|
+
};
|
|
1205
|
+
});
|
|
1233
1206
|
const schemas = {};
|
|
1234
1207
|
const shortContenTypeMap = {
|
|
1235
1208
|
"application/json": "json",
|
|
@@ -1244,9 +1217,9 @@ function generateCode(config) {
|
|
|
1244
1217
|
};
|
|
1245
1218
|
let outgoingContentType;
|
|
1246
1219
|
if (!isEmpty(operation.requestBody)) {
|
|
1247
|
-
const requestBody =
|
|
1220
|
+
const requestBody = isRef6(operation.requestBody) ? followRef5(config.spec, operation.requestBody.$ref) : operation.requestBody;
|
|
1248
1221
|
for (const type in requestBody.content) {
|
|
1249
|
-
const ctSchema =
|
|
1222
|
+
const ctSchema = isRef6(requestBody.content[type].schema) ? followRef5(config.spec, requestBody.content[type].schema.$ref) : requestBody.content[type].schema;
|
|
1250
1223
|
if (!ctSchema) {
|
|
1251
1224
|
console.warn(
|
|
1252
1225
|
`Schema not found for ${type} in ${entry.method} ${entry.path}`
|
|
@@ -1264,9 +1237,9 @@ function generateCode(config) {
|
|
|
1264
1237
|
};
|
|
1265
1238
|
}
|
|
1266
1239
|
const schema = merge({}, objectSchema, {
|
|
1267
|
-
required: additionalProperties.filter((p) => p.required).map((p) => p.name),
|
|
1268
|
-
properties: additionalProperties.reduce(
|
|
1269
|
-
(acc, p) => ({
|
|
1240
|
+
required: Object.values(additionalProperties).filter((p) => p.required).map((p) => p.name),
|
|
1241
|
+
properties: Object.entries(additionalProperties).reduce(
|
|
1242
|
+
(acc, [, p]) => ({
|
|
1270
1243
|
...acc,
|
|
1271
1244
|
[p.name]: p.schema
|
|
1272
1245
|
}),
|
|
@@ -1286,8 +1259,8 @@ function generateCode(config) {
|
|
|
1286
1259
|
outgoingContentType = "json";
|
|
1287
1260
|
}
|
|
1288
1261
|
} else {
|
|
1289
|
-
const properties = additionalProperties.reduce(
|
|
1290
|
-
(acc, p) => ({
|
|
1262
|
+
const properties = Object.entries(additionalProperties).reduce(
|
|
1263
|
+
(acc, [, p]) => ({
|
|
1291
1264
|
...acc,
|
|
1292
1265
|
[p.name]: p.schema
|
|
1293
1266
|
}),
|
|
@@ -1296,7 +1269,7 @@ function generateCode(config) {
|
|
|
1296
1269
|
schemas[shortContenTypeMap["application/json"]] = zodDeserialzer.handle(
|
|
1297
1270
|
{
|
|
1298
1271
|
type: "object",
|
|
1299
|
-
required: additionalProperties.filter((p) => p.required).map((p) => p.name),
|
|
1272
|
+
required: Object.values(additionalProperties).filter((p) => p.required).map((p) => p.name),
|
|
1300
1273
|
properties
|
|
1301
1274
|
},
|
|
1302
1275
|
true
|
|
@@ -1421,7 +1394,6 @@ ${allSchemas.map((it) => it.use).join(",\n")}
|
|
|
1421
1394
|
join("api", `${spinalcase2(name)}.ts`),
|
|
1422
1395
|
`${[
|
|
1423
1396
|
...imps,
|
|
1424
|
-
// ...imports,
|
|
1425
1397
|
`import z from 'zod';`,
|
|
1426
1398
|
`import * as http from '${config.makeImport("../http/response")}';`,
|
|
1427
1399
|
`import { toRequest, json, urlencoded, nobody, formdata, createUrl } from '${config.makeImport("../http/request")}';`,
|
|
@@ -1441,8 +1413,8 @@ ${endpoint.flatMap((it) => it.schemas).join(",\n")}
|
|
|
1441
1413
|
};
|
|
1442
1414
|
}
|
|
1443
1415
|
function toProps(spec, schemaOrRef, aggregator = []) {
|
|
1444
|
-
if (
|
|
1445
|
-
const schema =
|
|
1416
|
+
if (isRef6(schemaOrRef)) {
|
|
1417
|
+
const schema = followRef5(spec, schemaOrRef.$ref);
|
|
1446
1418
|
return toProps(spec, schema, aggregator);
|
|
1447
1419
|
} else if (schemaOrRef.type === "object") {
|
|
1448
1420
|
for (const [name] of Object.entries(schemaOrRef.properties ?? {})) {
|
|
@@ -1912,6 +1884,311 @@ export type SuccessfulResponse =
|
|
|
1912
1884
|
// packages/typescript/src/lib/http/send-request.txt
|
|
1913
1885
|
var send_request_default = "export interface Type<T> {\n new (...args: any[]): T;\n}\nexport type Parser = (\n response: Response,\n) => Promise<unknown> | ReadableStream<any>;\nexport type OutputType =\n | Type<APIResponse>\n | { parser: Parser; type: Type<APIResponse> };\n\nexport interface RequestSchema {\n schema: z.ZodType;\n toRequest: (input: any) => RequestConfig;\n output: OutputType[];\n}\n\nexport const fetchType = z\n .function()\n .args(z.instanceof(Request))\n .returns(z.promise(z.instanceof(Response)))\n .optional();\n\nexport async function dispatch(\n input: unknown,\n route: RequestSchema,\n options: {\n fetch?: z.infer<typeof fetchType>;\n interceptors?: Interceptor[];\n signal?: AbortSignal;\n },\n) {\n const { interceptors = [] } = options;\n const [parsedInput, parseError] = parseInput(route.schema, input);\n if (parseError) {\n <% if(throwError) { %>\n throw parseError;\n <% } else { %>\n return [null as never, parseError as never] as const;\n <% } %>\n }\n\n let config = route.toRequest(parsedInput as never);\n for (const interceptor of interceptors) {\n if (interceptor.before) {\n config = await interceptor.before(config);\n }\n }\n\n let response = await (options.fetch ?? fetch)(\n new Request(config.url, config.init),\n {\n ...config.init,\n signal: options.signal,\n },\n );\n\n for (let i = interceptors.length - 1; i >= 0; i--) {\n const interceptor = interceptors[i];\n if (interceptor.after) {\n response = await interceptor.after(response.clone());\n }\n }\n return await parse(route, response);\n}\n\nexport async function parse(route: RequestSchema, response: Response) {\n let output: typeof APIResponse | null = null;\n let parser: Parser = buffered;\n for (const outputType of route.output) {\n if ('parser' in outputType) {\n parser = outputType.parser;\n if (isTypeOf(outputType.type, APIResponse)) {\n if (response.status === outputType.type.status) {\n output = outputType.type;\n break;\n }\n }\n } else if (isTypeOf(outputType, APIResponse)) {\n if (response.status === outputType.status) {\n output = outputType;\n break;\n }\n }\n }\n\n if (response.ok) {\n const apiresponse = (output || APIResponse).create(\n response.status,\n await parser(response),\n );\n <% if(throwError) { %>\n return <% if (outputType === 'default') { %>apiresponse.data<% } else { %>apiresponse<% } %>;\n <% } else { %>\n return [<% if (outputType === 'default') { %>apiresponse.data<% } else { %>apiresponse<% } %> , null] as const;\n <% } %>\n }\n<% if(throwError) { %>\n throw (output || APIError).create(\n response.status,\n await parser(response),\n );\n<% } else { %>\n const data = (output || APIError).create(\n response.status,\n await parser(response),\n );\n return [null as never, data as never] as const;\n<% } %>\n}\n\nexport function isTypeOf<T extends Type<APIResponse>>(\n instance: any,\n baseType: T,\n): instance is T {\n if (instance === baseType) {\n return true;\n }\n const prototype = Object.getPrototypeOf(instance);\n if (prototype === null) {\n return false;\n }\n return isTypeOf(prototype, baseType);\n}\n";
|
|
1914
1886
|
|
|
1887
|
+
// packages/typescript/src/lib/readme.ts
|
|
1888
|
+
import { followRef as followRef6, isRef as isRef7 } from "@sdk-it/core";
|
|
1889
|
+
var PropEmitter = class {
|
|
1890
|
+
#spec;
|
|
1891
|
+
constructor(spec) {
|
|
1892
|
+
this.#spec = spec;
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Handle objects (properties)
|
|
1896
|
+
*/
|
|
1897
|
+
#object(schema) {
|
|
1898
|
+
const lines = [];
|
|
1899
|
+
const properties = schema.properties || {};
|
|
1900
|
+
if (Object.keys(properties).length > 0) {
|
|
1901
|
+
lines.push(`**Properties:**`);
|
|
1902
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
1903
|
+
const isRequired = (schema.required ?? []).includes(propName);
|
|
1904
|
+
lines.push(...this.#property(propName, propSchema, isRequired));
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
if (schema.additionalProperties) {
|
|
1908
|
+
lines.push(`**Additional Properties:**`);
|
|
1909
|
+
if (typeof schema.additionalProperties === "boolean") {
|
|
1910
|
+
lines.push(`- Allowed: ${schema.additionalProperties}`);
|
|
1911
|
+
} else {
|
|
1912
|
+
lines.push(
|
|
1913
|
+
...this.handle(schema.additionalProperties).map((l) => ` ${l}`)
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
return lines;
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Format a property with its type and description
|
|
1921
|
+
*/
|
|
1922
|
+
#property(name, schema, required) {
|
|
1923
|
+
const requiredMark = required ? " (required)" : "";
|
|
1924
|
+
const propNameLine = `- \`${name}\`${requiredMark}:`;
|
|
1925
|
+
const lines = [propNameLine];
|
|
1926
|
+
const schemaDocs = this.handle(schema);
|
|
1927
|
+
lines.push(...schemaDocs.map((line) => ` ${line}`));
|
|
1928
|
+
return lines;
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Handle array schemas
|
|
1932
|
+
*/
|
|
1933
|
+
#array(schema) {
|
|
1934
|
+
const lines = [];
|
|
1935
|
+
lines.push(`**Array items:**`);
|
|
1936
|
+
if (schema.items) {
|
|
1937
|
+
const itemDocs = this.handle(schema.items);
|
|
1938
|
+
lines.push(...itemDocs.map((line) => ` ${line}`));
|
|
1939
|
+
} else {
|
|
1940
|
+
lines.push(` **Type:** \`unknown\``);
|
|
1941
|
+
}
|
|
1942
|
+
if (schema.minItems !== void 0)
|
|
1943
|
+
lines.push(`- Minimum items: ${schema.minItems}`);
|
|
1944
|
+
if (schema.maxItems !== void 0)
|
|
1945
|
+
lines.push(`- Maximum items: ${schema.maxItems}`);
|
|
1946
|
+
if (schema.uniqueItems)
|
|
1947
|
+
lines.push(`- Items must be unique.`);
|
|
1948
|
+
return lines;
|
|
1949
|
+
}
|
|
1950
|
+
#ref($ref) {
|
|
1951
|
+
const schemaName = $ref.split("/").pop() || "object";
|
|
1952
|
+
const resolved = followRef6(this.#spec, $ref);
|
|
1953
|
+
const lines = [
|
|
1954
|
+
`**Type:** [\`${schemaName}\`](#${schemaName.toLowerCase()})`
|
|
1955
|
+
];
|
|
1956
|
+
if (resolved.description) {
|
|
1957
|
+
lines.push(resolved.description);
|
|
1958
|
+
}
|
|
1959
|
+
return lines;
|
|
1960
|
+
}
|
|
1961
|
+
#allOf(schemas) {
|
|
1962
|
+
const lines = ["**All of (Intersection):**"];
|
|
1963
|
+
schemas.forEach((subSchema, index) => {
|
|
1964
|
+
lines.push(`- **Constraint ${index + 1}:**`);
|
|
1965
|
+
const subLines = this.handle(subSchema);
|
|
1966
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1967
|
+
});
|
|
1968
|
+
return lines;
|
|
1969
|
+
}
|
|
1970
|
+
#anyOf(schemas) {
|
|
1971
|
+
const lines = ["**Any of (Union):**"];
|
|
1972
|
+
schemas.forEach((subSchema, index) => {
|
|
1973
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
1974
|
+
const subLines = this.handle(subSchema);
|
|
1975
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1976
|
+
});
|
|
1977
|
+
return lines;
|
|
1978
|
+
}
|
|
1979
|
+
#oneOf(schemas) {
|
|
1980
|
+
const lines = ["**One of (Exclusive Union):**"];
|
|
1981
|
+
schemas.forEach((subSchema, index) => {
|
|
1982
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
1983
|
+
const subLines = this.handle(subSchema);
|
|
1984
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1985
|
+
});
|
|
1986
|
+
return lines;
|
|
1987
|
+
}
|
|
1988
|
+
#enum(schema) {
|
|
1989
|
+
const lines = [`**Type:** \`${schema.type || "unknown"}\` (enum)`];
|
|
1990
|
+
if (schema.description)
|
|
1991
|
+
lines.push(schema.description);
|
|
1992
|
+
lines.push("**Allowed values:**");
|
|
1993
|
+
lines.push(
|
|
1994
|
+
...(schema.enum || []).map((val) => `- \`${JSON.stringify(val)}\``)
|
|
1995
|
+
);
|
|
1996
|
+
if (schema.default !== void 0) {
|
|
1997
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
1998
|
+
}
|
|
1999
|
+
return lines;
|
|
2000
|
+
}
|
|
2001
|
+
#normal(type, schema, nullable) {
|
|
2002
|
+
const lines = [];
|
|
2003
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
2004
|
+
const description = schema.description ? [schema.description] : [];
|
|
2005
|
+
switch (type) {
|
|
2006
|
+
case "string":
|
|
2007
|
+
lines.push(
|
|
2008
|
+
`**Type:** \`string\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
2009
|
+
);
|
|
2010
|
+
lines.push(...description);
|
|
2011
|
+
if (schema.minLength !== void 0)
|
|
2012
|
+
lines.push(`- Minimum length: ${schema.minLength}`);
|
|
2013
|
+
if (schema.maxLength !== void 0)
|
|
2014
|
+
lines.push(`- Maximum length: ${schema.maxLength}`);
|
|
2015
|
+
if (schema.pattern !== void 0)
|
|
2016
|
+
lines.push(`- Pattern: \`${schema.pattern}\``);
|
|
2017
|
+
break;
|
|
2018
|
+
case "number":
|
|
2019
|
+
case "integer":
|
|
2020
|
+
lines.push(
|
|
2021
|
+
`**Type:** \`${type}\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
2022
|
+
);
|
|
2023
|
+
lines.push(...description);
|
|
2024
|
+
if (schema.minimum !== void 0) {
|
|
2025
|
+
const exclusiveMin = typeof schema.exclusiveMinimum === "number";
|
|
2026
|
+
lines.push(
|
|
2027
|
+
`- Minimum: ${schema.minimum}${exclusiveMin ? " (exclusive)" : ""}`
|
|
2028
|
+
);
|
|
2029
|
+
if (exclusiveMin) {
|
|
2030
|
+
lines.push(
|
|
2031
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
2032
|
+
);
|
|
2033
|
+
}
|
|
2034
|
+
} else if (typeof schema.exclusiveMinimum === "number") {
|
|
2035
|
+
lines.push(
|
|
2036
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
if (schema.maximum !== void 0) {
|
|
2040
|
+
const exclusiveMax = typeof schema.exclusiveMaximum === "number";
|
|
2041
|
+
lines.push(
|
|
2042
|
+
`- Maximum: ${schema.maximum}${exclusiveMax ? " (exclusive)" : ""}`
|
|
2043
|
+
);
|
|
2044
|
+
if (exclusiveMax) {
|
|
2045
|
+
lines.push(
|
|
2046
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2049
|
+
} else if (typeof schema.exclusiveMaximum === "number") {
|
|
2050
|
+
lines.push(
|
|
2051
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
if (schema.multipleOf !== void 0)
|
|
2055
|
+
lines.push(`- Must be a multiple of: ${schema.multipleOf}`);
|
|
2056
|
+
break;
|
|
2057
|
+
case "boolean":
|
|
2058
|
+
lines.push(`**Type:** \`boolean\`${nullableSuffix}`);
|
|
2059
|
+
lines.push(...description);
|
|
2060
|
+
break;
|
|
2061
|
+
case "object":
|
|
2062
|
+
lines.push(`**Type:** \`object\`${nullableSuffix}`);
|
|
2063
|
+
lines.push(...description);
|
|
2064
|
+
lines.push(...this.#object(schema));
|
|
2065
|
+
break;
|
|
2066
|
+
case "array":
|
|
2067
|
+
lines.push(`**Type:** \`array\`${nullableSuffix}`);
|
|
2068
|
+
lines.push(...description);
|
|
2069
|
+
lines.push(...this.#array(schema));
|
|
2070
|
+
break;
|
|
2071
|
+
case "null":
|
|
2072
|
+
lines.push(`**Type:** \`null\``);
|
|
2073
|
+
lines.push(...description);
|
|
2074
|
+
break;
|
|
2075
|
+
default:
|
|
2076
|
+
lines.push(`**Type:** \`${type}\`${nullableSuffix}`);
|
|
2077
|
+
lines.push(...description);
|
|
2078
|
+
}
|
|
2079
|
+
if (schema.default !== void 0) {
|
|
2080
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
2081
|
+
}
|
|
2082
|
+
return lines.filter((l) => l);
|
|
2083
|
+
}
|
|
2084
|
+
/**
|
|
2085
|
+
* Handle schemas by resolving references and delegating to appropriate handler
|
|
2086
|
+
*/
|
|
2087
|
+
handle(schemaOrRef) {
|
|
2088
|
+
if (isRef7(schemaOrRef)) {
|
|
2089
|
+
return this.#ref(schemaOrRef.$ref);
|
|
2090
|
+
}
|
|
2091
|
+
const schema = schemaOrRef;
|
|
2092
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
2093
|
+
return this.#allOf(schema.allOf);
|
|
2094
|
+
}
|
|
2095
|
+
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
2096
|
+
return this.#anyOf(schema.anyOf);
|
|
2097
|
+
}
|
|
2098
|
+
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
2099
|
+
return this.#oneOf(schema.oneOf);
|
|
2100
|
+
}
|
|
2101
|
+
if (schema.enum && Array.isArray(schema.enum)) {
|
|
2102
|
+
return this.#enum(schema);
|
|
2103
|
+
}
|
|
2104
|
+
let types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
2105
|
+
let nullable = false;
|
|
2106
|
+
if (types.includes("null")) {
|
|
2107
|
+
nullable = true;
|
|
2108
|
+
types = types.filter((t) => t !== "null");
|
|
2109
|
+
}
|
|
2110
|
+
if (types.length === 0) {
|
|
2111
|
+
if (schema.properties || schema.additionalProperties) {
|
|
2112
|
+
types = ["object"];
|
|
2113
|
+
} else if (schema.items) {
|
|
2114
|
+
types = ["array"];
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
if (types.length === 0) {
|
|
2118
|
+
const lines2 = ["**Type:** `unknown`"];
|
|
2119
|
+
if (schema.description)
|
|
2120
|
+
lines2.push(schema.description);
|
|
2121
|
+
if (schema.default !== void 0)
|
|
2122
|
+
lines2.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
2123
|
+
return lines2;
|
|
2124
|
+
}
|
|
2125
|
+
if (types.length === 1) {
|
|
2126
|
+
return this.#normal(types[0], schema, nullable);
|
|
2127
|
+
}
|
|
2128
|
+
const typeString = types.join(" | ");
|
|
2129
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
2130
|
+
const lines = [`**Type:** \`${typeString}\`${nullableSuffix}`];
|
|
2131
|
+
if (schema.description)
|
|
2132
|
+
lines.push(schema.description);
|
|
2133
|
+
if (schema.default !== void 0)
|
|
2134
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
2135
|
+
return lines;
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* Process a request body and return markdown documentation
|
|
2139
|
+
*/
|
|
2140
|
+
requestBody(requestBody) {
|
|
2141
|
+
if (!requestBody)
|
|
2142
|
+
return [];
|
|
2143
|
+
const resolvedBody = isRef7(requestBody) ? followRef6(this.#spec, requestBody.$ref) : requestBody;
|
|
2144
|
+
const lines = [];
|
|
2145
|
+
lines.push(`##### Request Body`);
|
|
2146
|
+
if (resolvedBody.description) {
|
|
2147
|
+
lines.push(resolvedBody.description);
|
|
2148
|
+
}
|
|
2149
|
+
if (resolvedBody.required) {
|
|
2150
|
+
lines.push(`*This request body is required.*`);
|
|
2151
|
+
}
|
|
2152
|
+
if (resolvedBody.content) {
|
|
2153
|
+
for (const [contentType, mediaType] of Object.entries(
|
|
2154
|
+
resolvedBody.content
|
|
2155
|
+
)) {
|
|
2156
|
+
lines.push(`**Content Type:** \`${contentType}\``);
|
|
2157
|
+
if (mediaType.schema) {
|
|
2158
|
+
const schemaDocs = this.handle(mediaType.schema);
|
|
2159
|
+
lines.push(...schemaDocs);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
return lines;
|
|
2164
|
+
}
|
|
2165
|
+
};
|
|
2166
|
+
function toReadme(spec) {
|
|
2167
|
+
const markdown = [];
|
|
2168
|
+
const propEmitter = new PropEmitter(spec);
|
|
2169
|
+
forEachOperation({ spec }, ({ method, path, name }, operation) => {
|
|
2170
|
+
spec.components ??= {};
|
|
2171
|
+
spec.components.schemas ??= {};
|
|
2172
|
+
const statuses = [];
|
|
2173
|
+
markdown.push(
|
|
2174
|
+
`#### ${name || operation.operationId} | ${`_${method.toUpperCase()} ${path}_`}`
|
|
2175
|
+
);
|
|
2176
|
+
markdown.push(operation.summary || "");
|
|
2177
|
+
const requestBodyContent = propEmitter.requestBody(operation.requestBody);
|
|
2178
|
+
if (requestBodyContent.length > 1) {
|
|
2179
|
+
markdown.push(requestBodyContent.join("\n\n"));
|
|
2180
|
+
}
|
|
2181
|
+
markdown.push(`##### Responses`);
|
|
2182
|
+
for (const status in operation.responses) {
|
|
2183
|
+
const response = operation.responses[status];
|
|
2184
|
+
const resolvedResponse = isRef7(response) ? followRef6(spec, response.$ref) : response;
|
|
2185
|
+
statuses.push(`**${status}** _${resolvedResponse.description}_`);
|
|
2186
|
+
}
|
|
2187
|
+
markdown.push(`<small>${statuses.join("\n\n")}</small>`);
|
|
2188
|
+
});
|
|
2189
|
+
return markdown.join("\n\n");
|
|
2190
|
+
}
|
|
2191
|
+
|
|
1915
2192
|
// packages/typescript/src/lib/generate.ts
|
|
1916
2193
|
function security(spec) {
|
|
1917
2194
|
const security2 = spec.security || [];
|
|
@@ -1956,13 +2233,14 @@ async function generate(spec, settings) {
|
|
|
1956
2233
|
);
|
|
1957
2234
|
const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
|
|
1958
2235
|
const options = security(spec);
|
|
1959
|
-
const clientName = settings.name
|
|
2236
|
+
const clientName = settings.name?.trim() ? pascalcase3(settings.name) : "Client";
|
|
2237
|
+
const readme = settings.readme ? toReadme(spec) : "";
|
|
1960
2238
|
const inputFiles = generateInputs(groups, commonZod, makeImport);
|
|
2239
|
+
console.log("Writing to", output);
|
|
1961
2240
|
await writeFiles(output, {
|
|
1962
2241
|
"outputs/.gitkeep": "",
|
|
1963
2242
|
"inputs/.gitkeep": "",
|
|
1964
2243
|
"models/.getkeep": ""
|
|
1965
|
-
// 'README.md': readme,
|
|
1966
2244
|
});
|
|
1967
2245
|
await writeFiles(join2(output, "http"), {
|
|
1968
2246
|
"interceptors.ts": `
|
|
@@ -2041,7 +2319,7 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2041
2319
|
"index.ts": await getFolderExports(output, settings.useTsExtension, ["ts"])
|
|
2042
2320
|
});
|
|
2043
2321
|
if (settings.mode === "full") {
|
|
2044
|
-
|
|
2322
|
+
const configFiles = {
|
|
2045
2323
|
"package.json": {
|
|
2046
2324
|
ignoreIfExists: true,
|
|
2047
2325
|
content: JSON.stringify(
|
|
@@ -2080,7 +2358,14 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2080
2358
|
2
|
|
2081
2359
|
)
|
|
2082
2360
|
}
|
|
2083
|
-
}
|
|
2361
|
+
};
|
|
2362
|
+
if (readme) {
|
|
2363
|
+
configFiles["README.md"] = {
|
|
2364
|
+
ignoreIfExists: true,
|
|
2365
|
+
content: readme
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
await writeFiles(settings.output, configFiles);
|
|
2084
2369
|
}
|
|
2085
2370
|
await settings.formatCode?.({
|
|
2086
2371
|
output,
|