@sdk-it/typescript 0.20.0 → 0.21.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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2072 -541
- package/dist/index.js.map +4 -4
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/emitters/interface.d.ts +1 -1
- package/dist/lib/emitters/interface.d.ts.map +1 -1
- package/dist/lib/emitters/snippet.d.ts +24 -0
- package/dist/lib/emitters/snippet.d.ts.map +1 -0
- 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 +6 -18
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/generator.d.ts +2 -4
- package/dist/lib/generator.d.ts.map +1 -1
- package/dist/lib/options.d.ts +27 -0
- package/dist/lib/options.d.ts.map +1 -0
- package/dist/lib/sdk.d.ts +5 -2
- package/dist/lib/sdk.d.ts.map +1 -1
- package/dist/lib/style.d.ts +2 -1
- package/dist/lib/style.d.ts.map +1 -1
- package/dist/lib/typescript-snippet.d.ts +17 -0
- package/dist/lib/typescript-snippet.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +2 -2
- package/dist/lib/utils.d.ts.map +1 -1
- package/package.json +4 -3
- package/dist/lib/readme.d.ts +0 -19
- package/dist/lib/readme.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,156 +1,1315 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined")
|
|
11
|
+
return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
14
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
15
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
33
|
+
|
|
34
|
+
// node_modules/pluralize/pluralize.js
|
|
35
|
+
var require_pluralize = __commonJS({
|
|
36
|
+
"node_modules/pluralize/pluralize.js"(exports, module) {
|
|
37
|
+
"use strict";
|
|
38
|
+
(function(root, pluralize3) {
|
|
39
|
+
if (typeof __require === "function" && typeof exports === "object" && typeof module === "object") {
|
|
40
|
+
module.exports = pluralize3();
|
|
41
|
+
} else if (typeof define === "function" && define.amd) {
|
|
42
|
+
define(function() {
|
|
43
|
+
return pluralize3();
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
root.pluralize = pluralize3();
|
|
47
|
+
}
|
|
48
|
+
})(exports, function() {
|
|
49
|
+
var pluralRules = [];
|
|
50
|
+
var singularRules = [];
|
|
51
|
+
var uncountables = {};
|
|
52
|
+
var irregularPlurals = {};
|
|
53
|
+
var irregularSingles = {};
|
|
54
|
+
function sanitizeRule(rule) {
|
|
55
|
+
if (typeof rule === "string") {
|
|
56
|
+
return new RegExp("^" + rule + "$", "i");
|
|
57
|
+
}
|
|
58
|
+
return rule;
|
|
59
|
+
}
|
|
60
|
+
function restoreCase(word, token) {
|
|
61
|
+
if (word === token)
|
|
62
|
+
return token;
|
|
63
|
+
if (word === word.toLowerCase())
|
|
64
|
+
return token.toLowerCase();
|
|
65
|
+
if (word === word.toUpperCase())
|
|
66
|
+
return token.toUpperCase();
|
|
67
|
+
if (word[0] === word[0].toUpperCase()) {
|
|
68
|
+
return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
|
|
69
|
+
}
|
|
70
|
+
return token.toLowerCase();
|
|
71
|
+
}
|
|
72
|
+
function interpolate(str, args) {
|
|
73
|
+
return str.replace(/\$(\d{1,2})/g, function(match, index) {
|
|
74
|
+
return args[index] || "";
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function replace(word, rule) {
|
|
78
|
+
return word.replace(rule[0], function(match, index) {
|
|
79
|
+
var result = interpolate(rule[1], arguments);
|
|
80
|
+
if (match === "") {
|
|
81
|
+
return restoreCase(word[index - 1], result);
|
|
82
|
+
}
|
|
83
|
+
return restoreCase(match, result);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function sanitizeWord(token, word, rules) {
|
|
87
|
+
if (!token.length || uncountables.hasOwnProperty(token)) {
|
|
88
|
+
return word;
|
|
89
|
+
}
|
|
90
|
+
var len = rules.length;
|
|
91
|
+
while (len--) {
|
|
92
|
+
var rule = rules[len];
|
|
93
|
+
if (rule[0].test(word))
|
|
94
|
+
return replace(word, rule);
|
|
95
|
+
}
|
|
96
|
+
return word;
|
|
97
|
+
}
|
|
98
|
+
function replaceWord(replaceMap, keepMap, rules) {
|
|
99
|
+
return function(word) {
|
|
100
|
+
var token = word.toLowerCase();
|
|
101
|
+
if (keepMap.hasOwnProperty(token)) {
|
|
102
|
+
return restoreCase(word, token);
|
|
103
|
+
}
|
|
104
|
+
if (replaceMap.hasOwnProperty(token)) {
|
|
105
|
+
return restoreCase(word, replaceMap[token]);
|
|
106
|
+
}
|
|
107
|
+
return sanitizeWord(token, word, rules);
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function checkWord(replaceMap, keepMap, rules, bool) {
|
|
111
|
+
return function(word) {
|
|
112
|
+
var token = word.toLowerCase();
|
|
113
|
+
if (keepMap.hasOwnProperty(token))
|
|
114
|
+
return true;
|
|
115
|
+
if (replaceMap.hasOwnProperty(token))
|
|
116
|
+
return false;
|
|
117
|
+
return sanitizeWord(token, token, rules) === token;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function pluralize3(word, count, inclusive) {
|
|
121
|
+
var pluralized = count === 1 ? pluralize3.singular(word) : pluralize3.plural(word);
|
|
122
|
+
return (inclusive ? count + " " : "") + pluralized;
|
|
123
|
+
}
|
|
124
|
+
pluralize3.plural = replaceWord(
|
|
125
|
+
irregularSingles,
|
|
126
|
+
irregularPlurals,
|
|
127
|
+
pluralRules
|
|
128
|
+
);
|
|
129
|
+
pluralize3.isPlural = checkWord(
|
|
130
|
+
irregularSingles,
|
|
131
|
+
irregularPlurals,
|
|
132
|
+
pluralRules
|
|
133
|
+
);
|
|
134
|
+
pluralize3.singular = replaceWord(
|
|
135
|
+
irregularPlurals,
|
|
136
|
+
irregularSingles,
|
|
137
|
+
singularRules
|
|
138
|
+
);
|
|
139
|
+
pluralize3.isSingular = checkWord(
|
|
140
|
+
irregularPlurals,
|
|
141
|
+
irregularSingles,
|
|
142
|
+
singularRules
|
|
143
|
+
);
|
|
144
|
+
pluralize3.addPluralRule = function(rule, replacement) {
|
|
145
|
+
pluralRules.push([sanitizeRule(rule), replacement]);
|
|
146
|
+
};
|
|
147
|
+
pluralize3.addSingularRule = function(rule, replacement) {
|
|
148
|
+
singularRules.push([sanitizeRule(rule), replacement]);
|
|
149
|
+
};
|
|
150
|
+
pluralize3.addUncountableRule = function(word) {
|
|
151
|
+
if (typeof word === "string") {
|
|
152
|
+
uncountables[word.toLowerCase()] = true;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
pluralize3.addPluralRule(word, "$0");
|
|
156
|
+
pluralize3.addSingularRule(word, "$0");
|
|
157
|
+
};
|
|
158
|
+
pluralize3.addIrregularRule = function(single, plural) {
|
|
159
|
+
plural = plural.toLowerCase();
|
|
160
|
+
single = single.toLowerCase();
|
|
161
|
+
irregularSingles[single] = plural;
|
|
162
|
+
irregularPlurals[plural] = single;
|
|
163
|
+
};
|
|
164
|
+
[
|
|
165
|
+
// Pronouns.
|
|
166
|
+
["I", "we"],
|
|
167
|
+
["me", "us"],
|
|
168
|
+
["he", "they"],
|
|
169
|
+
["she", "they"],
|
|
170
|
+
["them", "them"],
|
|
171
|
+
["myself", "ourselves"],
|
|
172
|
+
["yourself", "yourselves"],
|
|
173
|
+
["itself", "themselves"],
|
|
174
|
+
["herself", "themselves"],
|
|
175
|
+
["himself", "themselves"],
|
|
176
|
+
["themself", "themselves"],
|
|
177
|
+
["is", "are"],
|
|
178
|
+
["was", "were"],
|
|
179
|
+
["has", "have"],
|
|
180
|
+
["this", "these"],
|
|
181
|
+
["that", "those"],
|
|
182
|
+
// Words ending in with a consonant and `o`.
|
|
183
|
+
["echo", "echoes"],
|
|
184
|
+
["dingo", "dingoes"],
|
|
185
|
+
["volcano", "volcanoes"],
|
|
186
|
+
["tornado", "tornadoes"],
|
|
187
|
+
["torpedo", "torpedoes"],
|
|
188
|
+
// Ends with `us`.
|
|
189
|
+
["genus", "genera"],
|
|
190
|
+
["viscus", "viscera"],
|
|
191
|
+
// Ends with `ma`.
|
|
192
|
+
["stigma", "stigmata"],
|
|
193
|
+
["stoma", "stomata"],
|
|
194
|
+
["dogma", "dogmata"],
|
|
195
|
+
["lemma", "lemmata"],
|
|
196
|
+
["schema", "schemata"],
|
|
197
|
+
["anathema", "anathemata"],
|
|
198
|
+
// Other irregular rules.
|
|
199
|
+
["ox", "oxen"],
|
|
200
|
+
["axe", "axes"],
|
|
201
|
+
["die", "dice"],
|
|
202
|
+
["yes", "yeses"],
|
|
203
|
+
["foot", "feet"],
|
|
204
|
+
["eave", "eaves"],
|
|
205
|
+
["goose", "geese"],
|
|
206
|
+
["tooth", "teeth"],
|
|
207
|
+
["quiz", "quizzes"],
|
|
208
|
+
["human", "humans"],
|
|
209
|
+
["proof", "proofs"],
|
|
210
|
+
["carve", "carves"],
|
|
211
|
+
["valve", "valves"],
|
|
212
|
+
["looey", "looies"],
|
|
213
|
+
["thief", "thieves"],
|
|
214
|
+
["groove", "grooves"],
|
|
215
|
+
["pickaxe", "pickaxes"],
|
|
216
|
+
["passerby", "passersby"]
|
|
217
|
+
].forEach(function(rule) {
|
|
218
|
+
return pluralize3.addIrregularRule(rule[0], rule[1]);
|
|
219
|
+
});
|
|
220
|
+
[
|
|
221
|
+
[/s?$/i, "s"],
|
|
222
|
+
[/[^\u0000-\u007F]$/i, "$0"],
|
|
223
|
+
[/([^aeiou]ese)$/i, "$1"],
|
|
224
|
+
[/(ax|test)is$/i, "$1es"],
|
|
225
|
+
[/(alias|[^aou]us|t[lm]as|gas|ris)$/i, "$1es"],
|
|
226
|
+
[/(e[mn]u)s?$/i, "$1s"],
|
|
227
|
+
[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, "$1"],
|
|
228
|
+
[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1i"],
|
|
229
|
+
[/(alumn|alg|vertebr)(?:a|ae)$/i, "$1ae"],
|
|
230
|
+
[/(seraph|cherub)(?:im)?$/i, "$1im"],
|
|
231
|
+
[/(her|at|gr)o$/i, "$1oes"],
|
|
232
|
+
[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, "$1a"],
|
|
233
|
+
[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, "$1a"],
|
|
234
|
+
[/sis$/i, "ses"],
|
|
235
|
+
[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, "$1$2ves"],
|
|
236
|
+
[/([^aeiouy]|qu)y$/i, "$1ies"],
|
|
237
|
+
[/([^ch][ieo][ln])ey$/i, "$1ies"],
|
|
238
|
+
[/(x|ch|ss|sh|zz)$/i, "$1es"],
|
|
239
|
+
[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, "$1ices"],
|
|
240
|
+
[/\b((?:tit)?m|l)(?:ice|ouse)$/i, "$1ice"],
|
|
241
|
+
[/(pe)(?:rson|ople)$/i, "$1ople"],
|
|
242
|
+
[/(child)(?:ren)?$/i, "$1ren"],
|
|
243
|
+
[/eaux$/i, "$0"],
|
|
244
|
+
[/m[ae]n$/i, "men"],
|
|
245
|
+
["thou", "you"]
|
|
246
|
+
].forEach(function(rule) {
|
|
247
|
+
return pluralize3.addPluralRule(rule[0], rule[1]);
|
|
248
|
+
});
|
|
249
|
+
[
|
|
250
|
+
[/s$/i, ""],
|
|
251
|
+
[/(ss)$/i, "$1"],
|
|
252
|
+
[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, "$1fe"],
|
|
253
|
+
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, "$1f"],
|
|
254
|
+
[/ies$/i, "y"],
|
|
255
|
+
[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, "$1ie"],
|
|
256
|
+
[/\b(mon|smil)ies$/i, "$1ey"],
|
|
257
|
+
[/\b((?:tit)?m|l)ice$/i, "$1ouse"],
|
|
258
|
+
[/(seraph|cherub)im$/i, "$1"],
|
|
259
|
+
[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, "$1"],
|
|
260
|
+
[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, "$1sis"],
|
|
261
|
+
[/(movie|twelve|abuse|e[mn]u)s$/i, "$1"],
|
|
262
|
+
[/(test)(?:is|es)$/i, "$1is"],
|
|
263
|
+
[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1us"],
|
|
264
|
+
[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, "$1um"],
|
|
265
|
+
[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, "$1on"],
|
|
266
|
+
[/(alumn|alg|vertebr)ae$/i, "$1a"],
|
|
267
|
+
[/(cod|mur|sil|vert|ind)ices$/i, "$1ex"],
|
|
268
|
+
[/(matr|append)ices$/i, "$1ix"],
|
|
269
|
+
[/(pe)(rson|ople)$/i, "$1rson"],
|
|
270
|
+
[/(child)ren$/i, "$1"],
|
|
271
|
+
[/(eau)x?$/i, "$1"],
|
|
272
|
+
[/men$/i, "man"]
|
|
273
|
+
].forEach(function(rule) {
|
|
274
|
+
return pluralize3.addSingularRule(rule[0], rule[1]);
|
|
275
|
+
});
|
|
276
|
+
[
|
|
277
|
+
// Singular words with no plurals.
|
|
278
|
+
"adulthood",
|
|
279
|
+
"advice",
|
|
280
|
+
"agenda",
|
|
281
|
+
"aid",
|
|
282
|
+
"aircraft",
|
|
283
|
+
"alcohol",
|
|
284
|
+
"ammo",
|
|
285
|
+
"analytics",
|
|
286
|
+
"anime",
|
|
287
|
+
"athletics",
|
|
288
|
+
"audio",
|
|
289
|
+
"bison",
|
|
290
|
+
"blood",
|
|
291
|
+
"bream",
|
|
292
|
+
"buffalo",
|
|
293
|
+
"butter",
|
|
294
|
+
"carp",
|
|
295
|
+
"cash",
|
|
296
|
+
"chassis",
|
|
297
|
+
"chess",
|
|
298
|
+
"clothing",
|
|
299
|
+
"cod",
|
|
300
|
+
"commerce",
|
|
301
|
+
"cooperation",
|
|
302
|
+
"corps",
|
|
303
|
+
"debris",
|
|
304
|
+
"diabetes",
|
|
305
|
+
"digestion",
|
|
306
|
+
"elk",
|
|
307
|
+
"energy",
|
|
308
|
+
"equipment",
|
|
309
|
+
"excretion",
|
|
310
|
+
"expertise",
|
|
311
|
+
"firmware",
|
|
312
|
+
"flounder",
|
|
313
|
+
"fun",
|
|
314
|
+
"gallows",
|
|
315
|
+
"garbage",
|
|
316
|
+
"graffiti",
|
|
317
|
+
"hardware",
|
|
318
|
+
"headquarters",
|
|
319
|
+
"health",
|
|
320
|
+
"herpes",
|
|
321
|
+
"highjinks",
|
|
322
|
+
"homework",
|
|
323
|
+
"housework",
|
|
324
|
+
"information",
|
|
325
|
+
"jeans",
|
|
326
|
+
"justice",
|
|
327
|
+
"kudos",
|
|
328
|
+
"labour",
|
|
329
|
+
"literature",
|
|
330
|
+
"machinery",
|
|
331
|
+
"mackerel",
|
|
332
|
+
"mail",
|
|
333
|
+
"media",
|
|
334
|
+
"mews",
|
|
335
|
+
"moose",
|
|
336
|
+
"music",
|
|
337
|
+
"mud",
|
|
338
|
+
"manga",
|
|
339
|
+
"news",
|
|
340
|
+
"only",
|
|
341
|
+
"personnel",
|
|
342
|
+
"pike",
|
|
343
|
+
"plankton",
|
|
344
|
+
"pliers",
|
|
345
|
+
"police",
|
|
346
|
+
"pollution",
|
|
347
|
+
"premises",
|
|
348
|
+
"rain",
|
|
349
|
+
"research",
|
|
350
|
+
"rice",
|
|
351
|
+
"salmon",
|
|
352
|
+
"scissors",
|
|
353
|
+
"series",
|
|
354
|
+
"sewage",
|
|
355
|
+
"shambles",
|
|
356
|
+
"shrimp",
|
|
357
|
+
"software",
|
|
358
|
+
"species",
|
|
359
|
+
"staff",
|
|
360
|
+
"swine",
|
|
361
|
+
"tennis",
|
|
362
|
+
"traffic",
|
|
363
|
+
"transportation",
|
|
364
|
+
"trout",
|
|
365
|
+
"tuna",
|
|
366
|
+
"wealth",
|
|
367
|
+
"welfare",
|
|
368
|
+
"whiting",
|
|
369
|
+
"wildebeest",
|
|
370
|
+
"wildlife",
|
|
371
|
+
"you",
|
|
372
|
+
/pok[eé]mon$/i,
|
|
373
|
+
// Regexes.
|
|
374
|
+
/[^aeiou]ese$/i,
|
|
375
|
+
// "chinese", "japanese"
|
|
376
|
+
/deer$/i,
|
|
377
|
+
// "deer", "reindeer"
|
|
378
|
+
/fish$/i,
|
|
379
|
+
// "fish", "blowfish", "angelfish"
|
|
380
|
+
/measles$/i,
|
|
381
|
+
/o[iu]s$/i,
|
|
382
|
+
// "carnivorous"
|
|
383
|
+
/pox$/i,
|
|
384
|
+
// "chickpox", "smallpox"
|
|
385
|
+
/sheep$/i
|
|
386
|
+
].forEach(pluralize3.addUncountableRule);
|
|
387
|
+
return pluralize3;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
1
392
|
// packages/typescript/src/lib/generate.ts
|
|
2
393
|
import { template as template2 } from "lodash-es";
|
|
3
|
-
import {
|
|
394
|
+
import { readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
|
395
|
+
import { join as join2, relative, sep } from "node:path";
|
|
4
396
|
import { npmRunPathEnv } from "npm-run-path";
|
|
5
|
-
import { spinalcase as
|
|
6
|
-
import { methods, pascalcase as
|
|
397
|
+
import { spinalcase as spinalcase4 } from "stringcase";
|
|
398
|
+
import { methods, pascalcase as pascalcase4 } from "@sdk-it/core";
|
|
7
399
|
import {
|
|
400
|
+
addLeadingSlash,
|
|
401
|
+
exist,
|
|
8
402
|
getFolderExports,
|
|
403
|
+
readFolder,
|
|
9
404
|
writeFiles
|
|
10
405
|
} from "@sdk-it/core/file-system.js";
|
|
11
406
|
|
|
12
|
-
// packages/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
407
|
+
// packages/readme/dist/index.js
|
|
408
|
+
var import_pluralize = __toESM(require_pluralize(), 1);
|
|
409
|
+
import { isEmpty as isEmpty2 } from "@sdk-it/core";
|
|
410
|
+
import { camelcase } from "stringcase";
|
|
411
|
+
import { followRef, isRef as isRef2 } from "@sdk-it/core/ref.js";
|
|
412
|
+
import { isRef } from "@sdk-it/core/ref.js";
|
|
413
|
+
import { isEmpty } from "@sdk-it/core/utils.js";
|
|
414
|
+
import { followRef as followRef2, isRef as isRef3 } from "@sdk-it/core";
|
|
415
|
+
var HAS_MORE_POSITIVE_REGEX_PATTERNS = [
|
|
416
|
+
"\\bhas_?more\\b",
|
|
417
|
+
"\\bhas_?next\\b",
|
|
418
|
+
// e.g., itemsHasNext, items_has_next
|
|
419
|
+
"\\bmore_?items\\b",
|
|
420
|
+
"\\bnext_?page\\b",
|
|
421
|
+
// e.g., userNextPageFlag
|
|
422
|
+
"\\badditional\\b",
|
|
423
|
+
// e.g., hasAdditionalData, additional_results_exist
|
|
424
|
+
"\\bcontinuation\\b",
|
|
425
|
+
// e.g., continuationAvailable, has_continuation_token
|
|
426
|
+
"\\bmore_?results\\b",
|
|
427
|
+
"\\bpage_?available\\b",
|
|
428
|
+
"\\bnext(?:_?(page))?\\b"
|
|
429
|
+
];
|
|
430
|
+
var COMPILED_HAS_MORE_POSITIVE_REGEXES = HAS_MORE_POSITIVE_REGEX_PATTERNS.map((p) => new RegExp(p, "i"));
|
|
431
|
+
var HAS_MORE_INVERTED_REGEX_PATTERNS = [
|
|
432
|
+
"\\bis_?last\\b",
|
|
433
|
+
// e.g., pageIsLast
|
|
434
|
+
"\\blast_?page\\b",
|
|
435
|
+
// e.g., resultsAreLastPage
|
|
436
|
+
"\\bend_?of_?(data|results|list|items|stream)\\b",
|
|
437
|
+
"\\bno_?more_?(items|data|results)?\\b",
|
|
438
|
+
"\\ball_?(items_?)?loaded\\b",
|
|
439
|
+
"\\bis_?complete\\b"
|
|
440
|
+
];
|
|
441
|
+
var COMPILED_HAS_MORE_INVERTED_REGEXES = HAS_MORE_INVERTED_REGEX_PATTERNS.map((p) => new RegExp(p, "i"));
|
|
442
|
+
function forEachOperation(config, callback) {
|
|
443
|
+
const result = [];
|
|
444
|
+
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
445
|
+
const { parameters = [], ...methods2 } = pathItem;
|
|
446
|
+
for (const [method, operation] of Object.entries(methods2)) {
|
|
447
|
+
const metadata = operation["x-oaiMeta"] ?? {};
|
|
448
|
+
const operationTag = operation.tags?.[0];
|
|
449
|
+
result.push(
|
|
450
|
+
callback(
|
|
451
|
+
{
|
|
452
|
+
name: metadata.name,
|
|
453
|
+
method,
|
|
454
|
+
path,
|
|
455
|
+
groupName: operationTag,
|
|
456
|
+
tag: operationTag
|
|
457
|
+
},
|
|
458
|
+
operation
|
|
459
|
+
)
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
var PropEmitter = class {
|
|
466
|
+
#spec;
|
|
467
|
+
constructor(spec) {
|
|
468
|
+
this.#spec = spec;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Handle objects (properties)
|
|
472
|
+
*/
|
|
473
|
+
#object(schema) {
|
|
474
|
+
const lines = [];
|
|
475
|
+
const properties = schema.properties || {};
|
|
476
|
+
if (Object.keys(properties).length > 0) {
|
|
477
|
+
lines.push(`**Properties:**`);
|
|
478
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
479
|
+
const isRequired = (schema.required ?? []).includes(propName);
|
|
480
|
+
lines.push(...this.#property(propName, propSchema, isRequired));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (schema.additionalProperties) {
|
|
484
|
+
lines.push(`**Additional Properties:**`);
|
|
485
|
+
if (typeof schema.additionalProperties === "boolean") {
|
|
486
|
+
lines.push(`- Allowed: ${schema.additionalProperties}`);
|
|
487
|
+
} else {
|
|
488
|
+
lines.push(
|
|
489
|
+
...this.handle(schema.additionalProperties).map((l) => ` ${l}`)
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return lines;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Format a property with its type and description
|
|
497
|
+
*/
|
|
498
|
+
#property(name, schema, required) {
|
|
499
|
+
const docs = this.handle(schema);
|
|
500
|
+
const rawType = docs[0].replace("**Type:** ", "").replace(" (nullable)", "|null");
|
|
501
|
+
const defaultVal = !isRef3(schema) && schema.default !== void 0 ? ` default: ${JSON.stringify(schema.default)}` : "";
|
|
502
|
+
const reqMark = required ? " required" : "";
|
|
503
|
+
const summary = `- \`${name}\` ${rawType}${reqMark}${defaultVal}:`;
|
|
504
|
+
const detailLines = docs.slice(1).filter((l) => !l.startsWith("**Default:**")).map((l) => ` ${l}`);
|
|
505
|
+
return [summary, ...detailLines];
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Handle array schemas
|
|
509
|
+
*/
|
|
510
|
+
#array(schema) {
|
|
511
|
+
const lines = [];
|
|
512
|
+
lines.push(`**Array items:**`);
|
|
513
|
+
if (schema.items) {
|
|
514
|
+
const itemDocs = this.handle(schema.items);
|
|
515
|
+
lines.push(...itemDocs.map((line) => ` ${line}`));
|
|
516
|
+
} else {
|
|
517
|
+
lines.push(` **Type:** \`unknown\``);
|
|
518
|
+
}
|
|
519
|
+
if (schema.minItems !== void 0)
|
|
520
|
+
lines.push(`- Minimum items: ${schema.minItems}`);
|
|
521
|
+
if (schema.maxItems !== void 0)
|
|
522
|
+
lines.push(`- Maximum items: ${schema.maxItems}`);
|
|
523
|
+
if (schema.uniqueItems)
|
|
524
|
+
lines.push(`- Items must be unique.`);
|
|
525
|
+
return lines;
|
|
526
|
+
}
|
|
527
|
+
#ref($ref) {
|
|
528
|
+
const schemaName = $ref.split("/").pop() || "object";
|
|
529
|
+
const resolved = followRef2(this.#spec, $ref);
|
|
530
|
+
const lines = [
|
|
531
|
+
`**Type:** [\`${schemaName}\`](#${schemaName.toLowerCase()})`
|
|
532
|
+
];
|
|
533
|
+
if (resolved.description) {
|
|
534
|
+
lines.push(resolved.description);
|
|
535
|
+
}
|
|
536
|
+
return lines;
|
|
537
|
+
}
|
|
538
|
+
#allOf(schemas) {
|
|
539
|
+
const lines = ["**All of (Intersection):**"];
|
|
540
|
+
schemas.forEach((subSchema, index) => {
|
|
541
|
+
lines.push(`- **Constraint ${index + 1}:**`);
|
|
542
|
+
const subLines = this.handle(subSchema);
|
|
543
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
544
|
+
});
|
|
545
|
+
return lines;
|
|
546
|
+
}
|
|
547
|
+
#anyOf(schemas) {
|
|
548
|
+
const lines = ["**Any of (Union):**"];
|
|
549
|
+
schemas.forEach((subSchema, index) => {
|
|
550
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
551
|
+
const subLines = this.handle(subSchema);
|
|
552
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
553
|
+
});
|
|
554
|
+
return lines;
|
|
555
|
+
}
|
|
556
|
+
#oneOf(schemas) {
|
|
557
|
+
const lines = ["**One of (Exclusive Union):**"];
|
|
558
|
+
schemas.forEach((subSchema, index) => {
|
|
559
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
560
|
+
const subLines = this.handle(subSchema);
|
|
561
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
562
|
+
});
|
|
563
|
+
return lines;
|
|
564
|
+
}
|
|
565
|
+
#enum(schema) {
|
|
566
|
+
const lines = [`**Type:** \`${schema.type || "unknown"}\` (enum)`];
|
|
567
|
+
if (schema.description)
|
|
568
|
+
lines.push(schema.description);
|
|
569
|
+
lines.push("**Allowed values:**");
|
|
570
|
+
lines.push(
|
|
571
|
+
...(schema.enum || []).map((val) => `- \`${JSON.stringify(val)}\``)
|
|
572
|
+
);
|
|
573
|
+
if (schema.default !== void 0) {
|
|
574
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
575
|
+
}
|
|
576
|
+
return lines;
|
|
577
|
+
}
|
|
578
|
+
#normal(type, schema, nullable) {
|
|
579
|
+
const lines = [];
|
|
580
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
581
|
+
const description = schema.description ? [schema.description] : [];
|
|
582
|
+
switch (type) {
|
|
583
|
+
case "string":
|
|
584
|
+
lines.push(
|
|
585
|
+
`**Type:** \`string\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
586
|
+
);
|
|
587
|
+
lines.push(...description);
|
|
588
|
+
if (schema.minLength !== void 0)
|
|
589
|
+
lines.push(`- Minimum length: ${schema.minLength}`);
|
|
590
|
+
if (schema.maxLength !== void 0)
|
|
591
|
+
lines.push(`- Maximum length: ${schema.maxLength}`);
|
|
592
|
+
if (schema.pattern !== void 0)
|
|
593
|
+
lines.push(`- Pattern: \`${schema.pattern}\``);
|
|
594
|
+
break;
|
|
595
|
+
case "number":
|
|
596
|
+
case "integer":
|
|
597
|
+
lines.push(
|
|
598
|
+
`**Type:** \`${type}\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
599
|
+
);
|
|
600
|
+
lines.push(...description);
|
|
601
|
+
if (schema.minimum !== void 0) {
|
|
602
|
+
const exclusiveMin = typeof schema.exclusiveMinimum === "number";
|
|
603
|
+
lines.push(
|
|
604
|
+
`- Minimum: ${schema.minimum}${exclusiveMin ? " (exclusive)" : ""}`
|
|
605
|
+
);
|
|
606
|
+
if (exclusiveMin) {
|
|
607
|
+
lines.push(
|
|
608
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
} else if (typeof schema.exclusiveMinimum === "number") {
|
|
612
|
+
lines.push(
|
|
613
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
if (schema.maximum !== void 0) {
|
|
617
|
+
const exclusiveMax = typeof schema.exclusiveMaximum === "number";
|
|
618
|
+
lines.push(
|
|
619
|
+
`- Maximum: ${schema.maximum}${exclusiveMax ? " (exclusive)" : ""}`
|
|
620
|
+
);
|
|
621
|
+
if (exclusiveMax) {
|
|
622
|
+
lines.push(
|
|
623
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
} else if (typeof schema.exclusiveMaximum === "number") {
|
|
627
|
+
lines.push(
|
|
628
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
if (schema.multipleOf !== void 0)
|
|
632
|
+
lines.push(`- Must be a multiple of: ${schema.multipleOf}`);
|
|
633
|
+
break;
|
|
634
|
+
case "boolean":
|
|
635
|
+
lines.push(`**Type:** \`boolean\`${nullableSuffix}`);
|
|
636
|
+
lines.push(...description);
|
|
637
|
+
break;
|
|
638
|
+
case "object":
|
|
639
|
+
lines.push(`**Type:** \`object\`${nullableSuffix}`);
|
|
640
|
+
lines.push(...description);
|
|
641
|
+
lines.push(...this.#object(schema));
|
|
642
|
+
break;
|
|
643
|
+
case "array":
|
|
644
|
+
lines.push(`**Type:** \`array\`${nullableSuffix}`);
|
|
645
|
+
lines.push(...description);
|
|
646
|
+
lines.push(...this.#array(schema));
|
|
647
|
+
break;
|
|
648
|
+
case "null":
|
|
649
|
+
lines.push(`**Type:** \`null\``);
|
|
650
|
+
lines.push(...description);
|
|
651
|
+
break;
|
|
652
|
+
default:
|
|
653
|
+
lines.push(`**Type:** \`${type}\`${nullableSuffix}`);
|
|
654
|
+
lines.push(...description);
|
|
655
|
+
}
|
|
656
|
+
if (schema.default !== void 0) {
|
|
657
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
658
|
+
}
|
|
659
|
+
return lines.filter((l) => l);
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Handle schemas by resolving references and delegating to appropriate handler
|
|
663
|
+
*/
|
|
664
|
+
handle(schemaOrRef) {
|
|
665
|
+
if (isRef3(schemaOrRef)) {
|
|
666
|
+
return this.#ref(schemaOrRef.$ref);
|
|
667
|
+
}
|
|
668
|
+
const schema = schemaOrRef;
|
|
669
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
670
|
+
return this.#allOf(schema.allOf);
|
|
671
|
+
}
|
|
672
|
+
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
673
|
+
return this.#anyOf(schema.anyOf);
|
|
674
|
+
}
|
|
675
|
+
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
676
|
+
return this.#oneOf(schema.oneOf);
|
|
677
|
+
}
|
|
678
|
+
if (schema.enum && Array.isArray(schema.enum)) {
|
|
679
|
+
return this.#enum(schema);
|
|
680
|
+
}
|
|
681
|
+
let types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
682
|
+
let nullable = false;
|
|
683
|
+
if (types.includes("null")) {
|
|
684
|
+
nullable = true;
|
|
685
|
+
types = types.filter((t) => t !== "null");
|
|
686
|
+
}
|
|
687
|
+
if (types.length === 0) {
|
|
688
|
+
if (schema.properties || schema.additionalProperties) {
|
|
689
|
+
types = ["object"];
|
|
690
|
+
} else if (schema.items) {
|
|
691
|
+
types = ["array"];
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
if (types.length === 0) {
|
|
695
|
+
const lines2 = ["**Type:** `unknown`"];
|
|
696
|
+
if (schema.description)
|
|
697
|
+
lines2.push(schema.description);
|
|
698
|
+
if (schema.default !== void 0)
|
|
699
|
+
lines2.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
700
|
+
return lines2;
|
|
701
|
+
}
|
|
702
|
+
if (types.length === 1) {
|
|
703
|
+
return this.#normal(types[0], schema, nullable);
|
|
704
|
+
}
|
|
705
|
+
const typeString = types.join(" | ");
|
|
706
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
707
|
+
const lines = [`**Type:** \`${typeString}\`${nullableSuffix}`];
|
|
708
|
+
if (schema.description)
|
|
709
|
+
lines.push(schema.description);
|
|
710
|
+
if (schema.default !== void 0)
|
|
711
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
712
|
+
return lines;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Process a request body and return markdown documentation
|
|
716
|
+
*/
|
|
717
|
+
requestBody(requestBody) {
|
|
718
|
+
if (!requestBody)
|
|
719
|
+
return [];
|
|
720
|
+
const lines = [];
|
|
721
|
+
lines.push(`##### Request Body`);
|
|
722
|
+
if (requestBody.description) {
|
|
723
|
+
lines.push(requestBody.description);
|
|
33
724
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});
|
|
50
|
-
${spec.servers.length ? `export type Servers = typeof servers[number];` : ""}
|
|
51
|
-
|
|
52
|
-
type ${spec.name}Options = z.infer<typeof optionsSchema>;
|
|
53
|
-
|
|
54
|
-
export class ${spec.name} {
|
|
55
|
-
public options: ${spec.name}Options
|
|
56
|
-
constructor(options: ${spec.name}Options) {
|
|
57
|
-
this.options = optionsSchema.parse(options);
|
|
725
|
+
if (requestBody.required) {
|
|
726
|
+
lines.push(`*This request body is required.*`);
|
|
727
|
+
}
|
|
728
|
+
if (requestBody.content) {
|
|
729
|
+
for (const [contentType, mediaType] of Object.entries(
|
|
730
|
+
requestBody.content
|
|
731
|
+
)) {
|
|
732
|
+
lines.push(`**Content Type:** \`${contentType}\``);
|
|
733
|
+
if (mediaType.schema) {
|
|
734
|
+
const schemaDocs = this.handle(mediaType.schema);
|
|
735
|
+
lines.push(...schemaDocs);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return lines;
|
|
58
740
|
}
|
|
741
|
+
};
|
|
742
|
+
function toReadme(spec, generators) {
|
|
743
|
+
const markdown = [];
|
|
744
|
+
const propEmitter = new PropEmitter(spec);
|
|
745
|
+
forEachOperation({ spec }, (entry, operation) => {
|
|
746
|
+
const { method, path, name } = entry;
|
|
747
|
+
spec.components ??= {};
|
|
748
|
+
spec.components.schemas ??= {};
|
|
749
|
+
markdown.push(
|
|
750
|
+
`#### ${name || operation.operationId} | ${`_${method.toUpperCase()} ${path}_`}`
|
|
751
|
+
);
|
|
752
|
+
markdown.push(operation.summary || "");
|
|
753
|
+
const snippet = generators.generateSnippet(entry, operation);
|
|
754
|
+
markdown.push(`##### Example usage`);
|
|
755
|
+
markdown.push(snippet);
|
|
756
|
+
const requestBodyContent = propEmitter.requestBody(operation.requestBody);
|
|
757
|
+
if (requestBodyContent.length > 1) {
|
|
758
|
+
markdown.push(requestBodyContent.join("\n\n"));
|
|
759
|
+
}
|
|
760
|
+
markdown.push(`##### Responses`);
|
|
761
|
+
for (const status in operation.responses) {
|
|
762
|
+
const response = operation.responses[status];
|
|
763
|
+
markdown.push(`<details>`);
|
|
764
|
+
markdown.push(
|
|
765
|
+
`<summary><b>${status}</b> <i>${response.description}</i></summary>`
|
|
766
|
+
);
|
|
767
|
+
if (!isEmpty2(response.content)) {
|
|
768
|
+
for (const [contentType, mediaType] of Object.entries(
|
|
769
|
+
response.content
|
|
770
|
+
)) {
|
|
771
|
+
markdown.push(`
|
|
772
|
+
**Content Type:** \`${contentType}\``);
|
|
773
|
+
if (mediaType.schema) {
|
|
774
|
+
const schemaDocs = propEmitter.handle(mediaType.schema);
|
|
775
|
+
markdown.push(...schemaDocs.map((l) => `
|
|
776
|
+
${l}`));
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
markdown.push(`</details>`);
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
return markdown.join("\n\n");
|
|
784
|
+
}
|
|
59
785
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
786
|
+
// packages/spec/dist/lib/operation.js
|
|
787
|
+
import { camelcase as camelcase2 } from "stringcase";
|
|
788
|
+
import { followRef as followRef3, isRef as isRef5 } from "@sdk-it/core/ref.js";
|
|
789
|
+
|
|
790
|
+
// packages/spec/dist/lib/pagination/pagination.js
|
|
791
|
+
import { isRef as isRef4 } from "@sdk-it/core/ref.js";
|
|
792
|
+
import { isEmpty as isEmpty3 } from "@sdk-it/core/utils.js";
|
|
793
|
+
|
|
794
|
+
// packages/spec/dist/lib/pagination/pagination-result.js
|
|
795
|
+
var import_pluralize2 = __toESM(require_pluralize(), 1);
|
|
796
|
+
var PRIMARY_TOP_TIER_KEYWORDS = [
|
|
797
|
+
"data",
|
|
798
|
+
"items",
|
|
799
|
+
"results",
|
|
800
|
+
"value"
|
|
801
|
+
];
|
|
802
|
+
var PRIMARY_OTHER_KEYWORDS = [
|
|
803
|
+
"records",
|
|
804
|
+
"content",
|
|
805
|
+
"list",
|
|
806
|
+
"payload",
|
|
807
|
+
"entities",
|
|
808
|
+
"collection",
|
|
809
|
+
"users",
|
|
810
|
+
"products",
|
|
811
|
+
"orders",
|
|
812
|
+
"bookings",
|
|
813
|
+
"articles",
|
|
814
|
+
"posts",
|
|
815
|
+
"documents",
|
|
816
|
+
"events"
|
|
817
|
+
];
|
|
818
|
+
var SECONDARY_KEYWORDS = ["entries", "rows", "elements"];
|
|
819
|
+
var PLURAL_DEPRIORITIZE_LIST = [
|
|
820
|
+
"status",
|
|
821
|
+
"success",
|
|
822
|
+
"address",
|
|
823
|
+
"details",
|
|
824
|
+
"properties",
|
|
825
|
+
"params",
|
|
826
|
+
"headers",
|
|
827
|
+
"cookies",
|
|
828
|
+
"series",
|
|
829
|
+
"links",
|
|
830
|
+
"meta",
|
|
831
|
+
"metadata",
|
|
832
|
+
"statistics",
|
|
833
|
+
"settings",
|
|
834
|
+
"options",
|
|
835
|
+
"permissions",
|
|
836
|
+
"credentials",
|
|
837
|
+
"diagnostics",
|
|
838
|
+
"warnings",
|
|
839
|
+
"errors",
|
|
840
|
+
"actions",
|
|
841
|
+
"attributes",
|
|
842
|
+
"categories",
|
|
843
|
+
"features",
|
|
844
|
+
"includes",
|
|
845
|
+
"tags"
|
|
846
|
+
];
|
|
847
|
+
var HAS_MORE_PRIMARY_POSITIVE_EXACT = [
|
|
848
|
+
"hasmore",
|
|
849
|
+
"hasnext",
|
|
850
|
+
"hasnextpage",
|
|
851
|
+
"moreitems",
|
|
852
|
+
"moreitemsavailable",
|
|
853
|
+
"nextpage",
|
|
854
|
+
"nextpageexists",
|
|
855
|
+
"nextpageavailable",
|
|
856
|
+
"hasadditionalresults",
|
|
857
|
+
"moreresultsavailable",
|
|
858
|
+
"canloadmore",
|
|
859
|
+
"hasadditional",
|
|
860
|
+
"additionalitems",
|
|
861
|
+
"fetchmore"
|
|
862
|
+
];
|
|
863
|
+
var HAS_MORE_SECONDARY_POSITIVE_EXACT = ["more", "next"];
|
|
864
|
+
var HAS_MORE_PRIMARY_INVERTED_EXACT = [
|
|
865
|
+
"islast",
|
|
866
|
+
"lastpage",
|
|
867
|
+
"endofresults",
|
|
868
|
+
"endoflist",
|
|
869
|
+
"nomoreitems",
|
|
870
|
+
"nomoredata",
|
|
871
|
+
"allitemsloaded",
|
|
872
|
+
"iscomplete",
|
|
873
|
+
"completed"
|
|
874
|
+
];
|
|
875
|
+
var HAS_MORE_POSITIVE_REGEX_PATTERNS2 = [
|
|
876
|
+
"\\bhas_?more\\b",
|
|
877
|
+
"\\bhas_?next\\b",
|
|
878
|
+
// e.g., itemsHasNext, items_has_next
|
|
879
|
+
"\\bmore_?items\\b",
|
|
880
|
+
"\\bnext_?page\\b",
|
|
881
|
+
// e.g., userNextPageFlag
|
|
882
|
+
"\\badditional\\b",
|
|
883
|
+
// e.g., hasAdditionalData, additional_results_exist
|
|
884
|
+
"\\bcontinuation\\b",
|
|
885
|
+
// e.g., continuationAvailable, has_continuation_token
|
|
886
|
+
"\\bmore_?results\\b",
|
|
887
|
+
"\\bpage_?available\\b",
|
|
888
|
+
"\\bnext(?:_?(page))?\\b"
|
|
889
|
+
];
|
|
890
|
+
var COMPILED_HAS_MORE_POSITIVE_REGEXES2 = HAS_MORE_POSITIVE_REGEX_PATTERNS2.map((p) => new RegExp(p, "i"));
|
|
891
|
+
var HAS_MORE_INVERTED_REGEX_PATTERNS2 = [
|
|
892
|
+
"\\bis_?last\\b",
|
|
893
|
+
// e.g., pageIsLast
|
|
894
|
+
"\\blast_?page\\b",
|
|
895
|
+
// e.g., resultsAreLastPage
|
|
896
|
+
"\\bend_?of_?(data|results|list|items|stream)\\b",
|
|
897
|
+
"\\bno_?more_?(items|data|results)?\\b",
|
|
898
|
+
"\\ball_?(items_?)?loaded\\b",
|
|
899
|
+
"\\bis_?complete\\b"
|
|
900
|
+
];
|
|
901
|
+
var COMPILED_HAS_MORE_INVERTED_REGEXES2 = HAS_MORE_INVERTED_REGEX_PATTERNS2.map((p) => new RegExp(p, "i"));
|
|
902
|
+
function getItemsName(properties) {
|
|
903
|
+
const arrayPropertyNames = [];
|
|
904
|
+
for (const propName in properties) {
|
|
905
|
+
if (propName in properties) {
|
|
906
|
+
const propSchema = properties[propName];
|
|
907
|
+
if (propSchema && propSchema.type === "array") {
|
|
908
|
+
arrayPropertyNames.push(propName);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
75
911
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
>` : `Promise<RequestConfig & {
|
|
89
|
-
parse: (response: Response) => ReturnType<typeof parse>;
|
|
90
|
-
}>`} {
|
|
91
|
-
const route = schemas[endpoint];
|
|
92
|
-
|
|
93
|
-
const interceptors = [
|
|
94
|
-
createHeadersInterceptor(
|
|
95
|
-
() => this.defaultHeaders,
|
|
96
|
-
options?.headers ?? {},
|
|
97
|
-
),
|
|
98
|
-
createBaseUrlInterceptor(() => this.options.baseUrl),
|
|
99
|
-
];
|
|
100
|
-
const [parsedInput, parseError] = parseInput(route.schema, input);
|
|
101
|
-
if (parseError) {
|
|
102
|
-
${style.errorAsValue ? "return [null as never, parseError as never] as const;" : "throw parseError;"}
|
|
912
|
+
if (arrayPropertyNames.length === 0) {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
if (arrayPropertyNames.length === 1) {
|
|
916
|
+
return arrayPropertyNames[0];
|
|
917
|
+
}
|
|
918
|
+
let bestCandidate = null;
|
|
919
|
+
let candidateRank = Infinity;
|
|
920
|
+
const updateCandidate = (propName, rank) => {
|
|
921
|
+
if (rank < candidateRank) {
|
|
922
|
+
bestCandidate = propName;
|
|
923
|
+
candidateRank = rank;
|
|
103
924
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
925
|
+
};
|
|
926
|
+
for (const propName of arrayPropertyNames) {
|
|
927
|
+
const lowerPropName = propName.toLowerCase();
|
|
928
|
+
if (PRIMARY_TOP_TIER_KEYWORDS.includes(lowerPropName)) {
|
|
929
|
+
updateCandidate(propName, 2);
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
if (candidateRank > 3 && PRIMARY_OTHER_KEYWORDS.includes(lowerPropName)) {
|
|
933
|
+
updateCandidate(propName, 3);
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
if (candidateRank > 4 && SECONDARY_KEYWORDS.includes(lowerPropName)) {
|
|
937
|
+
updateCandidate(propName, 4);
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
if (candidateRank > 5 && import_pluralize2.default.isPlural(propName) && !PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
|
|
941
|
+
updateCandidate(propName, 5);
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
if (candidateRank > 6 && import_pluralize2.default.isPlural(propName) && PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
|
|
945
|
+
updateCandidate(propName, 6);
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
if (bestCandidate) {
|
|
950
|
+
return bestCandidate;
|
|
951
|
+
}
|
|
952
|
+
return arrayPropertyNames[0];
|
|
953
|
+
}
|
|
954
|
+
function guess(properties) {
|
|
955
|
+
const booleanPropertyNames = [];
|
|
956
|
+
for (const propName in properties) {
|
|
957
|
+
if (Object.prototype.hasOwnProperty.call(properties, propName)) {
|
|
958
|
+
const propSchema = properties[propName];
|
|
959
|
+
if (propSchema && propSchema.type === "boolean" || propSchema.type === "integer") {
|
|
960
|
+
booleanPropertyNames.push(propName);
|
|
109
961
|
}
|
|
110
962
|
}
|
|
111
|
-
const prepared = { ...config, parse: (response: Response) => parse(route, response) };
|
|
112
|
-
return ${style.errorAsValue ? "[prepared, null as never] as const;" : "prepared"}
|
|
113
963
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return ${defaultHeaders}
|
|
964
|
+
if (booleanPropertyNames.length === 0) {
|
|
965
|
+
return null;
|
|
117
966
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return ${defaultInputs}
|
|
967
|
+
if (booleanPropertyNames.length === 1) {
|
|
968
|
+
return booleanPropertyNames[0];
|
|
121
969
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
970
|
+
let bestCandidate = null;
|
|
971
|
+
let candidateRank = Infinity;
|
|
972
|
+
const updateCandidate = (propName, rank) => {
|
|
973
|
+
if (rank < candidateRank) {
|
|
974
|
+
bestCandidate = propName;
|
|
975
|
+
candidateRank = rank;
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
for (const propName of booleanPropertyNames) {
|
|
979
|
+
const normalizedForExactMatch = propName.toLowerCase().replace(/[-_]/g, "");
|
|
980
|
+
let currentPropRank = Infinity;
|
|
981
|
+
if (HAS_MORE_PRIMARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {
|
|
982
|
+
currentPropRank = 1;
|
|
983
|
+
} else if (HAS_MORE_SECONDARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {
|
|
984
|
+
currentPropRank = 2;
|
|
985
|
+
} else {
|
|
986
|
+
let foundPositiveRegex = false;
|
|
987
|
+
for (const regex of COMPILED_HAS_MORE_POSITIVE_REGEXES2) {
|
|
988
|
+
if (regex.test(propName)) {
|
|
989
|
+
currentPropRank = 3;
|
|
990
|
+
foundPositiveRegex = true;
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
if (!foundPositiveRegex) {
|
|
995
|
+
if (HAS_MORE_PRIMARY_INVERTED_EXACT.includes(normalizedForExactMatch)) {
|
|
996
|
+
currentPropRank = 4;
|
|
997
|
+
} else {
|
|
998
|
+
for (const regex of COMPILED_HAS_MORE_INVERTED_REGEXES2) {
|
|
999
|
+
if (regex.test(propName)) {
|
|
1000
|
+
currentPropRank = 5;
|
|
1001
|
+
break;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
129
1005
|
}
|
|
130
1006
|
}
|
|
1007
|
+
updateCandidate(propName, currentPropRank);
|
|
131
1008
|
}
|
|
132
|
-
|
|
133
|
-
}
|
|
1009
|
+
return bestCandidate;
|
|
1010
|
+
}
|
|
1011
|
+
function getHasMoreName(properties) {
|
|
1012
|
+
const rootGuess = guess(properties);
|
|
1013
|
+
if (rootGuess) {
|
|
1014
|
+
return rootGuess;
|
|
1015
|
+
}
|
|
1016
|
+
for (const propName in properties) {
|
|
1017
|
+
const propSchema = properties[propName];
|
|
1018
|
+
if (propSchema.type === "object" && propSchema.properties) {
|
|
1019
|
+
const nested = getHasMoreName(propSchema.properties);
|
|
1020
|
+
if (nested) {
|
|
1021
|
+
return propName + "." + nested;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
134
1027
|
|
|
135
|
-
// packages/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1028
|
+
// packages/spec/dist/lib/pagination/pagination.js
|
|
1029
|
+
var OFFSET_PARAM_REGEXES = [
|
|
1030
|
+
/\boffset\b/i,
|
|
1031
|
+
/\bskip\b/i,
|
|
1032
|
+
/\bstart(?:ing_at|_index)?\b/i,
|
|
1033
|
+
// e.g., start, starting_at, start_index
|
|
1034
|
+
/\bfrom\b/i
|
|
1035
|
+
];
|
|
1036
|
+
var GENERIC_LIMIT_PARAM_REGEXES = [
|
|
1037
|
+
/\blimit\b/i,
|
|
1038
|
+
/\bcount\b/i,
|
|
1039
|
+
/\b(?:page_?)?size\b/i,
|
|
1040
|
+
// e.g., size, page_size, pagesize
|
|
1041
|
+
/\bmax_results\b/i,
|
|
1042
|
+
/\bnum_results\b/i,
|
|
1043
|
+
/\bshow\b/i,
|
|
1044
|
+
// Can sometimes mean limit
|
|
1045
|
+
/\bper_?page\b/i,
|
|
1046
|
+
// e.g., per_page, perpage
|
|
1047
|
+
/\bper-page\b/i,
|
|
1048
|
+
/\btake\b/i
|
|
1049
|
+
];
|
|
1050
|
+
var PAGE_NUMBER_REGEXES = [
|
|
1051
|
+
/^page$/i,
|
|
1052
|
+
// Exact match for "page"
|
|
1053
|
+
/^p$/i,
|
|
1054
|
+
// Exact match for "p" (common shorthand)
|
|
1055
|
+
/\bpage_?(?:number|num|idx|index)\b/i
|
|
1056
|
+
// e.g., page_number, pageNumber, page_num, page_idx
|
|
1057
|
+
];
|
|
1058
|
+
var PAGE_SIZE_REGEXES = [
|
|
1059
|
+
/\bpage_?size\b/i,
|
|
1060
|
+
// e.g., page_size, pagesize
|
|
1061
|
+
/^size$/i,
|
|
1062
|
+
// Exact "size"
|
|
1063
|
+
// /\bsize\b/i, // Broader "size" - can be ambiguous, prefer more specific ones first
|
|
1064
|
+
/\blimit\b/i,
|
|
1065
|
+
// Limit is often used for page size
|
|
1066
|
+
/\bcount\b/i,
|
|
1067
|
+
// Count can also be used for page size
|
|
1068
|
+
/\bper_?page\b/i,
|
|
1069
|
+
// e.g., per_page, perpage
|
|
1070
|
+
/\bper-page\b/i,
|
|
1071
|
+
/\bnum_?(?:items|records|results)\b/i,
|
|
1072
|
+
// e.g., num_items, numitems
|
|
1073
|
+
/\bresults_?per_?page\b/i
|
|
1074
|
+
];
|
|
1075
|
+
var CURSOR_REGEXES = [
|
|
1076
|
+
/\bcursor\b/i,
|
|
1077
|
+
/\bafter(?:_?cursor)?\b/i,
|
|
1078
|
+
// e.g., after, after_cursor
|
|
1079
|
+
/\bbefore(?:_?cursor)?\b/i,
|
|
1080
|
+
// e.g., before, before_cursor
|
|
1081
|
+
/\b(next|prev|previous)_?(?:page_?)?token\b/i,
|
|
1082
|
+
// e.g., next_page_token, nextPageToken, prev_token
|
|
1083
|
+
/\b(next|prev|previous)_?cursor\b/i,
|
|
1084
|
+
// e.g., next_cursor, previousCursor
|
|
1085
|
+
/\bcontinuation(?:_?token)?\b/i,
|
|
1086
|
+
// e.g., continuation, continuation_token
|
|
1087
|
+
/\bpage(?:_?(token|id))?\b/i,
|
|
1088
|
+
// e.g., after, after_cursor
|
|
1089
|
+
/\bstart_?(?:key|cursor|token|after)\b/i
|
|
1090
|
+
// e.g., start_key, startCursor, startToken, startAfter
|
|
1091
|
+
];
|
|
1092
|
+
var CURSOR_LIMIT_REGEXES = [
|
|
1093
|
+
/\blimit\b/i,
|
|
1094
|
+
/\bcount\b/i,
|
|
1095
|
+
/\bsize\b/i,
|
|
1096
|
+
// General size
|
|
1097
|
+
/\bfirst\b/i,
|
|
1098
|
+
// Common in Relay-style cursor pagination (forward pagination)
|
|
1099
|
+
/\blast\b/i,
|
|
1100
|
+
// Common in Relay-style cursor pagination (backward pagination)
|
|
1101
|
+
/\bpage_?size\b/i,
|
|
1102
|
+
// Sometimes page_size is used with cursors
|
|
1103
|
+
/\bnum_?(?:items|records|results)\b/i,
|
|
1104
|
+
// e.g., num_items
|
|
1105
|
+
/\bmax_?items\b/i,
|
|
1106
|
+
/\btake\b/i
|
|
1107
|
+
];
|
|
1108
|
+
function findParamAndKeyword(queryParams, regexes, excludeParamName) {
|
|
1109
|
+
for (const param of queryParams) {
|
|
1110
|
+
if (param.name === excludeParamName) {
|
|
1111
|
+
continue;
|
|
1112
|
+
}
|
|
1113
|
+
for (const regex of regexes) {
|
|
1114
|
+
const match = param.name.match(regex);
|
|
1115
|
+
if (match) {
|
|
1116
|
+
return { param, keyword: match[0] };
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return null;
|
|
1121
|
+
}
|
|
1122
|
+
function isOffsetPagination(operation, parameters) {
|
|
1123
|
+
const offsetMatch = findParamAndKeyword(parameters, OFFSET_PARAM_REGEXES);
|
|
1124
|
+
if (!offsetMatch)
|
|
1125
|
+
return null;
|
|
1126
|
+
const limitMatch = findParamAndKeyword(
|
|
1127
|
+
parameters,
|
|
1128
|
+
GENERIC_LIMIT_PARAM_REGEXES,
|
|
1129
|
+
offsetMatch.param.name
|
|
1130
|
+
);
|
|
1131
|
+
if (!limitMatch)
|
|
1132
|
+
return null;
|
|
1133
|
+
return {
|
|
1134
|
+
type: "offset",
|
|
1135
|
+
offsetParamName: offsetMatch.param.name,
|
|
1136
|
+
offsetKeyword: offsetMatch.keyword,
|
|
1137
|
+
limitParamName: limitMatch.param.name,
|
|
1138
|
+
limitKeyword: limitMatch.keyword
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function isPagePagination(operation) {
|
|
1142
|
+
const queryParams = operation.parameters.filter((p) => p.in === "query").filter(
|
|
1143
|
+
(it) => it.schema && !isRef4(it.schema) && it.schema.type === "integer"
|
|
1144
|
+
);
|
|
1145
|
+
if (queryParams.length < 2)
|
|
1146
|
+
return null;
|
|
1147
|
+
const pageNoMatch = findParamAndKeyword(queryParams, PAGE_NUMBER_REGEXES);
|
|
1148
|
+
if (!pageNoMatch)
|
|
1149
|
+
return null;
|
|
1150
|
+
const pageSizeMatch = findParamAndKeyword(
|
|
1151
|
+
queryParams,
|
|
1152
|
+
PAGE_SIZE_REGEXES,
|
|
1153
|
+
pageNoMatch.param.name
|
|
1154
|
+
);
|
|
1155
|
+
if (!pageSizeMatch)
|
|
1156
|
+
return null;
|
|
1157
|
+
return {
|
|
1158
|
+
type: "page",
|
|
1159
|
+
pageNumberParamName: pageNoMatch.param.name,
|
|
1160
|
+
pageNumberKeyword: pageNoMatch.keyword,
|
|
1161
|
+
pageSizeParamName: pageSizeMatch.param.name,
|
|
1162
|
+
pageSizeKeyword: pageSizeMatch.keyword
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
function isCursorPagination(operation) {
|
|
1166
|
+
const queryParams = operation.parameters.filter((p) => p.in === "query");
|
|
1167
|
+
if (queryParams.length < 2)
|
|
1168
|
+
return null;
|
|
1169
|
+
const cursorMatch = findParamAndKeyword(queryParams, CURSOR_REGEXES);
|
|
1170
|
+
if (!cursorMatch)
|
|
1171
|
+
return null;
|
|
1172
|
+
const limitMatch = findParamAndKeyword(
|
|
1173
|
+
queryParams,
|
|
1174
|
+
CURSOR_LIMIT_REGEXES,
|
|
1175
|
+
cursorMatch.param.name
|
|
1176
|
+
);
|
|
1177
|
+
if (!limitMatch)
|
|
1178
|
+
return null;
|
|
1179
|
+
return {
|
|
1180
|
+
type: "cursor",
|
|
1181
|
+
cursorParamName: cursorMatch.param.name,
|
|
1182
|
+
cursorKeyword: cursorMatch.keyword,
|
|
1183
|
+
limitParamName: limitMatch.param.name,
|
|
1184
|
+
limitKeyword: limitMatch.keyword
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
function guessPagination(operation, body, response) {
|
|
1188
|
+
const bodyParameters = body && body.properties ? Object.keys(body.properties).map((it) => ({ name: it })) : [];
|
|
1189
|
+
const parameters = operation.parameters;
|
|
1190
|
+
if (isEmpty3(operation.parameters) && isEmpty3(bodyParameters)) {
|
|
1191
|
+
return { type: "none", reason: "no parameters" };
|
|
1192
|
+
}
|
|
1193
|
+
if (!response) {
|
|
1194
|
+
return { type: "none", reason: "no response" };
|
|
1195
|
+
}
|
|
1196
|
+
if (!response.properties) {
|
|
1197
|
+
return { type: "none", reason: "empty response" };
|
|
1198
|
+
}
|
|
1199
|
+
const properties = response.properties;
|
|
1200
|
+
const itemsKey = getItemsName(properties);
|
|
1201
|
+
if (!itemsKey) {
|
|
1202
|
+
return { type: "none", reason: "no items key" };
|
|
1203
|
+
}
|
|
1204
|
+
const hasMoreKey = getHasMoreName(excludeKey(properties, itemsKey));
|
|
1205
|
+
if (!hasMoreKey) {
|
|
1206
|
+
return { type: "none", reason: "no hasMore key" };
|
|
1207
|
+
}
|
|
1208
|
+
const pagination = isOffsetPagination(operation, [...parameters, ...bodyParameters]) || isPagePagination(operation) || isCursorPagination(operation);
|
|
1209
|
+
return pagination ? { ...pagination, items: itemsKey, hasMore: hasMoreKey } : { type: "none", reason: "no pagination" };
|
|
1210
|
+
}
|
|
1211
|
+
function excludeKey(obj, key) {
|
|
1212
|
+
const { [key]: _, ...rest } = obj;
|
|
1213
|
+
return rest;
|
|
1214
|
+
}
|
|
140
1215
|
|
|
141
1216
|
// packages/spec/dist/lib/operation.js
|
|
142
|
-
|
|
143
|
-
|
|
1217
|
+
function augmentSpec(config) {
|
|
1218
|
+
config.spec.paths ??= {};
|
|
1219
|
+
const paths = {};
|
|
1220
|
+
for (const [path, pathItem] of Object.entries(config.spec.paths)) {
|
|
1221
|
+
const { parameters = [], ...methods2 } = pathItem;
|
|
1222
|
+
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
1223
|
+
for (const [method, operation] of Object.entries(methods2)) {
|
|
1224
|
+
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
1225
|
+
const formatTag = config.tag ?? defaults.tag;
|
|
1226
|
+
const operationId = formatOperationId(operation, fixedPath, method);
|
|
1227
|
+
const operationTag = formatTag(operation, fixedPath);
|
|
1228
|
+
const requestBody = isRef5(operation.requestBody) ? followRef3(config.spec, operation.requestBody.$ref) : operation.requestBody;
|
|
1229
|
+
const tunedOperation = {
|
|
1230
|
+
...operation,
|
|
1231
|
+
parameters: [...parameters, ...operation.parameters ?? []].map(
|
|
1232
|
+
(it) => isRef5(it) ? followRef3(config.spec, it.$ref) : it
|
|
1233
|
+
),
|
|
1234
|
+
tags: [operationTag],
|
|
1235
|
+
operationId,
|
|
1236
|
+
responses: resolveResponses(config.spec, operation),
|
|
1237
|
+
requestBody
|
|
1238
|
+
};
|
|
1239
|
+
tunedOperation["x-pagination"] = toPagination(
|
|
1240
|
+
config.spec,
|
|
1241
|
+
tunedOperation
|
|
1242
|
+
);
|
|
1243
|
+
Object.assign(paths, {
|
|
1244
|
+
[fixedPath]: {
|
|
1245
|
+
...paths[fixedPath],
|
|
1246
|
+
[method]: tunedOperation
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
return { ...config.spec, paths };
|
|
1252
|
+
}
|
|
1253
|
+
function toPagination(spec, tunedOperation) {
|
|
1254
|
+
if (tunedOperation["x-pagination"]) {
|
|
1255
|
+
return tunedOperation["x-pagination"];
|
|
1256
|
+
}
|
|
1257
|
+
const schema = getResponseContentSchema(
|
|
1258
|
+
spec,
|
|
1259
|
+
tunedOperation.responses["200"],
|
|
1260
|
+
"application/json"
|
|
1261
|
+
);
|
|
1262
|
+
const pagination = guessPagination(
|
|
1263
|
+
tunedOperation,
|
|
1264
|
+
tunedOperation.requestBody ? getRequestContentSchema(
|
|
1265
|
+
spec,
|
|
1266
|
+
tunedOperation.requestBody,
|
|
1267
|
+
"application/json"
|
|
1268
|
+
) : void 0,
|
|
1269
|
+
schema
|
|
1270
|
+
);
|
|
1271
|
+
if (pagination && pagination.type !== "none" && schema) {
|
|
1272
|
+
return pagination;
|
|
1273
|
+
}
|
|
1274
|
+
return void 0;
|
|
1275
|
+
}
|
|
1276
|
+
function getResponseContentSchema(spec, response, type) {
|
|
1277
|
+
if (!response) {
|
|
1278
|
+
return void 0;
|
|
1279
|
+
}
|
|
1280
|
+
const content = response.content;
|
|
1281
|
+
if (!content) {
|
|
1282
|
+
return void 0;
|
|
1283
|
+
}
|
|
1284
|
+
for (const contentType in content) {
|
|
1285
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
1286
|
+
return isRef5(content[contentType].schema) ? followRef3(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
return void 0;
|
|
1290
|
+
}
|
|
1291
|
+
function getRequestContentSchema(spec, requestBody, type) {
|
|
1292
|
+
const content = requestBody.content;
|
|
1293
|
+
if (!content) {
|
|
1294
|
+
return void 0;
|
|
1295
|
+
}
|
|
1296
|
+
for (const contentType in content) {
|
|
1297
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
1298
|
+
return isRef5(content[contentType].schema) ? followRef3(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return void 0;
|
|
1302
|
+
}
|
|
144
1303
|
var defaults = {
|
|
145
1304
|
operationId: (operation, path, method) => {
|
|
146
1305
|
if (operation.operationId) {
|
|
147
|
-
return
|
|
1306
|
+
return camelcase2(operation.operationId);
|
|
148
1307
|
}
|
|
149
1308
|
const metadata = operation["x-oaiMeta"];
|
|
150
1309
|
if (metadata && metadata.name) {
|
|
151
|
-
return
|
|
1310
|
+
return camelcase2(metadata.name);
|
|
152
1311
|
}
|
|
153
|
-
return
|
|
1312
|
+
return camelcase2(
|
|
154
1313
|
[method, ...path.replace(/[\\/\\{\\}]/g, " ").split(" ")].filter(Boolean).join(" ").trim()
|
|
155
1314
|
);
|
|
156
1315
|
},
|
|
@@ -162,37 +1321,28 @@ function resolveResponses(spec, operation) {
|
|
|
162
1321
|
const responses = operation.responses ?? {};
|
|
163
1322
|
const resolved = {};
|
|
164
1323
|
for (const status in responses) {
|
|
165
|
-
const response =
|
|
1324
|
+
const response = isRef5(responses[status]) ? followRef3(spec, responses[status].$ref) : responses[status];
|
|
166
1325
|
resolved[status] = response;
|
|
167
1326
|
}
|
|
168
1327
|
return resolved;
|
|
169
1328
|
}
|
|
170
|
-
function
|
|
1329
|
+
function forEachOperation2(config, callback) {
|
|
171
1330
|
const result = [];
|
|
172
1331
|
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
173
1332
|
const { parameters = [], ...methods2 } = pathItem;
|
|
174
|
-
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
175
1333
|
for (const [method, operation] of Object.entries(methods2)) {
|
|
176
|
-
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
177
|
-
const formatTag = config.tag ?? defaults.tag;
|
|
178
|
-
const operationName = formatOperationId(operation, fixedPath, method);
|
|
179
|
-
const operationTag = formatTag(operation, fixedPath);
|
|
180
1334
|
const metadata = operation["x-oaiMeta"] ?? {};
|
|
1335
|
+
const operationTag = operation.tags?.[0];
|
|
181
1336
|
result.push(
|
|
182
1337
|
callback(
|
|
183
1338
|
{
|
|
184
1339
|
name: metadata.name,
|
|
185
1340
|
method,
|
|
186
|
-
path
|
|
1341
|
+
path,
|
|
187
1342
|
groupName: operationTag,
|
|
188
1343
|
tag: operationTag
|
|
189
1344
|
},
|
|
190
|
-
|
|
191
|
-
...operation,
|
|
192
|
-
parameters: [...parameters, ...operation.parameters ?? []],
|
|
193
|
-
operationId: operationName,
|
|
194
|
-
responses: resolveResponses(config.spec, operation)
|
|
195
|
-
}
|
|
1345
|
+
operation
|
|
196
1346
|
)
|
|
197
1347
|
);
|
|
198
1348
|
}
|
|
@@ -264,7 +1414,7 @@ function sanitizeTag(camelCasedTag) {
|
|
|
264
1414
|
if (/^\d/.test(camelCasedTag)) {
|
|
265
1415
|
return `_${camelCasedTag}`;
|
|
266
1416
|
}
|
|
267
|
-
return reservedKeywords.has(
|
|
1417
|
+
return reservedKeywords.has(camelcase2(camelCasedTag)) ? `${camelCasedTag}_` : camelCasedTag;
|
|
268
1418
|
}
|
|
269
1419
|
function determineGenericTag(pathString, operation) {
|
|
270
1420
|
const operationId = operation.operationId || "";
|
|
@@ -296,7 +1446,7 @@ function determineGenericTag(pathString, operation) {
|
|
|
296
1446
|
for (let i = potentialCandidates.length - 1; i >= 0; i--) {
|
|
297
1447
|
const segment = potentialCandidates[i];
|
|
298
1448
|
if (!segment.startsWith("@")) {
|
|
299
|
-
return sanitizeTag(
|
|
1449
|
+
return sanitizeTag(camelcase2(segment));
|
|
300
1450
|
}
|
|
301
1451
|
}
|
|
302
1452
|
const canFallbackToPathSegment = potentialCandidates.length > 0;
|
|
@@ -331,17 +1481,17 @@ function determineGenericTag(pathString, operation) {
|
|
|
331
1481
|
}
|
|
332
1482
|
if (nextPartStartIndex !== -1 && nextPartStartIndex < operationId.length) {
|
|
333
1483
|
const remainingOriginalSubstring = operationId.substring(nextPartStartIndex);
|
|
334
|
-
const potentialTag =
|
|
1484
|
+
const potentialTag = camelcase2(remainingOriginalSubstring);
|
|
335
1485
|
if (potentialTag) {
|
|
336
1486
|
return sanitizeTag(potentialTag);
|
|
337
1487
|
}
|
|
338
1488
|
}
|
|
339
|
-
const potentialTagJoined =
|
|
1489
|
+
const potentialTagJoined = camelcase2(validParts.slice(1).join("_"));
|
|
340
1490
|
if (potentialTagJoined) {
|
|
341
1491
|
return sanitizeTag(potentialTagJoined);
|
|
342
1492
|
}
|
|
343
1493
|
}
|
|
344
|
-
const potentialTagFull =
|
|
1494
|
+
const potentialTagFull = camelcase2(operationId);
|
|
345
1495
|
if (potentialTagFull) {
|
|
346
1496
|
const isResultSingleVerb = validParts.length === 1 && isFirstPartVerb;
|
|
347
1497
|
if (!(isResultSingleVerb && canFallbackToPathSegment)) {
|
|
@@ -350,39 +1500,227 @@ function determineGenericTag(pathString, operation) {
|
|
|
350
1500
|
}
|
|
351
1501
|
}
|
|
352
1502
|
}
|
|
353
|
-
const firstPartCamel =
|
|
1503
|
+
const firstPartCamel = camelcase2(firstPart);
|
|
354
1504
|
if (firstPartCamel) {
|
|
355
1505
|
const isFirstPartCamelVerb = commonVerbs.has(firstPartCamel);
|
|
356
1506
|
if (!isFirstPartCamelVerb || validParts.length === 1 || !canFallbackToPathSegment) {
|
|
357
1507
|
return sanitizeTag(firstPartCamel);
|
|
358
1508
|
}
|
|
359
1509
|
}
|
|
360
|
-
if (isFirstPartVerb && validParts.length > 1 && validParts[1] && canFallbackToPathSegment) {
|
|
361
|
-
const secondPartCamel =
|
|
362
|
-
if (secondPartCamel) {
|
|
363
|
-
return sanitizeTag(secondPartCamel);
|
|
364
|
-
}
|
|
1510
|
+
if (isFirstPartVerb && validParts.length > 1 && validParts[1] && canFallbackToPathSegment) {
|
|
1511
|
+
const secondPartCamel = camelcase2(validParts[1]);
|
|
1512
|
+
if (secondPartCamel) {
|
|
1513
|
+
return sanitizeTag(secondPartCamel);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
if (potentialCandidates.length > 0) {
|
|
1519
|
+
let firstCandidate = potentialCandidates[0];
|
|
1520
|
+
if (firstCandidate.startsWith("@")) {
|
|
1521
|
+
firstCandidate = firstCandidate.substring(1);
|
|
1522
|
+
}
|
|
1523
|
+
if (firstCandidate) {
|
|
1524
|
+
return sanitizeTag(camelcase2(firstCandidate));
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
console.warn(
|
|
1528
|
+
`Could not determine a suitable tag for path: ${pathString}, operationId: ${operationId}. Using 'unknown'.`
|
|
1529
|
+
);
|
|
1530
|
+
return "unknown";
|
|
1531
|
+
}
|
|
1532
|
+
function patchParameters(spec, objectSchema, operation) {
|
|
1533
|
+
const securitySchemes = spec.components?.securitySchemes ?? {};
|
|
1534
|
+
const securityOptions = securityToOptions(
|
|
1535
|
+
spec,
|
|
1536
|
+
operation.security ?? [],
|
|
1537
|
+
securitySchemes
|
|
1538
|
+
);
|
|
1539
|
+
objectSchema.properties ??= {};
|
|
1540
|
+
objectSchema.required ??= [];
|
|
1541
|
+
for (const param of operation.parameters) {
|
|
1542
|
+
if (param.required) {
|
|
1543
|
+
objectSchema.required.push(param.name);
|
|
1544
|
+
}
|
|
1545
|
+
objectSchema.properties[param.name] = isRef5(param.schema) ? followRef3(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
1546
|
+
}
|
|
1547
|
+
for (const param of securityOptions) {
|
|
1548
|
+
objectSchema.required = (objectSchema.required ?? []).filter(
|
|
1549
|
+
(name) => name !== param.name
|
|
1550
|
+
);
|
|
1551
|
+
objectSchema.properties[param.name] = isRef5(param.schema) ? followRef3(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
function securityToOptions(spec, security2, securitySchemes, staticIn) {
|
|
1555
|
+
securitySchemes ??= {};
|
|
1556
|
+
const parameters = [];
|
|
1557
|
+
for (const it of security2) {
|
|
1558
|
+
const [name] = Object.keys(it);
|
|
1559
|
+
if (!name) {
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
const schema = isRef5(securitySchemes[name]) ? followRef3(spec, securitySchemes[name].$ref) : securitySchemes[name];
|
|
1563
|
+
if (schema.type === "http") {
|
|
1564
|
+
parameters.push({
|
|
1565
|
+
in: staticIn ?? "header",
|
|
1566
|
+
name: "authorization",
|
|
1567
|
+
schema: { type: "string" }
|
|
1568
|
+
});
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
if (schema.type === "apiKey") {
|
|
1572
|
+
if (!schema.in) {
|
|
1573
|
+
throw new Error(`apiKey security schema must have an "in" field`);
|
|
1574
|
+
}
|
|
1575
|
+
if (!schema.name) {
|
|
1576
|
+
throw new Error(`apiKey security schema must have a "name" field`);
|
|
365
1577
|
}
|
|
1578
|
+
parameters.push({
|
|
1579
|
+
in: staticIn ?? schema.in,
|
|
1580
|
+
name: schema.name,
|
|
1581
|
+
schema: { type: "string" }
|
|
1582
|
+
});
|
|
1583
|
+
continue;
|
|
366
1584
|
}
|
|
367
1585
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
1586
|
+
return parameters;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
// packages/typescript/src/lib/client.ts
|
|
1590
|
+
import { toLitObject } from "@sdk-it/core";
|
|
1591
|
+
var client_default = (spec, style) => {
|
|
1592
|
+
const optionsEntries = Object.entries(spec.options).map(
|
|
1593
|
+
([key, value]) => [`'${key}'`, value]
|
|
1594
|
+
);
|
|
1595
|
+
const defaultHeaders = `{${optionsEntries.filter(([, value]) => value.in === "header").map(
|
|
1596
|
+
([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
|
|
1597
|
+
).join(",\n")}}`;
|
|
1598
|
+
const defaultInputs = `{${optionsEntries.filter(([, value]) => value.in === "input").map(
|
|
1599
|
+
([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
|
|
1600
|
+
).join(",\n")}}`;
|
|
1601
|
+
const specOptions = {
|
|
1602
|
+
...Object.fromEntries(
|
|
1603
|
+
optionsEntries.map(([key, value]) => [value.optionName ?? key, value])
|
|
1604
|
+
),
|
|
1605
|
+
fetch: {
|
|
1606
|
+
schema: "fetchType"
|
|
1607
|
+
},
|
|
1608
|
+
baseUrl: {
|
|
1609
|
+
schema: spec.servers.length ? `z.enum(servers).default(servers[0])` : "z.string()"
|
|
372
1610
|
}
|
|
373
|
-
|
|
374
|
-
|
|
1611
|
+
};
|
|
1612
|
+
return `import z from 'zod';
|
|
1613
|
+
import type { HeadersInit, RequestConfig } from './http/${spec.makeImport("request")}';
|
|
1614
|
+
import { fetchType, parse } from './http/${spec.makeImport("dispatcher")}';
|
|
1615
|
+
import schemas from './api/${spec.makeImport("schemas")}';
|
|
1616
|
+
import {
|
|
1617
|
+
createBaseUrlInterceptor,
|
|
1618
|
+
createHeadersInterceptor,
|
|
1619
|
+
} from './http/${spec.makeImport("interceptors")}';
|
|
1620
|
+
|
|
1621
|
+
import { parseInput, type ParseError } from './http/${spec.makeImport("parser")}';
|
|
1622
|
+
|
|
1623
|
+
${spec.servers.length ? `export const servers = ${JSON.stringify(spec.servers, null, 2)} as const` : ""}
|
|
1624
|
+
const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});
|
|
1625
|
+
${spec.servers.length ? `export type Servers = typeof servers[number];` : ""}
|
|
1626
|
+
|
|
1627
|
+
type ${spec.name}Options = z.infer<typeof optionsSchema>;
|
|
1628
|
+
|
|
1629
|
+
export class ${spec.name} {
|
|
1630
|
+
public options: ${spec.name}Options
|
|
1631
|
+
constructor(options: ${spec.name}Options) {
|
|
1632
|
+
this.options = optionsSchema.parse(options);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
async request<const E extends keyof typeof schemas>(
|
|
1636
|
+
endpoint: E,
|
|
1637
|
+
input: z.infer<(typeof schemas)[E]['schema']>,
|
|
1638
|
+
options?: { signal?: AbortSignal, headers?: HeadersInit },
|
|
1639
|
+
) ${style.errorAsValue ? `: Promise<Awaited<ReturnType<(typeof schemas)[E]['dispatch']>>| [never, ParseError<(typeof schemas)[E]['schema']>]>` : `: Promise<Awaited<ReturnType<(typeof schemas)[E]['dispatch']>>>`} {
|
|
1640
|
+
const route = schemas[endpoint];
|
|
1641
|
+
const withDefaultInputs = Object.assign({}, this.#defaultInputs, input);
|
|
1642
|
+
const [parsedInput, parseError] = parseInput(route.schema, withDefaultInputs);
|
|
1643
|
+
if (parseError) {
|
|
1644
|
+
${style.errorAsValue ? "return [null as never, parseError as never] as const;" : "throw parseError;"}
|
|
375
1645
|
}
|
|
1646
|
+
const result = await route.dispatch(parsedInput as never, {
|
|
1647
|
+
fetch: this.options.fetch,
|
|
1648
|
+
interceptors: [
|
|
1649
|
+
createHeadersInterceptor(() => this.defaultHeaders, options?.headers ?? {}),
|
|
1650
|
+
createBaseUrlInterceptor(() => this.options.baseUrl),
|
|
1651
|
+
],
|
|
1652
|
+
signal: options?.signal,
|
|
1653
|
+
});
|
|
1654
|
+
return result as Awaited<ReturnType<(typeof schemas)[E]['dispatch']>>;
|
|
376
1655
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
1656
|
+
|
|
1657
|
+
async prepare<const E extends keyof typeof schemas>(
|
|
1658
|
+
endpoint: E,
|
|
1659
|
+
input: z.infer<(typeof schemas)[E]['schema']>,
|
|
1660
|
+
options?: { headers?: HeadersInit },
|
|
1661
|
+
): ${style.errorAsValue ? `Promise<
|
|
1662
|
+
readonly [
|
|
1663
|
+
RequestConfig & {
|
|
1664
|
+
parse: (response: Response) => ReturnType<typeof parse>;
|
|
1665
|
+
},
|
|
1666
|
+
ParseError<(typeof schemas)[E]['schema']> | null,
|
|
1667
|
+
]
|
|
1668
|
+
>` : `Promise<RequestConfig & {
|
|
1669
|
+
parse: (response: Response) => ReturnType<typeof parse>;
|
|
1670
|
+
}>`} {
|
|
1671
|
+
const route = schemas[endpoint];
|
|
1672
|
+
|
|
1673
|
+
const interceptors = [
|
|
1674
|
+
createHeadersInterceptor(
|
|
1675
|
+
() => this.defaultHeaders,
|
|
1676
|
+
options?.headers ?? {},
|
|
1677
|
+
),
|
|
1678
|
+
createBaseUrlInterceptor(() => this.options.baseUrl),
|
|
1679
|
+
];
|
|
1680
|
+
const [parsedInput, parseError] = parseInput(route.schema, input);
|
|
1681
|
+
if (parseError) {
|
|
1682
|
+
${style.errorAsValue ? "return [null as never, parseError as never] as const;" : "throw parseError;"}
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
let config = route.toRequest(parsedInput as never);
|
|
1686
|
+
for (const interceptor of interceptors) {
|
|
1687
|
+
if (interceptor.before) {
|
|
1688
|
+
config = await interceptor.before(config);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
const prepared = { ...config, parse: (response: Response) => parse(route.output, response) as never };
|
|
1692
|
+
return ${style.errorAsValue ? "[prepared, null as never] as const;" : "prepared as any"}
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
get defaultHeaders() {
|
|
1696
|
+
return ${defaultHeaders}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
get #defaultInputs() {
|
|
1700
|
+
return ${defaultInputs}
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
setOptions(options: Partial<${spec.name}Options>) {
|
|
1704
|
+
const validated = optionsSchema.partial().parse(options);
|
|
1705
|
+
|
|
1706
|
+
for (const key of Object.keys(validated) as (keyof ${spec.name}Options)[]) {
|
|
1707
|
+
if (validated[key] !== undefined) {
|
|
1708
|
+
(this.options[key] as typeof validated[typeof key]) = validated[key]!;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}`;
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1715
|
+
// packages/typescript/src/lib/generator.ts
|
|
1716
|
+
import { merge, template } from "lodash-es";
|
|
1717
|
+
import { join } from "node:path";
|
|
1718
|
+
import { camelcase as camelcase4, pascalcase as pascalcase2, spinalcase as spinalcase2 } from "stringcase";
|
|
1719
|
+
import { followRef as followRef7, isEmpty as isEmpty4, isRef as isRef10 } from "@sdk-it/core";
|
|
382
1720
|
|
|
383
1721
|
// packages/typescript/src/lib/emitters/zod.ts
|
|
384
|
-
import { cleanRef, followRef as
|
|
385
|
-
var
|
|
1722
|
+
import { cleanRef, followRef as followRef4, isRef as isRef6 } from "@sdk-it/core";
|
|
1723
|
+
var ZodEmitter = class {
|
|
386
1724
|
generatedRefs = /* @__PURE__ */ new Set();
|
|
387
1725
|
#spec;
|
|
388
1726
|
#onRef;
|
|
@@ -463,7 +1801,7 @@ var ZodDeserialzer = class {
|
|
|
463
1801
|
this.generatedRefs.add(schemaName);
|
|
464
1802
|
this.#onRef?.(
|
|
465
1803
|
schemaName,
|
|
466
|
-
this.handle(
|
|
1804
|
+
this.handle(followRef4(this.#spec, $ref), required)
|
|
467
1805
|
);
|
|
468
1806
|
return schemaName;
|
|
469
1807
|
}
|
|
@@ -593,7 +1931,7 @@ var ZodDeserialzer = class {
|
|
|
593
1931
|
return { base, defaultValue };
|
|
594
1932
|
}
|
|
595
1933
|
handle(schema, required) {
|
|
596
|
-
if (
|
|
1934
|
+
if (isRef6(schema)) {
|
|
597
1935
|
return `${this.ref(schema.$ref, true)}${appendOptional(required)}`;
|
|
598
1936
|
}
|
|
599
1937
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -639,12 +1977,12 @@ function appendDefault(defaultValue) {
|
|
|
639
1977
|
|
|
640
1978
|
// packages/typescript/src/lib/sdk.ts
|
|
641
1979
|
import { get } from "lodash-es";
|
|
642
|
-
import { camelcase as
|
|
643
|
-
import {
|
|
1980
|
+
import { camelcase as camelcase3, pascalcase, spinalcase } from "stringcase";
|
|
1981
|
+
import { isRef as isRef9, toLitObject as toLitObject2 } from "@sdk-it/core";
|
|
644
1982
|
|
|
645
1983
|
// packages/typescript/src/lib/emitters/interface.ts
|
|
646
|
-
import { cleanRef as cleanRef2, followRef as
|
|
647
|
-
var
|
|
1984
|
+
import { cleanRef as cleanRef2, followRef as followRef5, isRef as isRef7 } from "@sdk-it/core";
|
|
1985
|
+
var TypeScriptEmitter = class {
|
|
648
1986
|
generatedRefs = /* @__PURE__ */ new Set();
|
|
649
1987
|
#spec;
|
|
650
1988
|
#onRef;
|
|
@@ -656,7 +1994,7 @@ var TypeScriptDeserialzer = class {
|
|
|
656
1994
|
return `'${value}'`;
|
|
657
1995
|
};
|
|
658
1996
|
#isInternal = (schema) => {
|
|
659
|
-
return
|
|
1997
|
+
return isRef7(schema) ? false : !!schema["x-internal"];
|
|
660
1998
|
};
|
|
661
1999
|
/**
|
|
662
2000
|
* Handle objects (properties)
|
|
@@ -676,7 +2014,7 @@ var TypeScriptDeserialzer = class {
|
|
|
676
2014
|
propEntries.push("[key: string]: any");
|
|
677
2015
|
}
|
|
678
2016
|
}
|
|
679
|
-
return `{ ${propEntries.join("; ")} }`;
|
|
2017
|
+
return `${propEntries.length ? `{ ${propEntries.join("; ")} }` : "unknown"}`;
|
|
680
2018
|
}
|
|
681
2019
|
/**
|
|
682
2020
|
* Handle arrays (items could be a single schema or a tuple)
|
|
@@ -724,7 +2062,7 @@ var TypeScriptDeserialzer = class {
|
|
|
724
2062
|
this.generatedRefs.add(schemaName);
|
|
725
2063
|
this.#onRef?.(
|
|
726
2064
|
schemaName,
|
|
727
|
-
this.handle(
|
|
2065
|
+
this.handle(followRef5(this.#spec, $ref), required)
|
|
728
2066
|
);
|
|
729
2067
|
return appendOptional2(schemaName, required);
|
|
730
2068
|
}
|
|
@@ -786,7 +2124,7 @@ var TypeScriptDeserialzer = class {
|
|
|
786
2124
|
return appendOptional2(type, required);
|
|
787
2125
|
}
|
|
788
2126
|
handle(schema, required) {
|
|
789
|
-
if (
|
|
2127
|
+
if (isRef7(schema)) {
|
|
790
2128
|
return this.ref(schema.$ref, required);
|
|
791
2129
|
}
|
|
792
2130
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -831,8 +2169,8 @@ function appendOptional2(type, isRequired) {
|
|
|
831
2169
|
}
|
|
832
2170
|
|
|
833
2171
|
// packages/typescript/src/lib/utils.ts
|
|
834
|
-
import { isRef as
|
|
835
|
-
function
|
|
2172
|
+
import { followRef as followRef6, isRef as isRef8, removeDuplicates } from "@sdk-it/core";
|
|
2173
|
+
function securityToOptions2(spec, security2, securitySchemes, staticIn) {
|
|
836
2174
|
securitySchemes ??= {};
|
|
837
2175
|
const options = {};
|
|
838
2176
|
for (const it of security2) {
|
|
@@ -840,10 +2178,7 @@ function securityToOptions(security2, securitySchemes, staticIn) {
|
|
|
840
2178
|
if (!name) {
|
|
841
2179
|
continue;
|
|
842
2180
|
}
|
|
843
|
-
const schema = securitySchemes[name];
|
|
844
|
-
if (isRef4(schema)) {
|
|
845
|
-
throw new Error(`Ref security schemas are not supported`);
|
|
846
|
-
}
|
|
2181
|
+
const schema = isRef8(securitySchemes[name]) ? followRef6(spec, securitySchemes[name].$ref) : securitySchemes[name];
|
|
847
2182
|
if (schema.type === "http") {
|
|
848
2183
|
options["authorization"] = {
|
|
849
2184
|
in: staticIn ?? "header",
|
|
@@ -929,7 +2264,7 @@ function generateInputs(operationsSet, commonZod, makeImport) {
|
|
|
929
2264
|
const output = [];
|
|
930
2265
|
const imports = /* @__PURE__ */ new Set(['import { z } from "zod";']);
|
|
931
2266
|
for (const operation of operations) {
|
|
932
|
-
const schemaName =
|
|
2267
|
+
const schemaName = camelcase3(`${operation.name} schema`);
|
|
933
2268
|
const schema = `export const ${schemaName} = ${Object.keys(operation.schemas).length === 1 ? Object.values(operation.schemas)[0] : toLitObject2(operation.schemas)};`;
|
|
934
2269
|
const inputContent = schema;
|
|
935
2270
|
for (const schema2 of commonImports) {
|
|
@@ -966,8 +2301,8 @@ function generateInputs(operationsSet, commonZod, makeImport) {
|
|
|
966
2301
|
};
|
|
967
2302
|
}
|
|
968
2303
|
function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
969
|
-
const schemaName =
|
|
970
|
-
const schemaRef = `${
|
|
2304
|
+
const schemaName = camelcase3(`${operation.name} schema`);
|
|
2305
|
+
const schemaRef = `${camelcase3(groupName)}.${schemaName}`;
|
|
971
2306
|
const inputHeaders = [];
|
|
972
2307
|
const inputQuery = [];
|
|
973
2308
|
const inputBody = [];
|
|
@@ -999,13 +2334,25 @@ function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
|
999
2334
|
const statusCode = +status;
|
|
1000
2335
|
return statusCode >= 200 && statusCode < 300;
|
|
1001
2336
|
}).length > 1;
|
|
1002
|
-
|
|
1003
|
-
|
|
2337
|
+
const responseWithAtLeast200 = statusesCount ? specOperation.responses : Object.assign(
|
|
2338
|
+
{
|
|
2339
|
+
"200": {
|
|
2340
|
+
description: "OK",
|
|
2341
|
+
content: {
|
|
2342
|
+
"application/json": {
|
|
2343
|
+
schema: { type: "object" }
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
},
|
|
2348
|
+
specOperation.responses
|
|
2349
|
+
);
|
|
2350
|
+
for (const status in responseWithAtLeast200) {
|
|
1004
2351
|
const handled = handleResponse(
|
|
1005
2352
|
spec,
|
|
1006
2353
|
operation.name,
|
|
1007
2354
|
status,
|
|
1008
|
-
|
|
2355
|
+
responseWithAtLeast200[status],
|
|
1009
2356
|
utils,
|
|
1010
2357
|
true
|
|
1011
2358
|
// statusesCount,
|
|
@@ -1025,19 +2372,104 @@ function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
|
1025
2372
|
schema: ${schemaRef}${addTypeParser ? `.${type}` : ""},
|
|
1026
2373
|
output:[${outputs.join(",")}],
|
|
1027
2374
|
toRequest(input: z.infer<typeof ${schemaRef}${addTypeParser ? `.${type}` : ""}>) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
2375
|
+
return toRequest('${endpoint}', ${operation.outgoingContentType || "empty"}(input, {
|
|
2376
|
+
inputHeaders: [${inputHeaders}],
|
|
2377
|
+
inputQuery: [${inputQuery}],
|
|
2378
|
+
inputBody: [${inputBody}],
|
|
2379
|
+
inputParams: [${inputParams}],
|
|
2380
|
+
}));},
|
|
2381
|
+
async dispatch(input: z.infer<typeof ${schemaRef}${addTypeParser ? `.${type}` : ""}>,options: {
|
|
2382
|
+
signal?: AbortSignal;
|
|
2383
|
+
interceptors: Interceptor[];
|
|
2384
|
+
fetch: z.infer<typeof fetchType>;
|
|
2385
|
+
})${specOperation["x-pagination"] ? paginationOperation(specOperation, utils.style) : normalOperation(utils.style)}`
|
|
1037
2386
|
);
|
|
1038
2387
|
}
|
|
1039
2388
|
return { responses, schemas };
|
|
1040
2389
|
}
|
|
2390
|
+
function normalOperation(style) {
|
|
2391
|
+
return `{
|
|
2392
|
+
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
2393
|
+
const result = await dispatcher.send(this.toRequest(input), this.output);
|
|
2394
|
+
return ${style?.outputType === "status" ? "result" : style?.errorAsValue ? `result` : "result.data;"}
|
|
2395
|
+
},
|
|
2396
|
+
}`;
|
|
2397
|
+
}
|
|
2398
|
+
function paginationOperation(operation, style) {
|
|
2399
|
+
const pagination = operation["x-pagination"];
|
|
2400
|
+
const data = `${style?.errorAsValue ? `result[0]${style.outputType === "status" ? "" : ""}` : `${style?.outputType === "default" ? "result.data" : "result.data"}`}`;
|
|
2401
|
+
if (pagination.type === "offset") {
|
|
2402
|
+
const sameInputNames = pagination.limitParamName === "limit" && pagination.offsetParamName === "offset";
|
|
2403
|
+
const initialParams = sameInputNames ? "input" : `{...input, limit: input.${pagination.limitParamName}, offset: input.${pagination.offsetParamName}}`;
|
|
2404
|
+
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.offsetParamName}: nextPageParams.offset, ${pagination.limitParamName}: nextPageParams.limit`;
|
|
2405
|
+
const logic = `const pagination = new OffsetPagination(${initialParams}, async (nextPageParams) => {
|
|
2406
|
+
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
2407
|
+
const result = await dispatcher.send(
|
|
2408
|
+
this.toRequest({...input, ${nextPageParams}}),
|
|
2409
|
+
this.output,
|
|
2410
|
+
);
|
|
2411
|
+
return {
|
|
2412
|
+
data: ${data}.${pagination.items},
|
|
2413
|
+
meta: {
|
|
2414
|
+
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
2415
|
+
},
|
|
2416
|
+
};
|
|
2417
|
+
});
|
|
2418
|
+
await pagination.getNextPage();
|
|
2419
|
+
return ${style?.outputType === "status" ? "new http.Ok(pagination);" : "pagination"}
|
|
2420
|
+
`;
|
|
2421
|
+
return style?.errorAsValue ? `{try {${logic}} catch (error) {return [null as never, error] as const;}}}` : `{${logic}}}`;
|
|
2422
|
+
}
|
|
2423
|
+
if (pagination.type === "cursor") {
|
|
2424
|
+
const sameInputNames = pagination.cursorParamName === "cursor";
|
|
2425
|
+
const initialParams = sameInputNames ? "input" : `{...input, cursor: input.${pagination.cursorParamName}}`;
|
|
2426
|
+
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.cursorParamName}: nextPageParams.cursor`;
|
|
2427
|
+
const logic = `
|
|
2428
|
+
const pagination = new CursorPagination(${initialParams}, async (nextPageParams) => {
|
|
2429
|
+
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
2430
|
+
const result = await dispatcher.send(
|
|
2431
|
+
this.toRequest({...input, ${nextPageParams}}),
|
|
2432
|
+
this.output,
|
|
2433
|
+
);
|
|
2434
|
+
${style?.errorAsValue ? `if (result[1]) {throw result[1];}` : ""}
|
|
2435
|
+
return {
|
|
2436
|
+
data: ${data}.${pagination.items},
|
|
2437
|
+
meta: {
|
|
2438
|
+
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
2439
|
+
},
|
|
2440
|
+
};
|
|
2441
|
+
});
|
|
2442
|
+
await pagination.getNextPage();
|
|
2443
|
+
return ${style?.outputType === "status" ? "new http.Ok(pagination);" : "pagination"}
|
|
2444
|
+
`;
|
|
2445
|
+
return style?.errorAsValue ? `{try {${logic}} catch (error) {return [null as never, error] as const;}}}` : `{${logic}}}`;
|
|
2446
|
+
}
|
|
2447
|
+
if (pagination.type === "page") {
|
|
2448
|
+
const sameInputNames = pagination.pageNumberParamName === "page" && pagination.pageSizeParamName === "pageSize";
|
|
2449
|
+
const initialParams = sameInputNames ? "input" : `{...input, page: input.${pagination.pageNumberParamName}, pageSize: input.${pagination.pageSizeParamName}}`;
|
|
2450
|
+
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.pageNumberParamName}: nextPageParams.page, ${pagination.pageSizeParamName}: nextPageParams.pageSize`;
|
|
2451
|
+
const logic = `
|
|
2452
|
+
const pagination = new Pagination(${initialParams}, async (nextPageParams) => {
|
|
2453
|
+
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
2454
|
+
const result = await dispatcher.send(
|
|
2455
|
+
this.toRequest({...input, ${nextPageParams}}),
|
|
2456
|
+
this.output,
|
|
2457
|
+
);
|
|
2458
|
+
${style?.errorAsValue ? `if (result[1]) {throw result[1];}` : ""}
|
|
2459
|
+
return {
|
|
2460
|
+
data: ${data}.${pagination.items},
|
|
2461
|
+
meta: {
|
|
2462
|
+
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
2463
|
+
},
|
|
2464
|
+
};
|
|
2465
|
+
});
|
|
2466
|
+
await pagination.getNextPage();
|
|
2467
|
+
return ${style?.outputType === "status" ? "new http.Ok(pagination);" : "pagination"}
|
|
2468
|
+
`;
|
|
2469
|
+
return style?.errorAsValue ? `{try {${logic}} catch (error) {return [null as never, error] as const;}}}` : `{${logic}}}`;
|
|
2470
|
+
}
|
|
2471
|
+
return normalOperation(style);
|
|
2472
|
+
}
|
|
1041
2473
|
var statusCodeToResponseMap = {
|
|
1042
2474
|
"200": "Ok",
|
|
1043
2475
|
"201": "Created",
|
|
@@ -1075,7 +2507,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1075
2507
|
};
|
|
1076
2508
|
const responses = [];
|
|
1077
2509
|
const outputs = [];
|
|
1078
|
-
const typeScriptDeserialzer = new
|
|
2510
|
+
const typeScriptDeserialzer = new TypeScriptEmitter(
|
|
1079
2511
|
spec,
|
|
1080
2512
|
(schemaName, zod) => {
|
|
1081
2513
|
schemas[schemaName] = zod;
|
|
@@ -1110,7 +2542,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1110
2542
|
let responseSchema = parser === "chunked" ? "ReadableStream" : "void";
|
|
1111
2543
|
if (isJson) {
|
|
1112
2544
|
const schema = responseContent["application/json"].schema;
|
|
1113
|
-
const isObject = !
|
|
2545
|
+
const isObject = !isRef9(schema) && schema.type === "object";
|
|
1114
2546
|
if (isObject && schema.properties) {
|
|
1115
2547
|
schema.properties["[http.KIND]"] = {
|
|
1116
2548
|
"x-internal": true,
|
|
@@ -1151,13 +2583,13 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1151
2583
|
}
|
|
1152
2584
|
|
|
1153
2585
|
// packages/typescript/src/lib/styles/github/endpoints.txt
|
|
1154
|
-
var endpoints_default = "type
|
|
2586
|
+
var endpoints_default = "type EndpointOutput<K extends keyof typeof schemas> = Extract<\n Unionize<(typeof schemas)[K]['output']>,\n SuccessfulResponse\n>;\n\ntype EndpointError<K extends keyof typeof schemas> = Extract<\n Unionize<(typeof schemas)[K]['output']>,\n ProblematicResponse\n>;\n\nexport type Endpoints = {\n [K in keyof typeof schemas]: {\n input: z.infer<(typeof schemas)[K]['schema']>;\n output: <% if (outputType === 'default') { %>EndpointOutput<K>['data']<% } else { %>EndpointOutput<K><% } %>;\n error: EndpointError<K> | ParseError<(typeof schemas)[K]['schema']>;\n };\n};";
|
|
1155
2587
|
|
|
1156
2588
|
// packages/typescript/src/lib/generator.ts
|
|
1157
2589
|
function generateCode(config) {
|
|
1158
2590
|
const commonZod = /* @__PURE__ */ new Map();
|
|
1159
2591
|
const commonZodImports = [];
|
|
1160
|
-
const zodDeserialzer = new
|
|
2592
|
+
const zodDeserialzer = new ZodEmitter(config.spec, (model, schema) => {
|
|
1161
2593
|
commonZod.set(model, schema);
|
|
1162
2594
|
commonZodImports.push({
|
|
1163
2595
|
defaultImport: void 0,
|
|
@@ -1170,18 +2602,17 @@ function generateCode(config) {
|
|
|
1170
2602
|
const groups = {};
|
|
1171
2603
|
const outputs = {};
|
|
1172
2604
|
const endpoints = {};
|
|
1173
|
-
|
|
2605
|
+
forEachOperation2(config, (entry, operation) => {
|
|
1174
2606
|
console.log(`Processing ${entry.method} ${entry.path}`);
|
|
1175
2607
|
groups[entry.groupName] ??= [];
|
|
1176
2608
|
endpoints[entry.groupName] ??= [];
|
|
1177
2609
|
const inputs = {};
|
|
1178
2610
|
const additionalProperties = {};
|
|
1179
|
-
for (const param of operation.parameters
|
|
1180
|
-
if (isRef6(param)) {
|
|
1181
|
-
throw new Error(`Found reference in parameter ${param.$ref}`);
|
|
1182
|
-
}
|
|
2611
|
+
for (const param of operation.parameters) {
|
|
1183
2612
|
if (!param.schema) {
|
|
1184
|
-
|
|
2613
|
+
param.schema = {
|
|
2614
|
+
type: "string"
|
|
2615
|
+
};
|
|
1185
2616
|
}
|
|
1186
2617
|
inputs[param.name] = {
|
|
1187
2618
|
in: param.in,
|
|
@@ -1189,9 +2620,12 @@ function generateCode(config) {
|
|
|
1189
2620
|
};
|
|
1190
2621
|
additionalProperties[param.name] = param;
|
|
1191
2622
|
}
|
|
1192
|
-
const security2 = operation.security ?? [];
|
|
1193
2623
|
const securitySchemes = config.spec.components?.securitySchemes ?? {};
|
|
1194
|
-
const securityOptions =
|
|
2624
|
+
const securityOptions = securityToOptions2(
|
|
2625
|
+
config.spec,
|
|
2626
|
+
operation.security ?? [],
|
|
2627
|
+
securitySchemes
|
|
2628
|
+
);
|
|
1195
2629
|
Object.assign(inputs, securityOptions);
|
|
1196
2630
|
Object.entries(securityOptions).forEach(([name, value]) => {
|
|
1197
2631
|
additionalProperties[name] = {
|
|
@@ -1216,10 +2650,12 @@ function generateCode(config) {
|
|
|
1216
2650
|
"text/plain": "text"
|
|
1217
2651
|
};
|
|
1218
2652
|
let outgoingContentType;
|
|
1219
|
-
if (!
|
|
1220
|
-
const
|
|
1221
|
-
|
|
1222
|
-
|
|
2653
|
+
if (!isEmpty4(operation.requestBody)) {
|
|
2654
|
+
for (const type in operation.requestBody.content) {
|
|
2655
|
+
const ctSchema = isRef10(operation.requestBody.content[type].schema) ? followRef7(
|
|
2656
|
+
config.spec,
|
|
2657
|
+
operation.requestBody.content[type].schema.$ref
|
|
2658
|
+
) : operation.requestBody.content[type].schema;
|
|
1223
2659
|
if (!ctSchema) {
|
|
1224
2660
|
console.warn(
|
|
1225
2661
|
`Schema not found for ${type} in ${entry.method} ${entry.path}`
|
|
@@ -1230,7 +2666,7 @@ function generateCode(config) {
|
|
|
1230
2666
|
if (objectSchema.type !== "object") {
|
|
1231
2667
|
objectSchema = {
|
|
1232
2668
|
type: "object",
|
|
1233
|
-
required: [requestBody.required ? "$body" : ""],
|
|
2669
|
+
required: [operation.requestBody.required ? "$body" : ""],
|
|
1234
2670
|
properties: {
|
|
1235
2671
|
$body: ctSchema
|
|
1236
2672
|
}
|
|
@@ -1249,11 +2685,11 @@ function generateCode(config) {
|
|
|
1249
2685
|
Object.assign(inputs, bodyInputs(config, objectSchema));
|
|
1250
2686
|
schemas[shortContenTypeMap[type]] = zodDeserialzer.handle(schema, true);
|
|
1251
2687
|
}
|
|
1252
|
-
if (requestBody.content["application/json"]) {
|
|
2688
|
+
if (operation.requestBody.content["application/json"]) {
|
|
1253
2689
|
outgoingContentType = "json";
|
|
1254
|
-
} else if (requestBody.content["application/x-www-form-urlencoded"]) {
|
|
2690
|
+
} else if (operation.requestBody.content["application/x-www-form-urlencoded"]) {
|
|
1255
2691
|
outgoingContentType = "urlencoded";
|
|
1256
|
-
} else if (requestBody.content["multipart/form-data"]) {
|
|
2692
|
+
} else if (operation.requestBody.content["multipart/form-data"]) {
|
|
1257
2693
|
outgoingContentType = "formdata";
|
|
1258
2694
|
} else {
|
|
1259
2695
|
outgoingContentType = "json";
|
|
@@ -1287,11 +2723,11 @@ function generateCode(config) {
|
|
|
1287
2723
|
schemas,
|
|
1288
2724
|
inputs
|
|
1289
2725
|
},
|
|
1290
|
-
{ makeImport: config.makeImport }
|
|
2726
|
+
{ makeImport: config.makeImport, style: config.style }
|
|
1291
2727
|
);
|
|
1292
2728
|
const output = [
|
|
1293
2729
|
`import z from 'zod';`,
|
|
1294
|
-
`import type * as http from '../http';`
|
|
2730
|
+
`import type * as http from '${config.makeImport("../http/index")}';`
|
|
1295
2731
|
];
|
|
1296
2732
|
const responses = endpoint.responses.flatMap((it) => it.responses);
|
|
1297
2733
|
const responsesImports = endpoint.responses.flatMap(
|
|
@@ -1341,14 +2777,13 @@ function generateCode(config) {
|
|
|
1341
2777
|
{}
|
|
1342
2778
|
);
|
|
1343
2779
|
const allSchemas = Object.keys(endpoints).map((it) => ({
|
|
1344
|
-
import: `import ${
|
|
1345
|
-
use: ` ...${
|
|
2780
|
+
import: `import ${camelcase4(it)} from './${config.makeImport(spinalcase2(it))}';`,
|
|
2781
|
+
use: ` ...${camelcase4(it)}`
|
|
1346
2782
|
}));
|
|
1347
2783
|
const imports = [
|
|
1348
2784
|
'import z from "zod";',
|
|
1349
2785
|
`import type { ParseError } from '${config.makeImport("../http/parser")}';`,
|
|
1350
|
-
`import type { ServerError } from '${config.makeImport("../http/response")}'
|
|
1351
|
-
`import type { OutputType, Parser, Type } from '../http/send-request.ts';`
|
|
2786
|
+
`import type { ServerError } from '${config.makeImport("../http/response")}';`
|
|
1352
2787
|
];
|
|
1353
2788
|
return {
|
|
1354
2789
|
groups,
|
|
@@ -1364,12 +2799,9 @@ import type { ParseError } from '${config.makeImport("../http/parser")}';
|
|
|
1364
2799
|
import type { ProblematicResponse, SuccessfulResponse } from '${config.makeImport(
|
|
1365
2800
|
"../http/response"
|
|
1366
2801
|
)}';
|
|
1367
|
-
import type { OutputType, Parser, Type } from '${config.makeImport(
|
|
1368
|
-
"../http/send-request"
|
|
1369
|
-
)}';
|
|
1370
2802
|
|
|
1371
2803
|
import schemas from '${config.makeImport("./schemas")}';
|
|
1372
|
-
|
|
2804
|
+
import type { Unionize } from '${config.makeImport("../http/dispatcher")}';
|
|
1373
2805
|
${template(endpoints_default)({ outputType: config.style?.outputType })}`,
|
|
1374
2806
|
[`${join("api", "schemas.ts")}`]: `${allSchemas.map((it) => it.import).join("\n")}
|
|
1375
2807
|
import { KIND } from "${config.makeImport("../http/index")}";
|
|
@@ -1396,9 +2828,12 @@ ${allSchemas.map((it) => it.use).join(",\n")}
|
|
|
1396
2828
|
...imps,
|
|
1397
2829
|
`import z from 'zod';`,
|
|
1398
2830
|
`import * as http from '${config.makeImport("../http/response")}';`,
|
|
1399
|
-
`import { toRequest, json, urlencoded,
|
|
2831
|
+
`import { toRequest, json, urlencoded, empty, formdata, createUrl, type HeadersInit } from '${config.makeImport("../http/request")}';`,
|
|
1400
2832
|
`import { chunked, buffered } from "${config.makeImport("../http/parse-response")}";`,
|
|
1401
|
-
`import * as ${
|
|
2833
|
+
`import * as ${camelcase4(name)} from '../inputs/${config.makeImport(spinalcase2(name))}';`,
|
|
2834
|
+
`import { createBaseUrlInterceptor, createHeadersInterceptor, type Interceptor } from '${config.makeImport("../http/interceptors")}';`,
|
|
2835
|
+
`import { Dispatcher, fetchType, type InstanceType } from '${config.makeImport("../http/dispatcher")}';`,
|
|
2836
|
+
`import { Pagination, OffsetPagination, CursorPagination } from "${config.makeImport("../pagination/index")}";`
|
|
1402
2837
|
].join(
|
|
1403
2838
|
"\n"
|
|
1404
2839
|
)}
|
|
@@ -1413,8 +2848,8 @@ ${endpoint.flatMap((it) => it.schemas).join(",\n")}
|
|
|
1413
2848
|
};
|
|
1414
2849
|
}
|
|
1415
2850
|
function toProps(spec, schemaOrRef, aggregator = []) {
|
|
1416
|
-
if (
|
|
1417
|
-
const schema =
|
|
2851
|
+
if (isRef10(schemaOrRef)) {
|
|
2852
|
+
const schema = followRef7(spec, schemaOrRef.$ref);
|
|
1418
2853
|
return toProps(spec, schema, aggregator);
|
|
1419
2854
|
} else if (schemaOrRef.type === "object") {
|
|
1420
2855
|
for (const [name] of Object.entries(schemaOrRef.properties ?? {})) {
|
|
@@ -1458,6 +2893,9 @@ function bodyInputs(config, ctSchema) {
|
|
|
1458
2893
|
);
|
|
1459
2894
|
}
|
|
1460
2895
|
|
|
2896
|
+
// packages/typescript/src/lib/http/dispatcher.txt
|
|
2897
|
+
var dispatcher_default = "export type Unionize<T> = T extends [infer Single extends OutputType]\n ? InstanceType<Single>\n : T extends readonly [...infer Tuple extends OutputType[]]\n ? { [I in keyof Tuple]: InstanceType<Tuple[I]> }[number]\n : never;\n\nexport type InstanceType<T> =\n T extends Type<infer U>\n ? U\n : T extends { type: Type<infer U> }\n ? U\n : T extends Array<unknown>\n ? Unionize<T>\n : never;\n\nexport 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 const fetchType = z\n .function()\n .args(z.instanceof(Request))\n .returns(z.promise(z.instanceof(Response)))\n .optional();\n\nexport async function parse<T extends OutputType[]>(\n outputs: T,\n response: Response,\n) <% if(!throwError) { %>\n: Promise<\n [\n Extract<InstanceType<T>, SuccessfulResponse>['data'],\n Extract<InstanceType<T>, ProblematicResponse>['data'],\n ]\n>\n <% } %>\n\n\n\n {\n let output: typeof APIResponse | null = null;\n let parser: Parser = buffered;\n for (const outputType of outputs) {\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\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 as Extract<InstanceType<T>, SuccessfulResponse><% } else { %>apiresponse as Extract<InstanceType<T>, SuccessfulResponse>;<% } %>;\n <% } else { %>\n return [<% if (outputType === 'default') { %>apiresponse.data as Extract<InstanceType<T>, SuccessfulResponse>['data']<% } else { %>apiresponse as Extract<InstanceType<T>, SuccessfulResponse><% } %>, 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, data] 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\nexport class Dispatcher {\n #interceptors: Interceptor[] = [];\n #fetch: z.infer<typeof fetchType>;\n constructor(interceptors: Interceptor[], fetch?: z.infer<typeof fetchType>) {\n this.#interceptors = interceptors;\n this.#fetch = fetch;\n }\n\n async send<T extends OutputType[]>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n ) {\n for (const interceptor of this.#interceptors) {\n if (interceptor.before) {\n config = await interceptor.before(config);\n }\n }\n\n let response = await (this.#fetch ?? fetch)(\n new Request(config.url, config.init),\n {\n ...config.init,\n signal: signal,\n },\n );\n\n for (let i = this.#interceptors.length - 1; i >= 0; i--) {\n const interceptor = this.#interceptors[i];\n if (interceptor.after) {\n response = await interceptor.after(response.clone());\n }\n }\n\n return await parse(outputs, response);\n }\n}\n";
|
|
2898
|
+
|
|
1461
2899
|
// packages/typescript/src/lib/http/interceptors.txt
|
|
1462
2900
|
var interceptors_default = "export interface Interceptor {\n before?: (config: RequestConfig) => Promise<RequestConfig> | RequestConfig;\n after?: (response: Response) => Promise<Response> | Response;\n}\n\nexport const createHeadersInterceptor = (\n defaultHeaders: () => Record<string, string | undefined>,\n requestHeaders: HeadersInit,\n):Interceptor => {\n return {\n before({init, url}) {\n // Priority Levels\n // 1. Headers Input\n // 2. Request Headers\n // 3. Default Headers\n const headers = defaultHeaders();\n\n for (const [key, value] of new Headers(requestHeaders)) {\n // Only set the header if it doesn't already exist and has a value\n // even though these headers are passed at operation level\n // still they are lower priority compared to the headers input\n if (value !== undefined && !init.headers.has(key)) {\n init.headers.set(key, value);\n }\n }\n\n for (const [key, value] of Object.entries(headers)) {\n // Only set the header if it doesn't already exist and has a value\n if (value !== undefined && !init.headers.has(key)) {\n init.headers.set(key, value);\n }\n }\n\n return {init, url};\n },\n };\n};\n\nexport const createBaseUrlInterceptor = (\n getBaseUrl: () => string,\n): Interceptor => {\n return {\n before({ init, url }) {\n const baseUrl = getBaseUrl();\n if (url.protocol === 'local:') {\n return {\n init,\n url: new URL(url.href.replace('local://', baseUrl))\n };\n }\n return { init, url };\n },\n };\n};\n\nexport const logInterceptor: Interceptor = {\n before({ url, init }) {\n console.log('Request:', { url, init });\n return { url, init };\n },\n after(response) {\n console.log('Response:', response);\n return response;\n },\n};\n\n/**\n * Creates an interceptor that logs detailed information about requests and responses.\n * @param options Configuration options for the logger\n * @returns An interceptor object with before and after handlers\n */\nexport const createDetailedLogInterceptor = (options?: {\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\n includeRequestBody?: boolean;\n includeResponseBody?: boolean;\n}) => {\n const logLevel = options?.logLevel || 'info';\n const includeRequestBody = options?.includeRequestBody || false;\n const includeResponseBody = options?.includeResponseBody || false;\n\n return {\n async before(request: Request) {\n const logData = {\n url: request.url,\n method: request.method,\n contentType: request.headers.get('Content-Type'),\n headers: Object.fromEntries([...request.headers.entries()]),\n };\n\n console[logLevel]('\u{1F680} Outgoing Request:', logData);\n\n if (includeRequestBody) {\n try {\n // Clone the request to avoid consuming the body stream\n const clonedRequest = request.clone();\n if (clonedRequest.headers.get('Content-Type')?.includes('application/json')) {\n const body = await clonedRequest.json().catch(() => null);\n console[logLevel]('Request Body:', body);\n } else {\n const body = await clonedRequest.text().catch(() => null);\n console[logLevel]('Request Body:', body);\n }\n } catch (error) {\n console.error('Could not log request body:', error);\n }\n }\n\n return request;\n },\n\n async after(response: Response) {\n const logData = {\n status: response.status,\n statusText: response.statusText,\n url: response.url,\n headers: Object.fromEntries([...response.headers.entries()]),\n };\n\n console[logLevel]('\u{1F4E5} Incoming Response:', logData);\n\n if (includeResponseBody && response.body) {\n try {\n // Clone the response to avoid consuming the body stream\n const clonedResponse = response.clone();\n if (clonedResponse.headers.get('Content-Type')?.includes('application/json')) {\n const body = await clonedResponse.json().catch(() => null);\n console[logLevel]('Response Body:', body);\n } else {\n const body = await clonedResponse.text().catch(() => null);\n if (body) {\n console[logLevel]('Response Body:', body.substring(0, 500) + (body.length > 500 ? '...' : ''));\n } else {\n console[logLevel]('No response body');\n }\n }\n } catch (error) {\n console.error('Could not log response body:', error);\n }\n }\n\n return response;\n },\n };\n};\n";
|
|
1463
2901
|
|
|
@@ -1468,7 +2906,7 @@ var parse_response_default = 'import { parse } from "fast-content-type-parse";\n
|
|
|
1468
2906
|
var parser_default = "import { z } from 'zod';\n\nexport class ParseError<T extends z.ZodType<any, any, any>> {\n public data: z.typeToFlattenedError<T, z.ZodIssue>;\n constructor(data: z.typeToFlattenedError<T, z.ZodIssue>) {\n this.data = data;\n }\n}\n\nexport function parseInput<T extends z.ZodType<any, any, any>>(\n schema: T,\n input: unknown,\n) {\n const result = schema.safeParse(input);\n if (!result.success) {\n const error = result.error.flatten((issue) => issue);\n return [null, new ParseError(error)];\n }\n return [result.data as z.infer<T>, null];\n}\n";
|
|
1469
2907
|
|
|
1470
2908
|
// packages/typescript/src/lib/http/request.txt
|
|
1471
|
-
var request_default = "type Init = Omit<RequestInit, 'headers'> & { headers: Headers; };\nexport type RequestConfig = { init: Init; url: URL };\nexport type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';\nexport type ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart' | 'formdata';\nexport type HeadersInit = [string, string][] | Record<string, string>;\nexport type Endpoint =\n | `${ContentType} ${Method} ${string}`\n | `${Method} ${string}`;\n\nexport type BodyInit =\n | ArrayBuffer\n | Blob\n | FormData\n | URLSearchParams\n | null\n | string;\n\nexport function createUrl(path: string, query: URLSearchParams) {\n const url = new URL(path, `local://`);\n url.search = query.toString();\n return url;\n}\n\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n protected input: Input;\n protected props: Props;\n\n constructor(\n input: Input,\n props: Props,\n ) {\n this.input = input;\n this.props = props;\n }\n\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n if (\n this.props.inputBody.length === 1 &&\n this.props.inputBody[0] === '$body'\n ) {\n return JSON.stringify(this.input.$body);\n }\n\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n };\n }\n}\n\nclass
|
|
2909
|
+
var request_default = "type Init = Omit<RequestInit, 'headers'> & { headers: Headers; };\nexport type RequestConfig = { init: Init; url: URL };\nexport type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';\nexport type ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart' | 'formdata';\nexport type HeadersInit = [string, string][] | Record<string, string>;\nexport type Endpoint =\n | `${ContentType} ${Method} ${string}`\n | `${Method} ${string}`;\n\nexport type BodyInit =\n | ArrayBuffer\n | Blob\n | FormData\n | URLSearchParams\n | null\n | string;\n\nexport function createUrl(path: string, query: URLSearchParams) {\n const url = new URL(path, `local://`);\n url.search = query.toString();\n return url;\n}\n\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n protected input: Input;\n protected props: Props;\n\n constructor(\n input: Input,\n props: Props,\n ) {\n this.input = input;\n this.props = props;\n }\n\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n if (\n this.props.inputBody.length === 1 &&\n this.props.inputBody[0] === '$body'\n ) {\n return JSON.stringify(this.input.$body);\n }\n\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n };\n }\n}\n\nclass EmptySerializer extends Serializer {\n getBody(): BodyInit | null {\n return null;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {\n Accept: 'application/json',\n };\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props).serialize();\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props).serialize();\n}\nexport function empty(input: Input, props: Props) {\n return new EmptySerializer(input, props).serialize();\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props).serialize();\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n input: Serialized,\n): RequestConfig {\n const [method, path] = endpoint.split(' ');\n const pathVariable = template(path, input.params);\n\n return {\n url: createUrl(pathVariable, input.query),\n init: {\n method: method,\n headers: new Headers(input.headers),\n body: method === 'GET' ? undefined : input.body,\n },\n }\n}\n";
|
|
1472
2910
|
|
|
1473
2911
|
// packages/typescript/src/lib/http/response.txt
|
|
1474
2912
|
var response_default = `export const KIND = Symbol('APIDATA');
|
|
@@ -1881,321 +3319,323 @@ export type SuccessfulResponse =
|
|
|
1881
3319
|
| NoContent;
|
|
1882
3320
|
`;
|
|
1883
3321
|
|
|
1884
|
-
// packages/typescript/src/lib/
|
|
1885
|
-
var
|
|
3322
|
+
// packages/typescript/src/lib/paginations/cursor-pagination.txt
|
|
3323
|
+
var cursor_pagination_default = "type CursorPaginationParams = {\n cursor?: string;\n};\n\ninterface CursorMetadata extends Metadata {\n nextCursor?: string;\n}\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends CursorMetadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends CursorMetadata> = (\n input: CursorPaginationParams,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class CursorPagination<T, M extends CursorMetadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: CursorPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n\n constructor(\n initialParams: PartialNullable<CursorPaginationParams>,\n fetchFn: FetchFn<T, M>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = {\n cursor: initialParams.cursor ?? undefined,\n };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n cursor: result.meta.nextCursor,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n\ntype PartialNullable<T> = {\n [K in keyof T]?: T[K] | null;\n};\n";
|
|
1886
3324
|
|
|
1887
|
-
// packages/typescript/src/lib/
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
3325
|
+
// packages/typescript/src/lib/paginations/offset-pagination.txt
|
|
3326
|
+
var offset_pagination_default = "type OffsetPaginationParams = {\n offset: number;\n limit: number;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends Metadata> = (\n input: OffsetPaginationParams,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class OffsetPagination<T, M extends Metadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: OffsetPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n\n constructor(\n initialParams: Partial<OffsetPaginationParams>,\n fetchFn: FetchFn<T, M>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = {\n limit: initialParams.limit ?? 0,\n offset: initialParams.offset ?? 0,\n };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n offset: this.#params.offset + this.#params.limit,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n\n reset(params?: Partial<OffsetPaginationParams>) {\n this.#meta = null;\n this.#currentPage = null;\n if (params) {\n this.#params = { ...this.#params, ...params };\n } else {\n this.#params.offset = 0;\n }\n return this;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
|
|
3327
|
+
|
|
3328
|
+
// packages/typescript/src/lib/paginations/page-pagination.txt
|
|
3329
|
+
var page_pagination_default = "type InferPage<T> = T extends Page<infer U> ? U : never;\ntype PaginationParams<P extends number | bigint, S extends number | bigint> = {\n page?: P;\n pageSize?: S;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> = (input: Partial<PaginationParams<P, S>>) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class Pagination<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: PaginationParams<P, S>;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M, P, S>;\n\n constructor(\n initialParams: Partial<PaginationParams<P, S>>,\n fetchFn: FetchFn<T, M, P, S>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = { ...initialParams, page: initialParams.page };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n page: ((this.#params.page as number) || 0 + 1) as never,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
|
|
3330
|
+
|
|
3331
|
+
// packages/typescript/src/lib/typescript-snippet.ts
|
|
3332
|
+
import { camelcase as camelcase5, spinalcase as spinalcase3 } from "stringcase";
|
|
3333
|
+
import { followRef as followRef9, isEmpty as isEmpty5, isRef as isRef12, pascalcase as pascalcase3 } from "@sdk-it/core";
|
|
3334
|
+
|
|
3335
|
+
// packages/typescript/src/lib/emitters/snippet.ts
|
|
3336
|
+
import { followRef as followRef8, isRef as isRef11 } from "@sdk-it/core";
|
|
3337
|
+
var SnippetEmitter = class {
|
|
3338
|
+
spec;
|
|
3339
|
+
generatedRefs = /* @__PURE__ */ new Set();
|
|
3340
|
+
cache = /* @__PURE__ */ new Map();
|
|
1891
3341
|
constructor(spec) {
|
|
1892
|
-
this
|
|
3342
|
+
this.spec = spec;
|
|
1893
3343
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
const
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
const isRequired = (schema.required ?? []).includes(propName);
|
|
1904
|
-
lines.push(...this.#property(propName, propSchema, isRequired));
|
|
3344
|
+
object(schema) {
|
|
3345
|
+
const schemaObj = isRef11(schema) ? followRef8(this.spec, schema.$ref) : schema;
|
|
3346
|
+
const result = {};
|
|
3347
|
+
const properties = schemaObj.properties || {};
|
|
3348
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
3349
|
+
const isRequired = (schemaObj.required ?? []).includes(propName);
|
|
3350
|
+
const resolvedProp = isRef11(propSchema) ? followRef8(this.spec, propSchema.$ref) : propSchema;
|
|
3351
|
+
if (isRequired || resolvedProp.example !== void 0 || resolvedProp.default !== void 0 || Math.random() > 0.5) {
|
|
3352
|
+
result[propName] = this.handle(propSchema);
|
|
1905
3353
|
}
|
|
1906
3354
|
}
|
|
1907
|
-
if (
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
} else {
|
|
1912
|
-
lines.push(
|
|
1913
|
-
...this.handle(schema.additionalProperties).map((l) => ` ${l}`)
|
|
1914
|
-
);
|
|
1915
|
-
}
|
|
3355
|
+
if (schemaObj.additionalProperties && typeof schemaObj.additionalProperties === "object") {
|
|
3356
|
+
result["additionalPropExample"] = this.handle(
|
|
3357
|
+
schemaObj.additionalProperties
|
|
3358
|
+
);
|
|
1916
3359
|
}
|
|
1917
|
-
return
|
|
3360
|
+
return result;
|
|
1918
3361
|
}
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
const
|
|
1926
|
-
const
|
|
1927
|
-
|
|
1928
|
-
|
|
3362
|
+
array(schema) {
|
|
3363
|
+
const schemaObj = isRef11(schema) ? followRef8(this.spec, schema.$ref) : schema;
|
|
3364
|
+
const itemsSchema = schemaObj.items;
|
|
3365
|
+
if (!itemsSchema) {
|
|
3366
|
+
return [];
|
|
3367
|
+
}
|
|
3368
|
+
const count = Math.min(schemaObj.minItems ?? 1, 2);
|
|
3369
|
+
const result = [];
|
|
3370
|
+
for (let i = 0; i < count; i++) {
|
|
3371
|
+
result.push(this.handle(itemsSchema));
|
|
3372
|
+
}
|
|
3373
|
+
return result;
|
|
1929
3374
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
3375
|
+
string(schema) {
|
|
3376
|
+
if (schema.example !== void 0)
|
|
3377
|
+
return String(schema.example);
|
|
3378
|
+
if (schema.default !== void 0)
|
|
3379
|
+
return String(schema.default);
|
|
3380
|
+
switch (schema.format) {
|
|
3381
|
+
case "date-time":
|
|
3382
|
+
case "datetime":
|
|
3383
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3384
|
+
case "date":
|
|
3385
|
+
return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3386
|
+
case "time":
|
|
3387
|
+
return (/* @__PURE__ */ new Date()).toISOString().split("T")[1];
|
|
3388
|
+
case "email":
|
|
3389
|
+
return "user@example.com";
|
|
3390
|
+
case "uuid":
|
|
3391
|
+
return "123e4567-e89b-12d3-a456-426614174000";
|
|
3392
|
+
case "uri":
|
|
3393
|
+
case "url":
|
|
3394
|
+
return "https://example.com";
|
|
3395
|
+
case "ipv4":
|
|
3396
|
+
return "192.168.1.1";
|
|
3397
|
+
case "ipv6":
|
|
3398
|
+
return "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
|
|
3399
|
+
case "hostname":
|
|
3400
|
+
return "example.com";
|
|
3401
|
+
case "binary":
|
|
3402
|
+
case "byte":
|
|
3403
|
+
return "[binary data]";
|
|
3404
|
+
default:
|
|
3405
|
+
if (schema.enum && schema.enum.length > 0) {
|
|
3406
|
+
return String(schema.enum[0]);
|
|
3407
|
+
}
|
|
3408
|
+
return schema.pattern ? `string matching ${schema.pattern}` : "example";
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
number(schema) {
|
|
3412
|
+
if (schema.example !== void 0)
|
|
3413
|
+
return Number(schema.example);
|
|
3414
|
+
if (schema.default !== void 0)
|
|
3415
|
+
return Number(schema.default);
|
|
3416
|
+
let value;
|
|
3417
|
+
if (typeof schema.exclusiveMinimum === "number") {
|
|
3418
|
+
value = schema.exclusiveMinimum + 1;
|
|
3419
|
+
} else if (typeof schema.minimum === "number") {
|
|
3420
|
+
value = schema.minimum;
|
|
1939
3421
|
} else {
|
|
1940
|
-
|
|
3422
|
+
value = schema.type === "integer" ? 42 : 42.42;
|
|
1941
3423
|
}
|
|
1942
|
-
if (schema.
|
|
1943
|
-
|
|
1944
|
-
if (schema.
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
3424
|
+
if (typeof schema.exclusiveMaximum === "number" && value >= schema.exclusiveMaximum) {
|
|
3425
|
+
value = schema.exclusiveMaximum - 1;
|
|
3426
|
+
} else if (typeof schema.maximum === "number" && value > schema.maximum) {
|
|
3427
|
+
value = schema.maximum;
|
|
3428
|
+
}
|
|
3429
|
+
if (typeof schema.multipleOf === "number" && value % schema.multipleOf !== 0) {
|
|
3430
|
+
value = Math.floor(value / schema.multipleOf) * schema.multipleOf;
|
|
3431
|
+
}
|
|
3432
|
+
return schema.type === "integer" ? Math.floor(value) : value;
|
|
1949
3433
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
3434
|
+
boolean(schema) {
|
|
3435
|
+
if (schema.example !== void 0)
|
|
3436
|
+
return Boolean(schema.example);
|
|
3437
|
+
if (schema.default !== void 0)
|
|
3438
|
+
return Boolean(schema.default);
|
|
3439
|
+
return true;
|
|
3440
|
+
}
|
|
3441
|
+
null() {
|
|
3442
|
+
return null;
|
|
3443
|
+
}
|
|
3444
|
+
ref($ref) {
|
|
3445
|
+
const parts = $ref.split("/");
|
|
3446
|
+
const refKey = parts[parts.length - 1] || "";
|
|
3447
|
+
if (this.cache.has($ref)) {
|
|
3448
|
+
return this.cache.get($ref);
|
|
1958
3449
|
}
|
|
1959
|
-
|
|
3450
|
+
this.cache.set($ref, { _ref: refKey });
|
|
3451
|
+
const resolved = followRef8(this.spec, $ref);
|
|
3452
|
+
const result = this.handle(resolved);
|
|
3453
|
+
this.cache.set($ref, result);
|
|
3454
|
+
return result;
|
|
1960
3455
|
}
|
|
1961
|
-
|
|
1962
|
-
const
|
|
1963
|
-
schemas.
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
3456
|
+
allOf(schemas) {
|
|
3457
|
+
const initial = {};
|
|
3458
|
+
return schemas.reduce((result, schema) => {
|
|
3459
|
+
const example = this.handle(schema);
|
|
3460
|
+
if (typeof example === "object" && example !== null) {
|
|
3461
|
+
return { ...result, ...example };
|
|
3462
|
+
}
|
|
3463
|
+
return result;
|
|
3464
|
+
}, initial);
|
|
1969
3465
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
const subLines = this.handle(subSchema);
|
|
1975
|
-
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1976
|
-
});
|
|
1977
|
-
return lines;
|
|
3466
|
+
anyOf(schemas) {
|
|
3467
|
+
if (schemas.length === 0)
|
|
3468
|
+
return {};
|
|
3469
|
+
return this.handle(schemas[0]);
|
|
1978
3470
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
const subLines = this.handle(subSchema);
|
|
1984
|
-
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1985
|
-
});
|
|
1986
|
-
return lines;
|
|
3471
|
+
oneOf(schemas) {
|
|
3472
|
+
if (schemas.length === 0)
|
|
3473
|
+
return {};
|
|
3474
|
+
return this.handle(schemas[0]);
|
|
1987
3475
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
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;
|
|
3476
|
+
enum(schema) {
|
|
3477
|
+
return Array.isArray(schema.enum) && schema.enum.length > 0 ? schema.enum[0] : void 0;
|
|
2000
3478
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
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);
|
|
3479
|
+
handle(schemaOrRef) {
|
|
3480
|
+
if (isRef11(schemaOrRef)) {
|
|
3481
|
+
return this.ref(schemaOrRef.$ref);
|
|
2078
3482
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
3483
|
+
const schema = isRef11(schemaOrRef) ? followRef8(this.spec, schemaOrRef.$ref) : schemaOrRef;
|
|
3484
|
+
if (schema.example !== void 0) {
|
|
3485
|
+
return schema.example;
|
|
2081
3486
|
}
|
|
2082
|
-
|
|
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);
|
|
3487
|
+
if (schema.default !== void 0) {
|
|
3488
|
+
return schema.default;
|
|
2090
3489
|
}
|
|
2091
|
-
const schema = schemaOrRef;
|
|
2092
3490
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
2093
|
-
return this
|
|
3491
|
+
return this.allOf(schema.allOf);
|
|
2094
3492
|
}
|
|
2095
3493
|
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
2096
|
-
return this
|
|
3494
|
+
return this.anyOf(schema.anyOf);
|
|
2097
3495
|
}
|
|
2098
3496
|
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
2099
|
-
return this
|
|
3497
|
+
return this.oneOf(schema.oneOf);
|
|
2100
3498
|
}
|
|
2101
|
-
if (schema.enum && Array.isArray(schema.enum)) {
|
|
2102
|
-
return this
|
|
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");
|
|
3499
|
+
if (schema.enum && Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
3500
|
+
return this.enum(schema);
|
|
2109
3501
|
}
|
|
3502
|
+
const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
2110
3503
|
if (types.length === 0) {
|
|
2111
3504
|
if (schema.properties || schema.additionalProperties) {
|
|
2112
|
-
|
|
3505
|
+
return this.object(schema);
|
|
2113
3506
|
} else if (schema.items) {
|
|
2114
|
-
|
|
3507
|
+
return this.array(schema);
|
|
2115
3508
|
}
|
|
3509
|
+
return "example";
|
|
2116
3510
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
3511
|
+
const primaryType = types.find((t) => t !== "null") || types[0];
|
|
3512
|
+
switch (primaryType) {
|
|
3513
|
+
case "string":
|
|
3514
|
+
return this.string(schema);
|
|
3515
|
+
case "number":
|
|
3516
|
+
case "integer":
|
|
3517
|
+
return this.number(schema);
|
|
3518
|
+
case "boolean":
|
|
3519
|
+
return this.boolean(schema);
|
|
3520
|
+
case "object":
|
|
3521
|
+
return this.object(schema);
|
|
3522
|
+
case "array":
|
|
3523
|
+
return this.array(schema);
|
|
3524
|
+
case "null":
|
|
3525
|
+
return this.null();
|
|
3526
|
+
default:
|
|
3527
|
+
return "unknown";
|
|
2127
3528
|
}
|
|
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
3529
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
}
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
3530
|
+
};
|
|
3531
|
+
|
|
3532
|
+
// packages/typescript/src/lib/typescript-snippet.ts
|
|
3533
|
+
var TypeScriptGenerator = class {
|
|
3534
|
+
#spec;
|
|
3535
|
+
#settings;
|
|
3536
|
+
#snippetEmitter;
|
|
3537
|
+
#clientName;
|
|
3538
|
+
#packageName;
|
|
3539
|
+
constructor(spec, settings) {
|
|
3540
|
+
this.#spec = spec;
|
|
3541
|
+
this.#settings = settings;
|
|
3542
|
+
this.#snippetEmitter = new SnippetEmitter(spec);
|
|
3543
|
+
this.#clientName = settings.name?.trim() ? pascalcase3(settings.name) : "Client";
|
|
3544
|
+
this.#packageName = settings.name ? `@${spinalcase3(this.#clientName.toLowerCase())}/sdk` : "sdk";
|
|
3545
|
+
}
|
|
3546
|
+
succinct(entry, operation, values) {
|
|
3547
|
+
let payload = "{}";
|
|
3548
|
+
if (!isEmpty5(operation.requestBody)) {
|
|
3549
|
+
const contentTypes = Object.keys(operation.requestBody.content || {});
|
|
3550
|
+
if (contentTypes.length > 0) {
|
|
3551
|
+
const firstContent = operation.requestBody.content[contentTypes[0]];
|
|
3552
|
+
let schema = isRef12(firstContent.schema) ? followRef9(this.#spec, firstContent.schema.$ref) : firstContent.schema;
|
|
3553
|
+
if (schema) {
|
|
3554
|
+
if (schema.type !== "object") {
|
|
3555
|
+
schema = {
|
|
3556
|
+
type: "object",
|
|
3557
|
+
required: [operation.requestBody.required ? "$body" : ""],
|
|
3558
|
+
properties: {
|
|
3559
|
+
$body: schema
|
|
3560
|
+
}
|
|
3561
|
+
};
|
|
3562
|
+
}
|
|
3563
|
+
const properties = {};
|
|
3564
|
+
patchParameters(
|
|
3565
|
+
this.#spec,
|
|
3566
|
+
{ type: "object", properties },
|
|
3567
|
+
operation
|
|
3568
|
+
);
|
|
3569
|
+
const examplePayload = this.#snippetEmitter.handle({
|
|
3570
|
+
...schema,
|
|
3571
|
+
properties: Object.assign({}, properties, schema.properties)
|
|
3572
|
+
});
|
|
3573
|
+
Object.assign(
|
|
3574
|
+
examplePayload,
|
|
3575
|
+
values.requestBody ?? {},
|
|
3576
|
+
values.pathParameters ?? {},
|
|
3577
|
+
values.queryParameters ?? {},
|
|
3578
|
+
values.headers ?? {},
|
|
3579
|
+
values.cookies ?? {}
|
|
3580
|
+
);
|
|
3581
|
+
payload = JSON.stringify(examplePayload, null, 2);
|
|
2160
3582
|
}
|
|
2161
3583
|
}
|
|
3584
|
+
} else {
|
|
3585
|
+
const properties = {};
|
|
3586
|
+
patchParameters(this.#spec, { type: "object", properties }, operation);
|
|
3587
|
+
const examplePayload = this.#snippetEmitter.handle({
|
|
3588
|
+
properties
|
|
3589
|
+
});
|
|
3590
|
+
Object.assign(
|
|
3591
|
+
examplePayload,
|
|
3592
|
+
values.pathParameters ?? {},
|
|
3593
|
+
values.queryParameters ?? {},
|
|
3594
|
+
values.headers ?? {},
|
|
3595
|
+
values.cookies ?? {}
|
|
3596
|
+
);
|
|
3597
|
+
payload = JSON.stringify(examplePayload, null, 2);
|
|
2162
3598
|
}
|
|
2163
|
-
return
|
|
3599
|
+
return `const result = await ${camelcase5(this.#clientName)}.request('${entry.method.toUpperCase()} ${entry.path}', ${payload});`;
|
|
3600
|
+
}
|
|
3601
|
+
snippet(entry, operation) {
|
|
3602
|
+
const payload = this.succinct(entry, operation, {});
|
|
3603
|
+
return [
|
|
3604
|
+
"```typescript",
|
|
3605
|
+
`${this.client()}
|
|
3606
|
+
${payload}
|
|
3607
|
+
|
|
3608
|
+
console.log(result.data);
|
|
3609
|
+
`,
|
|
3610
|
+
"```"
|
|
3611
|
+
].join("\n");
|
|
3612
|
+
}
|
|
3613
|
+
client() {
|
|
3614
|
+
return `import { ${this.#clientName} } from '${this.#packageName}';
|
|
3615
|
+
|
|
3616
|
+
const ${camelcase5(this.#clientName)} = new ${this.#clientName}({
|
|
3617
|
+
baseUrl: '${this.#spec.servers?.[0]?.url ?? "http://localhost:3000"}',
|
|
3618
|
+
});`;
|
|
2164
3619
|
}
|
|
2165
3620
|
};
|
|
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
3621
|
|
|
2192
3622
|
// packages/typescript/src/lib/generate.ts
|
|
3623
|
+
var ALWAYS_AVAILABLE_FILES = [
|
|
3624
|
+
/readme\.md$/i,
|
|
3625
|
+
// match readme.md, case-insensitive
|
|
3626
|
+
/^tsconfig.*\.json$/,
|
|
3627
|
+
// match any tsconfig*.json
|
|
3628
|
+
/package\.json$/,
|
|
3629
|
+
// exact package.json
|
|
3630
|
+
/metadata\.json$/
|
|
3631
|
+
// exact metadata.json
|
|
3632
|
+
];
|
|
2193
3633
|
function security(spec) {
|
|
2194
3634
|
const security2 = spec.security || [];
|
|
2195
3635
|
const components = spec.components || {};
|
|
2196
3636
|
const securitySchemes = components.securitySchemes || {};
|
|
2197
3637
|
const paths = Object.values(spec.paths ?? {});
|
|
2198
|
-
const options =
|
|
3638
|
+
const options = securityToOptions2(spec, security2, securitySchemes);
|
|
2199
3639
|
for (const it of paths) {
|
|
2200
3640
|
for (const method of methods) {
|
|
2201
3641
|
const operation = it[method];
|
|
@@ -2204,13 +3644,20 @@ function security(spec) {
|
|
|
2204
3644
|
}
|
|
2205
3645
|
Object.assign(
|
|
2206
3646
|
options,
|
|
2207
|
-
|
|
3647
|
+
securityToOptions2(
|
|
3648
|
+
spec,
|
|
3649
|
+
operation.security || [],
|
|
3650
|
+
securitySchemes,
|
|
3651
|
+
"input"
|
|
3652
|
+
)
|
|
2208
3653
|
);
|
|
2209
3654
|
}
|
|
2210
3655
|
}
|
|
2211
3656
|
return options;
|
|
2212
3657
|
}
|
|
2213
3658
|
async function generate(spec, settings) {
|
|
3659
|
+
spec = "x-sdk-augmented" in spec ? spec : augmentSpec({ spec });
|
|
3660
|
+
const generator = new TypeScriptGenerator(spec, settings);
|
|
2214
3661
|
const style = Object.assign(
|
|
2215
3662
|
{},
|
|
2216
3663
|
{
|
|
@@ -2220,7 +3667,29 @@ async function generate(spec, settings) {
|
|
|
2220
3667
|
},
|
|
2221
3668
|
settings.style ?? {}
|
|
2222
3669
|
);
|
|
3670
|
+
const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
|
|
2223
3671
|
settings.useTsExtension ??= true;
|
|
3672
|
+
const writtenFiles = /* @__PURE__ */ new Set();
|
|
3673
|
+
settings.writer ??= writeFiles;
|
|
3674
|
+
const originalWriter = settings.writer;
|
|
3675
|
+
settings.writer = async (dir, contents) => {
|
|
3676
|
+
await originalWriter(dir, contents);
|
|
3677
|
+
for (const file of Object.keys(contents)) {
|
|
3678
|
+
if (contents[file] !== null) {
|
|
3679
|
+
writtenFiles.add(
|
|
3680
|
+
addLeadingSlash(`${relative(settings.output, dir)}/${file}`)
|
|
3681
|
+
);
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
};
|
|
3685
|
+
settings.readFolder ??= async (folder) => {
|
|
3686
|
+
const files = await readdir(folder, { withFileTypes: true });
|
|
3687
|
+
return files.map((file) => ({
|
|
3688
|
+
fileName: file.name,
|
|
3689
|
+
filePath: join2(file.parentPath, file.name),
|
|
3690
|
+
isFolder: file.isDirectory()
|
|
3691
|
+
}));
|
|
3692
|
+
};
|
|
2224
3693
|
const makeImport = (moduleSpecifier) => {
|
|
2225
3694
|
return settings.useTsExtension ? `${moduleSpecifier}.ts` : moduleSpecifier;
|
|
2226
3695
|
};
|
|
@@ -2231,37 +3700,34 @@ async function generate(spec, settings) {
|
|
|
2231
3700
|
makeImport
|
|
2232
3701
|
}
|
|
2233
3702
|
);
|
|
2234
|
-
const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
|
|
2235
3703
|
const options = security(spec);
|
|
2236
|
-
const clientName =
|
|
2237
|
-
const
|
|
3704
|
+
const clientName = pascalcase4((settings.name || "client").trim());
|
|
3705
|
+
const packageName = settings.name ? `@${spinalcase4(settings.name.trim().toLowerCase())}/sdk` : "sdk";
|
|
2238
3706
|
const inputFiles = generateInputs(groups, commonZod, makeImport);
|
|
2239
|
-
|
|
2240
|
-
await writeFiles(output, {
|
|
3707
|
+
await settings.writer(output, {
|
|
2241
3708
|
"outputs/.gitkeep": "",
|
|
2242
3709
|
"inputs/.gitkeep": "",
|
|
2243
3710
|
"models/.getkeep": ""
|
|
2244
3711
|
});
|
|
2245
|
-
await
|
|
2246
|
-
"interceptors.ts": `
|
|
2247
|
-
import type { RequestConfig, HeadersInit } from './${makeImport("request")}';
|
|
2248
|
-
${interceptors_default}`,
|
|
3712
|
+
await settings.writer(join2(output, "http"), {
|
|
2249
3713
|
"parse-response.ts": parse_response_default,
|
|
2250
|
-
"send-request.ts": `import z from 'zod';
|
|
2251
|
-
import type { Interceptor } from './${makeImport("interceptors")}';
|
|
2252
|
-
import { buffered } from './${makeImport("parse-response")}';
|
|
2253
|
-
import { parseInput } from './${makeImport("parser")}';
|
|
2254
|
-
import type { RequestConfig } from './${makeImport("request")}';
|
|
2255
|
-
import { APIError, APIResponse } from './${makeImport("response")}';
|
|
2256
|
-
|
|
2257
|
-
${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputType: style.outputType })}`,
|
|
2258
3714
|
"response.ts": response_default,
|
|
2259
3715
|
"parser.ts": parser_default,
|
|
2260
|
-
"request.ts": request_default
|
|
3716
|
+
"request.ts": request_default,
|
|
3717
|
+
"dispatcher.ts": `import z from 'zod';
|
|
3718
|
+
import { type Interceptor } from '${makeImport("../http/interceptors")}';
|
|
3719
|
+
import { type RequestConfig } from '${makeImport("../http/request")}';
|
|
3720
|
+
import { buffered } from '${makeImport("./parse-response")}';
|
|
3721
|
+
import { APIError, APIResponse, type SuccessfulResponse, type ProblematicResponse } from '${makeImport("./response")}';
|
|
3722
|
+
|
|
3723
|
+
${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputType: style.outputType })}`,
|
|
3724
|
+
"interceptors.ts": `
|
|
3725
|
+
import type { RequestConfig, HeadersInit } from './${makeImport("request")}';
|
|
3726
|
+
${interceptors_default}`
|
|
2261
3727
|
});
|
|
2262
|
-
await
|
|
3728
|
+
await settings.writer(join2(output, "outputs"), outputs);
|
|
2263
3729
|
const modelsImports = Object.entries(commonSchemas).map(([name]) => name);
|
|
2264
|
-
await
|
|
3730
|
+
await settings.writer(output, {
|
|
2265
3731
|
"client.ts": client_default(
|
|
2266
3732
|
{
|
|
2267
3733
|
name: clientName,
|
|
@@ -2286,37 +3752,90 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2286
3752
|
])
|
|
2287
3753
|
)
|
|
2288
3754
|
});
|
|
3755
|
+
await settings.writer(join2(output, "pagination"), {
|
|
3756
|
+
"cursor-pagination.ts": cursor_pagination_default,
|
|
3757
|
+
"offset-pagination.ts": offset_pagination_default,
|
|
3758
|
+
"page-pagination.ts": page_pagination_default
|
|
3759
|
+
});
|
|
3760
|
+
const metadata = await readJson(join2(settings.output, "metadata.json"));
|
|
3761
|
+
metadata.content.generatedFiles = Array.from(writtenFiles);
|
|
3762
|
+
metadata.content.userFiles ??= [];
|
|
3763
|
+
await metadata.write(metadata.content);
|
|
3764
|
+
if (settings.cleanup !== false && metadata.content.generatedFiles) {
|
|
3765
|
+
const generated = metadata.content.generatedFiles;
|
|
3766
|
+
const user = metadata.content.userFiles;
|
|
3767
|
+
const keep = /* @__PURE__ */ new Set([...generated, ...user]);
|
|
3768
|
+
const actualFiles = await readFolder(settings.output, true);
|
|
3769
|
+
const toRemove = actualFiles.filter((f) => !keep.has(addLeadingSlash(f))).filter(
|
|
3770
|
+
(f) => !ALWAYS_AVAILABLE_FILES.some((pattern) => pattern.test(f))
|
|
3771
|
+
);
|
|
3772
|
+
for (const file of toRemove) {
|
|
3773
|
+
if (file.endsWith(`${sep}index.ts`)) {
|
|
3774
|
+
continue;
|
|
3775
|
+
}
|
|
3776
|
+
const filePath = join2(settings.output, file);
|
|
3777
|
+
await unlink(filePath);
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
2289
3780
|
const folders = [
|
|
2290
|
-
getFolderExports(
|
|
3781
|
+
getFolderExports(
|
|
3782
|
+
join2(output, "outputs"),
|
|
3783
|
+
settings.readFolder,
|
|
3784
|
+
settings.useTsExtension
|
|
3785
|
+
),
|
|
2291
3786
|
getFolderExports(
|
|
2292
3787
|
join2(output, "inputs"),
|
|
3788
|
+
settings.readFolder,
|
|
2293
3789
|
settings.useTsExtension,
|
|
2294
3790
|
["ts"],
|
|
2295
|
-
(dirent) => dirent.
|
|
3791
|
+
(dirent) => dirent.isFolder && ["schemas"].includes(dirent.fileName)
|
|
3792
|
+
),
|
|
3793
|
+
getFolderExports(
|
|
3794
|
+
join2(output, "api"),
|
|
3795
|
+
settings.readFolder,
|
|
3796
|
+
settings.useTsExtension
|
|
2296
3797
|
),
|
|
2297
|
-
getFolderExports(join2(output, "api"), settings.useTsExtension),
|
|
2298
3798
|
getFolderExports(
|
|
2299
3799
|
join2(output, "http"),
|
|
3800
|
+
settings.readFolder,
|
|
2300
3801
|
settings.useTsExtension,
|
|
2301
3802
|
["ts"],
|
|
2302
|
-
(dirent) => !["response.ts", "parser.ts"].includes(dirent.
|
|
3803
|
+
(dirent) => !["response.ts", "parser.ts"].includes(dirent.fileName)
|
|
2303
3804
|
)
|
|
2304
3805
|
];
|
|
2305
3806
|
if (modelsImports.length) {
|
|
2306
3807
|
folders.push(
|
|
2307
|
-
getFolderExports(
|
|
3808
|
+
getFolderExports(
|
|
3809
|
+
join2(output, "models"),
|
|
3810
|
+
settings.readFolder,
|
|
3811
|
+
settings.useTsExtension
|
|
3812
|
+
)
|
|
2308
3813
|
);
|
|
2309
3814
|
}
|
|
2310
3815
|
const [outputIndex, inputsIndex, apiIndex, httpIndex, modelsIndex] = await Promise.all(folders);
|
|
2311
|
-
await
|
|
3816
|
+
await settings.writer(join2(output, "pagination"), {
|
|
3817
|
+
"index.ts": await getFolderExports(
|
|
3818
|
+
join2(output, "pagination"),
|
|
3819
|
+
settings.readFolder,
|
|
3820
|
+
settings.useTsExtension,
|
|
3821
|
+
["ts"]
|
|
3822
|
+
)
|
|
3823
|
+
});
|
|
3824
|
+
await settings.writer(output, {
|
|
2312
3825
|
"api/index.ts": apiIndex,
|
|
2313
3826
|
"outputs/index.ts": outputIndex,
|
|
2314
3827
|
"inputs/index.ts": inputsIndex || null,
|
|
2315
3828
|
"http/index.ts": httpIndex,
|
|
2316
3829
|
...modelsImports.length ? { "models/index.ts": modelsIndex } : {}
|
|
2317
3830
|
});
|
|
2318
|
-
await
|
|
2319
|
-
"index.ts": await getFolderExports(
|
|
3831
|
+
await settings.writer(output, {
|
|
3832
|
+
"index.ts": await getFolderExports(
|
|
3833
|
+
output,
|
|
3834
|
+
settings.readFolder,
|
|
3835
|
+
settings.useTsExtension,
|
|
3836
|
+
["ts"],
|
|
3837
|
+
(config) => config.fileName.endsWith("pagination")
|
|
3838
|
+
)
|
|
2320
3839
|
});
|
|
2321
3840
|
if (settings.mode === "full") {
|
|
2322
3841
|
const configFiles = {
|
|
@@ -2324,9 +3843,23 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2324
3843
|
ignoreIfExists: true,
|
|
2325
3844
|
content: JSON.stringify(
|
|
2326
3845
|
{
|
|
2327
|
-
name:
|
|
3846
|
+
name: packageName,
|
|
3847
|
+
version: "0.0.1",
|
|
2328
3848
|
type: "module",
|
|
2329
3849
|
main: "./src/index.ts",
|
|
3850
|
+
module: "./src/index.ts",
|
|
3851
|
+
types: "./src/index.ts",
|
|
3852
|
+
publishConfig: {
|
|
3853
|
+
access: "public"
|
|
3854
|
+
},
|
|
3855
|
+
exports: {
|
|
3856
|
+
"./package.json": "./package.json",
|
|
3857
|
+
".": {
|
|
3858
|
+
types: "./src/index.ts",
|
|
3859
|
+
import: "./src/index.ts",
|
|
3860
|
+
default: "./src/index.ts"
|
|
3861
|
+
}
|
|
3862
|
+
},
|
|
2330
3863
|
dependencies: {
|
|
2331
3864
|
"fast-content-type-parse": "^3.0.0",
|
|
2332
3865
|
zod: "^3.24.2"
|
|
@@ -2359,33 +3892,31 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2359
3892
|
)
|
|
2360
3893
|
}
|
|
2361
3894
|
};
|
|
2362
|
-
if (readme) {
|
|
3895
|
+
if (settings.readme) {
|
|
2363
3896
|
configFiles["README.md"] = {
|
|
2364
|
-
ignoreIfExists:
|
|
2365
|
-
content:
|
|
3897
|
+
ignoreIfExists: false,
|
|
3898
|
+
content: toReadme(spec, {
|
|
3899
|
+
generateSnippet: (...args) => generator.snippet(...args)
|
|
3900
|
+
})
|
|
2366
3901
|
};
|
|
2367
3902
|
}
|
|
2368
|
-
await
|
|
3903
|
+
await settings.writer(settings.output, configFiles);
|
|
2369
3904
|
}
|
|
2370
3905
|
await settings.formatCode?.({
|
|
2371
3906
|
output,
|
|
2372
3907
|
env: npmRunPathEnv()
|
|
2373
3908
|
});
|
|
2374
3909
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
nodeWatch(path, {
|
|
2382
|
-
persistent: true,
|
|
2383
|
-
recursive: true
|
|
2384
|
-
})
|
|
2385
|
-
).pipe(debounceTime(400));
|
|
3910
|
+
async function readJson(path) {
|
|
3911
|
+
const content = await exist(path) ? JSON.parse(await readFile(path, "utf-8")) : { content: {} };
|
|
3912
|
+
return {
|
|
3913
|
+
content,
|
|
3914
|
+
write: (value = content) => writeFile(path, JSON.stringify(value, null, 2), "utf-8")
|
|
3915
|
+
};
|
|
2386
3916
|
}
|
|
2387
3917
|
export {
|
|
3918
|
+
TypeScriptGenerator,
|
|
2388
3919
|
generate,
|
|
2389
|
-
|
|
3920
|
+
readJson
|
|
2390
3921
|
};
|
|
2391
3922
|
//# sourceMappingURL=index.js.map
|