@sdk-it/typescript 0.19.1 → 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 +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2171 -355
- package/dist/index.js.map +4 -4
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/emitters/interface.d.ts +2 -2
- 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 +2 -2
- package/dist/lib/emitters/zod.d.ts.map +1 -1
- package/dist/lib/generate.d.ts +6 -17
- 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/index.js
CHANGED
|
@@ -1,183 +1,1348 @@
|
|
|
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 {
|
|
7
|
-
|
|
8
|
-
// packages/typescript/src/lib/client.ts
|
|
9
|
-
import { toLitObject } from "@sdk-it/core";
|
|
10
|
-
var client_default = (spec, style) => {
|
|
11
|
-
const optionsEntries = Object.entries(spec.options).map(
|
|
12
|
-
([key, value]) => [`'${key}'`, value]
|
|
13
|
-
);
|
|
14
|
-
const defaultHeaders = `{${optionsEntries.filter(([, value]) => value.in === "header").map(
|
|
15
|
-
([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
|
|
16
|
-
).join(",\n")}}`;
|
|
17
|
-
const defaultInputs = `{${optionsEntries.filter(([, value]) => value.in === "input").map(
|
|
18
|
-
([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
|
|
19
|
-
).join(",\n")}}`;
|
|
20
|
-
const specOptions = {
|
|
21
|
-
...Object.fromEntries(
|
|
22
|
-
optionsEntries.map(([key, value]) => [value.optionName ?? key, value])
|
|
23
|
-
),
|
|
24
|
-
fetch: {
|
|
25
|
-
schema: "fetchType"
|
|
26
|
-
},
|
|
27
|
-
baseUrl: {
|
|
28
|
-
schema: spec.servers.length ? `z.enum(servers).default(servers[0])` : "z.string()"
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
return `
|
|
32
|
-
import type { HeadersInit, RequestConfig } from './http/${spec.makeImport("request")}';
|
|
33
|
-
import { fetchType, dispatch, parse } from './http/${spec.makeImport("send-request")}';
|
|
34
|
-
import z from 'zod';
|
|
35
|
-
import type { Endpoints } from './api/${spec.makeImport("endpoints")}';
|
|
36
|
-
import schemas from './api/${spec.makeImport("schemas")}';
|
|
397
|
+
import { spinalcase as spinalcase4 } from "stringcase";
|
|
398
|
+
import { methods, pascalcase as pascalcase4 } from "@sdk-it/core";
|
|
37
399
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
400
|
+
addLeadingSlash,
|
|
401
|
+
exist,
|
|
402
|
+
getFolderExports,
|
|
403
|
+
readFolder,
|
|
404
|
+
writeFiles
|
|
405
|
+
} from "@sdk-it/core/file-system.js";
|
|
406
|
+
|
|
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
|
+
}
|
|
54
462
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const route = schemas[endpoint];
|
|
62
|
-
const result = await dispatch(Object.assign(this.#defaultInputs, input), route, {
|
|
63
|
-
fetch: this.options.fetch,
|
|
64
|
-
interceptors: [
|
|
65
|
-
createHeadersInterceptor(() => this.defaultHeaders, options?.headers ?? {}),
|
|
66
|
-
createBaseUrlInterceptor(() => this.options.baseUrl),
|
|
67
|
-
],
|
|
68
|
-
signal: options?.signal,
|
|
69
|
-
});
|
|
70
|
-
return ${style.errorAsValue ? `result as [Endpoints[E]['output'], Endpoints[E]['error'] | null]` : `result as Endpoints[E]['output']`};
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
var PropEmitter = class {
|
|
466
|
+
#spec;
|
|
467
|
+
constructor(spec) {
|
|
468
|
+
this.#spec = spec;
|
|
71
469
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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()})`
|
|
95
532
|
];
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
${style.errorAsValue ? "return [null as never, parseError as never] as const;" : "throw parseError;"}
|
|
533
|
+
if (resolved.description) {
|
|
534
|
+
lines.push(resolved.description);
|
|
99
535
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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"];
|
|
105
692
|
}
|
|
106
693
|
}
|
|
107
|
-
|
|
108
|
-
|
|
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;
|
|
109
713
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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);
|
|
724
|
+
}
|
|
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;
|
|
113
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
|
+
}
|
|
114
785
|
|
|
115
|
-
|
|
116
|
-
|
|
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
|
+
}
|
|
117
911
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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;
|
|
924
|
+
}
|
|
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);
|
|
125
961
|
}
|
|
126
962
|
}
|
|
127
963
|
}
|
|
128
|
-
|
|
129
|
-
|
|
964
|
+
if (booleanPropertyNames.length === 0) {
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
if (booleanPropertyNames.length === 1) {
|
|
968
|
+
return booleanPropertyNames[0];
|
|
969
|
+
}
|
|
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
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
updateCandidate(propName, currentPropRank);
|
|
1008
|
+
}
|
|
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
|
+
}
|
|
130
1027
|
|
|
131
|
-
// packages/
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
+
}
|
|
136
1215
|
|
|
137
1216
|
// packages/spec/dist/lib/operation.js
|
|
138
|
-
|
|
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
|
+
}
|
|
139
1303
|
var defaults = {
|
|
140
1304
|
operationId: (operation, path, method) => {
|
|
141
1305
|
if (operation.operationId) {
|
|
142
|
-
return
|
|
1306
|
+
return camelcase2(operation.operationId);
|
|
143
1307
|
}
|
|
144
1308
|
const metadata = operation["x-oaiMeta"];
|
|
145
1309
|
if (metadata && metadata.name) {
|
|
146
|
-
return
|
|
1310
|
+
return camelcase2(metadata.name);
|
|
147
1311
|
}
|
|
148
|
-
return
|
|
1312
|
+
return camelcase2(
|
|
149
1313
|
[method, ...path.replace(/[\\/\\{\\}]/g, " ").split(" ")].filter(Boolean).join(" ").trim()
|
|
150
1314
|
);
|
|
151
1315
|
},
|
|
152
1316
|
tag: (operation, path) => {
|
|
153
|
-
return operation.tags?.[0]
|
|
1317
|
+
return operation.tags?.[0] ? sanitizeTag(operation.tags?.[0]) : determineGenericTag(path, operation);
|
|
154
1318
|
}
|
|
155
1319
|
};
|
|
156
|
-
function
|
|
1320
|
+
function resolveResponses(spec, operation) {
|
|
1321
|
+
const responses = operation.responses ?? {};
|
|
1322
|
+
const resolved = {};
|
|
1323
|
+
for (const status in responses) {
|
|
1324
|
+
const response = isRef5(responses[status]) ? followRef3(spec, responses[status].$ref) : responses[status];
|
|
1325
|
+
resolved[status] = response;
|
|
1326
|
+
}
|
|
1327
|
+
return resolved;
|
|
1328
|
+
}
|
|
1329
|
+
function forEachOperation2(config, callback) {
|
|
157
1330
|
const result = [];
|
|
158
1331
|
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
159
1332
|
const { parameters = [], ...methods2 } = pathItem;
|
|
160
|
-
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
161
1333
|
for (const [method, operation] of Object.entries(methods2)) {
|
|
162
|
-
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
163
|
-
const formatTag = config.tag ?? defaults.tag;
|
|
164
|
-
const operationName = formatOperationId(operation, fixedPath, method);
|
|
165
|
-
const operationTag = formatTag(operation, fixedPath);
|
|
166
1334
|
const metadata = operation["x-oaiMeta"] ?? {};
|
|
1335
|
+
const operationTag = operation.tags?.[0];
|
|
167
1336
|
result.push(
|
|
168
1337
|
callback(
|
|
169
1338
|
{
|
|
170
1339
|
name: metadata.name,
|
|
171
1340
|
method,
|
|
172
|
-
path
|
|
1341
|
+
path,
|
|
173
1342
|
groupName: operationTag,
|
|
174
1343
|
tag: operationTag
|
|
175
1344
|
},
|
|
176
|
-
|
|
177
|
-
...operation,
|
|
178
|
-
parameters: [...parameters, ...operation.parameters ?? []],
|
|
179
|
-
operationId: operationName
|
|
180
|
-
}
|
|
1345
|
+
operation
|
|
181
1346
|
)
|
|
182
1347
|
);
|
|
183
1348
|
}
|
|
@@ -185,15 +1350,11 @@ function forEachOperation(config, callback) {
|
|
|
185
1350
|
return result;
|
|
186
1351
|
}
|
|
187
1352
|
var reservedKeywords = /* @__PURE__ */ new Set([
|
|
188
|
-
"abstract",
|
|
189
|
-
"arguments",
|
|
190
1353
|
"await",
|
|
191
|
-
|
|
1354
|
+
// Reserved in async functions
|
|
192
1355
|
"break",
|
|
193
|
-
"byte",
|
|
194
1356
|
"case",
|
|
195
1357
|
"catch",
|
|
196
|
-
"char",
|
|
197
1358
|
"class",
|
|
198
1359
|
"const",
|
|
199
1360
|
"continue",
|
|
@@ -201,85 +1362,59 @@ var reservedKeywords = /* @__PURE__ */ new Set([
|
|
|
201
1362
|
"default",
|
|
202
1363
|
"delete",
|
|
203
1364
|
"do",
|
|
204
|
-
"double",
|
|
205
1365
|
"else",
|
|
206
1366
|
"enum",
|
|
207
|
-
"eval",
|
|
208
1367
|
"export",
|
|
209
1368
|
"extends",
|
|
210
1369
|
"false",
|
|
211
|
-
"final",
|
|
212
1370
|
"finally",
|
|
213
|
-
"float",
|
|
214
1371
|
"for",
|
|
215
1372
|
"function",
|
|
216
|
-
"goto",
|
|
217
1373
|
"if",
|
|
218
1374
|
"implements",
|
|
1375
|
+
// Strict mode
|
|
219
1376
|
"import",
|
|
220
1377
|
"in",
|
|
221
1378
|
"instanceof",
|
|
222
|
-
"int",
|
|
223
1379
|
"interface",
|
|
1380
|
+
// Strict mode
|
|
224
1381
|
"let",
|
|
225
|
-
|
|
226
|
-
"native",
|
|
1382
|
+
// Strict mode
|
|
227
1383
|
"new",
|
|
228
1384
|
"null",
|
|
229
1385
|
"package",
|
|
1386
|
+
// Strict mode
|
|
230
1387
|
"private",
|
|
1388
|
+
// Strict mode
|
|
231
1389
|
"protected",
|
|
1390
|
+
// Strict mode
|
|
232
1391
|
"public",
|
|
1392
|
+
// Strict mode
|
|
233
1393
|
"return",
|
|
234
|
-
"short",
|
|
235
1394
|
"static",
|
|
1395
|
+
// Strict mode
|
|
236
1396
|
"super",
|
|
237
1397
|
"switch",
|
|
238
|
-
"synchronized",
|
|
239
1398
|
"this",
|
|
240
1399
|
"throw",
|
|
241
|
-
"throws",
|
|
242
|
-
"transient",
|
|
243
1400
|
"true",
|
|
244
1401
|
"try",
|
|
245
1402
|
"typeof",
|
|
246
1403
|
"var",
|
|
247
1404
|
"void",
|
|
248
|
-
"volatile",
|
|
249
1405
|
"while",
|
|
250
1406
|
"with",
|
|
251
1407
|
"yield",
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"
|
|
256
|
-
"any",
|
|
257
|
-
"unknown",
|
|
258
|
-
"never",
|
|
259
|
-
"get",
|
|
260
|
-
"list",
|
|
261
|
-
"create",
|
|
262
|
-
"update",
|
|
263
|
-
"delete",
|
|
264
|
-
"post",
|
|
265
|
-
"put",
|
|
266
|
-
"patch",
|
|
267
|
-
"do",
|
|
268
|
-
"send",
|
|
269
|
-
"add",
|
|
270
|
-
"remove",
|
|
271
|
-
"set",
|
|
272
|
-
"find",
|
|
273
|
-
"search",
|
|
274
|
-
"check",
|
|
275
|
-
"make"
|
|
276
|
-
// Added make, check
|
|
1408
|
+
// Strict mode / Generator functions
|
|
1409
|
+
// 'arguments' is not technically a reserved word, but it's a special identifier within functions
|
|
1410
|
+
// and assigning to it or declaring it can cause issues or unexpected behavior.
|
|
1411
|
+
"arguments"
|
|
277
1412
|
]);
|
|
278
1413
|
function sanitizeTag(camelCasedTag) {
|
|
279
1414
|
if (/^\d/.test(camelCasedTag)) {
|
|
280
1415
|
return `_${camelCasedTag}`;
|
|
281
1416
|
}
|
|
282
|
-
return reservedKeywords.has(camelCasedTag) ? `${camelCasedTag}_` : camelCasedTag;
|
|
1417
|
+
return reservedKeywords.has(camelcase2(camelCasedTag)) ? `${camelCasedTag}_` : camelCasedTag;
|
|
283
1418
|
}
|
|
284
1419
|
function determineGenericTag(pathString, operation) {
|
|
285
1420
|
const operationId = operation.operationId || "";
|
|
@@ -303,7 +1438,6 @@ function determineGenericTag(pathString, operation) {
|
|
|
303
1438
|
"search",
|
|
304
1439
|
"check",
|
|
305
1440
|
"make"
|
|
306
|
-
// Added make
|
|
307
1441
|
]);
|
|
308
1442
|
const segments = pathString.split("/").filter(Boolean);
|
|
309
1443
|
const potentialCandidates = segments.filter(
|
|
@@ -312,7 +1446,7 @@ function determineGenericTag(pathString, operation) {
|
|
|
312
1446
|
for (let i = potentialCandidates.length - 1; i >= 0; i--) {
|
|
313
1447
|
const segment = potentialCandidates[i];
|
|
314
1448
|
if (!segment.startsWith("@")) {
|
|
315
|
-
return sanitizeTag(
|
|
1449
|
+
return sanitizeTag(camelcase2(segment));
|
|
316
1450
|
}
|
|
317
1451
|
}
|
|
318
1452
|
const canFallbackToPathSegment = potentialCandidates.length > 0;
|
|
@@ -347,17 +1481,17 @@ function determineGenericTag(pathString, operation) {
|
|
|
347
1481
|
}
|
|
348
1482
|
if (nextPartStartIndex !== -1 && nextPartStartIndex < operationId.length) {
|
|
349
1483
|
const remainingOriginalSubstring = operationId.substring(nextPartStartIndex);
|
|
350
|
-
const potentialTag =
|
|
1484
|
+
const potentialTag = camelcase2(remainingOriginalSubstring);
|
|
351
1485
|
if (potentialTag) {
|
|
352
1486
|
return sanitizeTag(potentialTag);
|
|
353
1487
|
}
|
|
354
1488
|
}
|
|
355
|
-
const potentialTagJoined =
|
|
1489
|
+
const potentialTagJoined = camelcase2(validParts.slice(1).join("_"));
|
|
356
1490
|
if (potentialTagJoined) {
|
|
357
1491
|
return sanitizeTag(potentialTagJoined);
|
|
358
1492
|
}
|
|
359
1493
|
}
|
|
360
|
-
const potentialTagFull =
|
|
1494
|
+
const potentialTagFull = camelcase2(operationId);
|
|
361
1495
|
if (potentialTagFull) {
|
|
362
1496
|
const isResultSingleVerb = validParts.length === 1 && isFirstPartVerb;
|
|
363
1497
|
if (!(isResultSingleVerb && canFallbackToPathSegment)) {
|
|
@@ -366,7 +1500,7 @@ function determineGenericTag(pathString, operation) {
|
|
|
366
1500
|
}
|
|
367
1501
|
}
|
|
368
1502
|
}
|
|
369
|
-
const firstPartCamel =
|
|
1503
|
+
const firstPartCamel = camelcase2(firstPart);
|
|
370
1504
|
if (firstPartCamel) {
|
|
371
1505
|
const isFirstPartCamelVerb = commonVerbs.has(firstPartCamel);
|
|
372
1506
|
if (!isFirstPartCamelVerb || validParts.length === 1 || !canFallbackToPathSegment) {
|
|
@@ -374,32 +1508,220 @@ function determineGenericTag(pathString, operation) {
|
|
|
374
1508
|
}
|
|
375
1509
|
}
|
|
376
1510
|
if (isFirstPartVerb && validParts.length > 1 && validParts[1] && canFallbackToPathSegment) {
|
|
377
|
-
const secondPartCamel =
|
|
1511
|
+
const secondPartCamel = camelcase2(validParts[1]);
|
|
378
1512
|
if (secondPartCamel) {
|
|
379
1513
|
return sanitizeTag(secondPartCamel);
|
|
380
1514
|
}
|
|
381
1515
|
}
|
|
382
1516
|
}
|
|
383
1517
|
}
|
|
384
|
-
if (potentialCandidates.length > 0) {
|
|
385
|
-
let firstCandidate = potentialCandidates[0];
|
|
386
|
-
if (firstCandidate.startsWith("@")) {
|
|
387
|
-
firstCandidate = firstCandidate.substring(1);
|
|
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`);
|
|
1577
|
+
}
|
|
1578
|
+
parameters.push({
|
|
1579
|
+
in: staticIn ?? schema.in,
|
|
1580
|
+
name: schema.name,
|
|
1581
|
+
schema: { type: "string" }
|
|
1582
|
+
});
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
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()"
|
|
1610
|
+
}
|
|
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;"}
|
|
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']>>;
|
|
1655
|
+
}
|
|
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;"}
|
|
388
1683
|
}
|
|
389
|
-
|
|
390
|
-
|
|
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
|
+
}
|
|
391
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"}
|
|
392
1693
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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";
|
|
398
1720
|
|
|
399
1721
|
// packages/typescript/src/lib/emitters/zod.ts
|
|
400
|
-
import { cleanRef, followRef, isRef
|
|
401
|
-
var
|
|
402
|
-
|
|
1722
|
+
import { cleanRef, followRef as followRef4, isRef as isRef6 } from "@sdk-it/core";
|
|
1723
|
+
var ZodEmitter = class {
|
|
1724
|
+
generatedRefs = /* @__PURE__ */ new Set();
|
|
403
1725
|
#spec;
|
|
404
1726
|
#onRef;
|
|
405
1727
|
constructor(spec, onRef) {
|
|
@@ -473,15 +1795,14 @@ var ZodDeserialzer = class {
|
|
|
473
1795
|
}
|
|
474
1796
|
ref($ref, required) {
|
|
475
1797
|
const schemaName = cleanRef($ref).split("/").pop();
|
|
476
|
-
if (this.
|
|
1798
|
+
if (this.generatedRefs.has(schemaName)) {
|
|
477
1799
|
return schemaName;
|
|
478
1800
|
}
|
|
479
|
-
this.
|
|
1801
|
+
this.generatedRefs.add(schemaName);
|
|
480
1802
|
this.#onRef?.(
|
|
481
1803
|
schemaName,
|
|
482
|
-
this.handle(
|
|
1804
|
+
this.handle(followRef4(this.#spec, $ref), required)
|
|
483
1805
|
);
|
|
484
|
-
this.circularRefTracker.delete(schemaName);
|
|
485
1806
|
return schemaName;
|
|
486
1807
|
}
|
|
487
1808
|
allOf(schemas, required) {
|
|
@@ -509,15 +1830,7 @@ var ZodDeserialzer = class {
|
|
|
509
1830
|
return `z.union([${anyOfSchemas.join(", ")}])${appendOptional(required)}`;
|
|
510
1831
|
}
|
|
511
1832
|
oneOf(schemas, required) {
|
|
512
|
-
const oneOfSchemas = schemas.map((sub) =>
|
|
513
|
-
if (isRef(sub)) {
|
|
514
|
-
const { model } = parseRef(sub.$ref);
|
|
515
|
-
if (this.circularRefTracker.has(model)) {
|
|
516
|
-
return `${model}${appendOptional(required)}`;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
return this.handle(sub, true);
|
|
520
|
-
});
|
|
1833
|
+
const oneOfSchemas = schemas.map((sub) => this.handle(sub, true));
|
|
521
1834
|
if (oneOfSchemas.length === 1) {
|
|
522
1835
|
return `${oneOfSchemas[0]}${appendOptional(required)}`;
|
|
523
1836
|
}
|
|
@@ -537,6 +1850,10 @@ var ZodDeserialzer = class {
|
|
|
537
1850
|
*/
|
|
538
1851
|
string(schema) {
|
|
539
1852
|
let base = "z.string()";
|
|
1853
|
+
if (schema.contentEncoding === "binary") {
|
|
1854
|
+
base = "z.instanceof(Blob)";
|
|
1855
|
+
return base;
|
|
1856
|
+
}
|
|
540
1857
|
switch (schema.format) {
|
|
541
1858
|
case "date-time":
|
|
542
1859
|
case "datetime":
|
|
@@ -614,7 +1931,7 @@ var ZodDeserialzer = class {
|
|
|
614
1931
|
return { base, defaultValue };
|
|
615
1932
|
}
|
|
616
1933
|
handle(schema, required) {
|
|
617
|
-
if (
|
|
1934
|
+
if (isRef6(schema)) {
|
|
618
1935
|
return `${this.ref(schema.$ref, true)}${appendOptional(required)}`;
|
|
619
1936
|
}
|
|
620
1937
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -660,13 +1977,13 @@ function appendDefault(defaultValue) {
|
|
|
660
1977
|
|
|
661
1978
|
// packages/typescript/src/lib/sdk.ts
|
|
662
1979
|
import { get } from "lodash-es";
|
|
663
|
-
import { camelcase as
|
|
664
|
-
import {
|
|
1980
|
+
import { camelcase as camelcase3, pascalcase, spinalcase } from "stringcase";
|
|
1981
|
+
import { isRef as isRef9, toLitObject as toLitObject2 } from "@sdk-it/core";
|
|
665
1982
|
|
|
666
1983
|
// packages/typescript/src/lib/emitters/interface.ts
|
|
667
|
-
import { cleanRef as cleanRef2, followRef as
|
|
668
|
-
var
|
|
669
|
-
|
|
1984
|
+
import { cleanRef as cleanRef2, followRef as followRef5, isRef as isRef7 } from "@sdk-it/core";
|
|
1985
|
+
var TypeScriptEmitter = class {
|
|
1986
|
+
generatedRefs = /* @__PURE__ */ new Set();
|
|
670
1987
|
#spec;
|
|
671
1988
|
#onRef;
|
|
672
1989
|
constructor(spec, onRef) {
|
|
@@ -677,7 +1994,7 @@ var TypeScriptDeserialzer = class {
|
|
|
677
1994
|
return `'${value}'`;
|
|
678
1995
|
};
|
|
679
1996
|
#isInternal = (schema) => {
|
|
680
|
-
return
|
|
1997
|
+
return isRef7(schema) ? false : !!schema["x-internal"];
|
|
681
1998
|
};
|
|
682
1999
|
/**
|
|
683
2000
|
* Handle objects (properties)
|
|
@@ -697,7 +2014,7 @@ var TypeScriptDeserialzer = class {
|
|
|
697
2014
|
propEntries.push("[key: string]: any");
|
|
698
2015
|
}
|
|
699
2016
|
}
|
|
700
|
-
return `{ ${propEntries.join("; ")} }`;
|
|
2017
|
+
return `${propEntries.length ? `{ ${propEntries.join("; ")} }` : "unknown"}`;
|
|
701
2018
|
}
|
|
702
2019
|
/**
|
|
703
2020
|
* Handle arrays (items could be a single schema or a tuple)
|
|
@@ -739,15 +2056,14 @@ var TypeScriptDeserialzer = class {
|
|
|
739
2056
|
}
|
|
740
2057
|
ref($ref, required) {
|
|
741
2058
|
const schemaName = cleanRef2($ref).split("/").pop();
|
|
742
|
-
if (this.
|
|
2059
|
+
if (this.generatedRefs.has(schemaName)) {
|
|
743
2060
|
return schemaName;
|
|
744
2061
|
}
|
|
745
|
-
this.
|
|
2062
|
+
this.generatedRefs.add(schemaName);
|
|
746
2063
|
this.#onRef?.(
|
|
747
2064
|
schemaName,
|
|
748
|
-
this.handle(
|
|
2065
|
+
this.handle(followRef5(this.#spec, $ref), required)
|
|
749
2066
|
);
|
|
750
|
-
this.circularRefTracker.delete(schemaName);
|
|
751
2067
|
return appendOptional2(schemaName, required);
|
|
752
2068
|
}
|
|
753
2069
|
allOf(schemas) {
|
|
@@ -763,12 +2079,6 @@ var TypeScriptDeserialzer = class {
|
|
|
763
2079
|
}
|
|
764
2080
|
oneOf(schemas, required) {
|
|
765
2081
|
const oneOfTypes = schemas.map((sub) => {
|
|
766
|
-
if (isRef2(sub)) {
|
|
767
|
-
const { model } = parseRef2(sub.$ref);
|
|
768
|
-
if (this.circularRefTracker.has(model)) {
|
|
769
|
-
return model;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
2082
|
return this.handle(sub, false);
|
|
773
2083
|
});
|
|
774
2084
|
return appendOptional2(
|
|
@@ -785,6 +2095,9 @@ var TypeScriptDeserialzer = class {
|
|
|
785
2095
|
*/
|
|
786
2096
|
string(schema, required) {
|
|
787
2097
|
let type;
|
|
2098
|
+
if (schema.contentEncoding === "binary") {
|
|
2099
|
+
return appendOptional2("Blob", required);
|
|
2100
|
+
}
|
|
788
2101
|
switch (schema.format) {
|
|
789
2102
|
case "date-time":
|
|
790
2103
|
case "datetime":
|
|
@@ -811,7 +2124,7 @@ var TypeScriptDeserialzer = class {
|
|
|
811
2124
|
return appendOptional2(type, required);
|
|
812
2125
|
}
|
|
813
2126
|
handle(schema, required) {
|
|
814
|
-
if (
|
|
2127
|
+
if (isRef7(schema)) {
|
|
815
2128
|
return this.ref(schema.$ref, required);
|
|
816
2129
|
}
|
|
817
2130
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -856,8 +2169,8 @@ function appendOptional2(type, isRequired) {
|
|
|
856
2169
|
}
|
|
857
2170
|
|
|
858
2171
|
// packages/typescript/src/lib/utils.ts
|
|
859
|
-
import { isRef as
|
|
860
|
-
function
|
|
2172
|
+
import { followRef as followRef6, isRef as isRef8, removeDuplicates } from "@sdk-it/core";
|
|
2173
|
+
function securityToOptions2(spec, security2, securitySchemes, staticIn) {
|
|
861
2174
|
securitySchemes ??= {};
|
|
862
2175
|
const options = {};
|
|
863
2176
|
for (const it of security2) {
|
|
@@ -865,10 +2178,7 @@ function securityToOptions(security2, securitySchemes, staticIn) {
|
|
|
865
2178
|
if (!name) {
|
|
866
2179
|
continue;
|
|
867
2180
|
}
|
|
868
|
-
const schema = securitySchemes[name];
|
|
869
|
-
if (isRef3(schema)) {
|
|
870
|
-
throw new Error(`Ref security schemas are not supported`);
|
|
871
|
-
}
|
|
2181
|
+
const schema = isRef8(securitySchemes[name]) ? followRef6(spec, securitySchemes[name].$ref) : securitySchemes[name];
|
|
872
2182
|
if (schema.type === "http") {
|
|
873
2183
|
options["authorization"] = {
|
|
874
2184
|
in: staticIn ?? "header",
|
|
@@ -954,7 +2264,7 @@ function generateInputs(operationsSet, commonZod, makeImport) {
|
|
|
954
2264
|
const output = [];
|
|
955
2265
|
const imports = /* @__PURE__ */ new Set(['import { z } from "zod";']);
|
|
956
2266
|
for (const operation of operations) {
|
|
957
|
-
const schemaName =
|
|
2267
|
+
const schemaName = camelcase3(`${operation.name} schema`);
|
|
958
2268
|
const schema = `export const ${schemaName} = ${Object.keys(operation.schemas).length === 1 ? Object.values(operation.schemas)[0] : toLitObject2(operation.schemas)};`;
|
|
959
2269
|
const inputContent = schema;
|
|
960
2270
|
for (const schema2 of commonImports) {
|
|
@@ -991,8 +2301,8 @@ function generateInputs(operationsSet, commonZod, makeImport) {
|
|
|
991
2301
|
};
|
|
992
2302
|
}
|
|
993
2303
|
function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
994
|
-
const schemaName =
|
|
995
|
-
const schemaRef = `${
|
|
2304
|
+
const schemaName = camelcase3(`${operation.name} schema`);
|
|
2305
|
+
const schemaRef = `${camelcase3(groupName)}.${schemaName}`;
|
|
996
2306
|
const inputHeaders = [];
|
|
997
2307
|
const inputQuery = [];
|
|
998
2308
|
const inputBody = [];
|
|
@@ -1024,13 +2334,25 @@ function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
|
1024
2334
|
const statusCode = +status;
|
|
1025
2335
|
return statusCode >= 200 && statusCode < 300;
|
|
1026
2336
|
}).length > 1;
|
|
1027
|
-
|
|
1028
|
-
|
|
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) {
|
|
1029
2351
|
const handled = handleResponse(
|
|
1030
2352
|
spec,
|
|
1031
2353
|
operation.name,
|
|
1032
2354
|
status,
|
|
1033
|
-
|
|
2355
|
+
responseWithAtLeast200[status],
|
|
1034
2356
|
utils,
|
|
1035
2357
|
true
|
|
1036
2358
|
// statusesCount,
|
|
@@ -1050,19 +2372,104 @@ function toEndpoint(groupName, spec, specOperation, operation, utils) {
|
|
|
1050
2372
|
schema: ${schemaRef}${addTypeParser ? `.${type}` : ""},
|
|
1051
2373
|
output:[${outputs.join(",")}],
|
|
1052
2374
|
toRequest(input: z.infer<typeof ${schemaRef}${addTypeParser ? `.${type}` : ""}>) {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
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)}`
|
|
1062
2386
|
);
|
|
1063
2387
|
}
|
|
1064
2388
|
return { responses, schemas };
|
|
1065
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
|
+
}
|
|
1066
2473
|
var statusCodeToResponseMap = {
|
|
1067
2474
|
"200": "Ok",
|
|
1068
2475
|
"201": "Created",
|
|
@@ -1100,7 +2507,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1100
2507
|
};
|
|
1101
2508
|
const responses = [];
|
|
1102
2509
|
const outputs = [];
|
|
1103
|
-
const typeScriptDeserialzer = new
|
|
2510
|
+
const typeScriptDeserialzer = new TypeScriptEmitter(
|
|
1104
2511
|
spec,
|
|
1105
2512
|
(schemaName, zod) => {
|
|
1106
2513
|
schemas[schemaName] = zod;
|
|
@@ -1135,7 +2542,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1135
2542
|
let responseSchema = parser === "chunked" ? "ReadableStream" : "void";
|
|
1136
2543
|
if (isJson) {
|
|
1137
2544
|
const schema = responseContent["application/json"].schema;
|
|
1138
|
-
const isObject = !
|
|
2545
|
+
const isObject = !isRef9(schema) && schema.type === "object";
|
|
1139
2546
|
if (isObject && schema.properties) {
|
|
1140
2547
|
schema.properties["[http.KIND]"] = {
|
|
1141
2548
|
"x-internal": true,
|
|
@@ -1143,7 +2550,7 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1143
2550
|
type: "string"
|
|
1144
2551
|
};
|
|
1145
2552
|
schema.required ??= [];
|
|
1146
|
-
schema.required.push("[KIND]");
|
|
2553
|
+
schema.required.push("[http.KIND]");
|
|
1147
2554
|
}
|
|
1148
2555
|
responseSchema = typeScriptDeserialzer.handle(schema, true);
|
|
1149
2556
|
}
|
|
@@ -1176,13 +2583,13 @@ function handleResponse(spec, operationName, status, response, utils, numbered)
|
|
|
1176
2583
|
}
|
|
1177
2584
|
|
|
1178
2585
|
// packages/typescript/src/lib/styles/github/endpoints.txt
|
|
1179
|
-
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};";
|
|
1180
2587
|
|
|
1181
2588
|
// packages/typescript/src/lib/generator.ts
|
|
1182
2589
|
function generateCode(config) {
|
|
1183
2590
|
const commonZod = /* @__PURE__ */ new Map();
|
|
1184
2591
|
const commonZodImports = [];
|
|
1185
|
-
const zodDeserialzer = new
|
|
2592
|
+
const zodDeserialzer = new ZodEmitter(config.spec, (model, schema) => {
|
|
1186
2593
|
commonZod.set(model, schema);
|
|
1187
2594
|
commonZodImports.push({
|
|
1188
2595
|
defaultImport: void 0,
|
|
@@ -1195,41 +2602,41 @@ function generateCode(config) {
|
|
|
1195
2602
|
const groups = {};
|
|
1196
2603
|
const outputs = {};
|
|
1197
2604
|
const endpoints = {};
|
|
1198
|
-
|
|
2605
|
+
forEachOperation2(config, (entry, operation) => {
|
|
1199
2606
|
console.log(`Processing ${entry.method} ${entry.path}`);
|
|
1200
2607
|
groups[entry.groupName] ??= [];
|
|
1201
2608
|
endpoints[entry.groupName] ??= [];
|
|
1202
2609
|
const inputs = {};
|
|
1203
|
-
const additionalProperties =
|
|
1204
|
-
for (const param of operation.parameters
|
|
1205
|
-
if (isRef5(param)) {
|
|
1206
|
-
throw new Error(`Found reference in parameter ${param.$ref}`);
|
|
1207
|
-
}
|
|
2610
|
+
const additionalProperties = {};
|
|
2611
|
+
for (const param of operation.parameters) {
|
|
1208
2612
|
if (!param.schema) {
|
|
1209
|
-
|
|
2613
|
+
param.schema = {
|
|
2614
|
+
type: "string"
|
|
2615
|
+
};
|
|
1210
2616
|
}
|
|
1211
2617
|
inputs[param.name] = {
|
|
1212
2618
|
in: param.in,
|
|
1213
2619
|
schema: ""
|
|
1214
2620
|
};
|
|
1215
|
-
additionalProperties.
|
|
2621
|
+
additionalProperties[param.name] = param;
|
|
1216
2622
|
}
|
|
1217
|
-
const security2 = operation.security ?? [];
|
|
1218
2623
|
const securitySchemes = config.spec.components?.securitySchemes ?? {};
|
|
1219
|
-
const securityOptions =
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
([name, value]) => ({
|
|
1224
|
-
name,
|
|
1225
|
-
required: false,
|
|
1226
|
-
schema: {
|
|
1227
|
-
type: "string"
|
|
1228
|
-
},
|
|
1229
|
-
in: value.in
|
|
1230
|
-
})
|
|
1231
|
-
)
|
|
2624
|
+
const securityOptions = securityToOptions2(
|
|
2625
|
+
config.spec,
|
|
2626
|
+
operation.security ?? [],
|
|
2627
|
+
securitySchemes
|
|
1232
2628
|
);
|
|
2629
|
+
Object.assign(inputs, securityOptions);
|
|
2630
|
+
Object.entries(securityOptions).forEach(([name, value]) => {
|
|
2631
|
+
additionalProperties[name] = {
|
|
2632
|
+
name,
|
|
2633
|
+
required: false,
|
|
2634
|
+
schema: {
|
|
2635
|
+
type: "string"
|
|
2636
|
+
},
|
|
2637
|
+
in: value.in
|
|
2638
|
+
};
|
|
2639
|
+
});
|
|
1233
2640
|
const schemas = {};
|
|
1234
2641
|
const shortContenTypeMap = {
|
|
1235
2642
|
"application/json": "json",
|
|
@@ -1243,10 +2650,12 @@ function generateCode(config) {
|
|
|
1243
2650
|
"text/plain": "text"
|
|
1244
2651
|
};
|
|
1245
2652
|
let outgoingContentType;
|
|
1246
|
-
if (!
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
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;
|
|
1250
2659
|
if (!ctSchema) {
|
|
1251
2660
|
console.warn(
|
|
1252
2661
|
`Schema not found for ${type} in ${entry.method} ${entry.path}`
|
|
@@ -1257,16 +2666,16 @@ function generateCode(config) {
|
|
|
1257
2666
|
if (objectSchema.type !== "object") {
|
|
1258
2667
|
objectSchema = {
|
|
1259
2668
|
type: "object",
|
|
1260
|
-
required: [requestBody.required ? "$body" : ""],
|
|
2669
|
+
required: [operation.requestBody.required ? "$body" : ""],
|
|
1261
2670
|
properties: {
|
|
1262
2671
|
$body: ctSchema
|
|
1263
2672
|
}
|
|
1264
2673
|
};
|
|
1265
2674
|
}
|
|
1266
2675
|
const schema = merge({}, objectSchema, {
|
|
1267
|
-
required: additionalProperties.filter((p) => p.required).map((p) => p.name),
|
|
1268
|
-
properties: additionalProperties.reduce(
|
|
1269
|
-
(acc, p) => ({
|
|
2676
|
+
required: Object.values(additionalProperties).filter((p) => p.required).map((p) => p.name),
|
|
2677
|
+
properties: Object.entries(additionalProperties).reduce(
|
|
2678
|
+
(acc, [, p]) => ({
|
|
1270
2679
|
...acc,
|
|
1271
2680
|
[p.name]: p.schema
|
|
1272
2681
|
}),
|
|
@@ -1276,18 +2685,18 @@ function generateCode(config) {
|
|
|
1276
2685
|
Object.assign(inputs, bodyInputs(config, objectSchema));
|
|
1277
2686
|
schemas[shortContenTypeMap[type]] = zodDeserialzer.handle(schema, true);
|
|
1278
2687
|
}
|
|
1279
|
-
if (requestBody.content["application/json"]) {
|
|
2688
|
+
if (operation.requestBody.content["application/json"]) {
|
|
1280
2689
|
outgoingContentType = "json";
|
|
1281
|
-
} else if (requestBody.content["application/x-www-form-urlencoded"]) {
|
|
2690
|
+
} else if (operation.requestBody.content["application/x-www-form-urlencoded"]) {
|
|
1282
2691
|
outgoingContentType = "urlencoded";
|
|
1283
|
-
} else if (requestBody.content["multipart/form-data"]) {
|
|
2692
|
+
} else if (operation.requestBody.content["multipart/form-data"]) {
|
|
1284
2693
|
outgoingContentType = "formdata";
|
|
1285
2694
|
} else {
|
|
1286
2695
|
outgoingContentType = "json";
|
|
1287
2696
|
}
|
|
1288
2697
|
} else {
|
|
1289
|
-
const properties = additionalProperties.reduce(
|
|
1290
|
-
(acc, p) => ({
|
|
2698
|
+
const properties = Object.entries(additionalProperties).reduce(
|
|
2699
|
+
(acc, [, p]) => ({
|
|
1291
2700
|
...acc,
|
|
1292
2701
|
[p.name]: p.schema
|
|
1293
2702
|
}),
|
|
@@ -1296,7 +2705,7 @@ function generateCode(config) {
|
|
|
1296
2705
|
schemas[shortContenTypeMap["application/json"]] = zodDeserialzer.handle(
|
|
1297
2706
|
{
|
|
1298
2707
|
type: "object",
|
|
1299
|
-
required: additionalProperties.filter((p) => p.required).map((p) => p.name),
|
|
2708
|
+
required: Object.values(additionalProperties).filter((p) => p.required).map((p) => p.name),
|
|
1300
2709
|
properties
|
|
1301
2710
|
},
|
|
1302
2711
|
true
|
|
@@ -1314,11 +2723,11 @@ function generateCode(config) {
|
|
|
1314
2723
|
schemas,
|
|
1315
2724
|
inputs
|
|
1316
2725
|
},
|
|
1317
|
-
{ makeImport: config.makeImport }
|
|
2726
|
+
{ makeImport: config.makeImport, style: config.style }
|
|
1318
2727
|
);
|
|
1319
2728
|
const output = [
|
|
1320
2729
|
`import z from 'zod';`,
|
|
1321
|
-
`import type * as http from '../http';`
|
|
2730
|
+
`import type * as http from '${config.makeImport("../http/index")}';`
|
|
1322
2731
|
];
|
|
1323
2732
|
const responses = endpoint.responses.flatMap((it) => it.responses);
|
|
1324
2733
|
const responsesImports = endpoint.responses.flatMap(
|
|
@@ -1368,14 +2777,13 @@ function generateCode(config) {
|
|
|
1368
2777
|
{}
|
|
1369
2778
|
);
|
|
1370
2779
|
const allSchemas = Object.keys(endpoints).map((it) => ({
|
|
1371
|
-
import: `import ${
|
|
1372
|
-
use: ` ...${
|
|
2780
|
+
import: `import ${camelcase4(it)} from './${config.makeImport(spinalcase2(it))}';`,
|
|
2781
|
+
use: ` ...${camelcase4(it)}`
|
|
1373
2782
|
}));
|
|
1374
2783
|
const imports = [
|
|
1375
2784
|
'import z from "zod";',
|
|
1376
2785
|
`import type { ParseError } from '${config.makeImport("../http/parser")}';`,
|
|
1377
|
-
`import type { ServerError } from '${config.makeImport("../http/response")}'
|
|
1378
|
-
`import type { OutputType, Parser, Type } from '../http/send-request.ts';`
|
|
2786
|
+
`import type { ServerError } from '${config.makeImport("../http/response")}';`
|
|
1379
2787
|
];
|
|
1380
2788
|
return {
|
|
1381
2789
|
groups,
|
|
@@ -1391,12 +2799,9 @@ import type { ParseError } from '${config.makeImport("../http/parser")}';
|
|
|
1391
2799
|
import type { ProblematicResponse, SuccessfulResponse } from '${config.makeImport(
|
|
1392
2800
|
"../http/response"
|
|
1393
2801
|
)}';
|
|
1394
|
-
import type { OutputType, Parser, Type } from '${config.makeImport(
|
|
1395
|
-
"../http/send-request"
|
|
1396
|
-
)}';
|
|
1397
2802
|
|
|
1398
2803
|
import schemas from '${config.makeImport("./schemas")}';
|
|
1399
|
-
|
|
2804
|
+
import type { Unionize } from '${config.makeImport("../http/dispatcher")}';
|
|
1400
2805
|
${template(endpoints_default)({ outputType: config.style?.outputType })}`,
|
|
1401
2806
|
[`${join("api", "schemas.ts")}`]: `${allSchemas.map((it) => it.import).join("\n")}
|
|
1402
2807
|
import { KIND } from "${config.makeImport("../http/index")}";
|
|
@@ -1421,12 +2826,14 @@ ${allSchemas.map((it) => it.use).join(",\n")}
|
|
|
1421
2826
|
join("api", `${spinalcase2(name)}.ts`),
|
|
1422
2827
|
`${[
|
|
1423
2828
|
...imps,
|
|
1424
|
-
// ...imports,
|
|
1425
2829
|
`import z from 'zod';`,
|
|
1426
2830
|
`import * as http from '${config.makeImport("../http/response")}';`,
|
|
1427
|
-
`import { toRequest, json, urlencoded,
|
|
2831
|
+
`import { toRequest, json, urlencoded, empty, formdata, createUrl, type HeadersInit } from '${config.makeImport("../http/request")}';`,
|
|
1428
2832
|
`import { chunked, buffered } from "${config.makeImport("../http/parse-response")}";`,
|
|
1429
|
-
`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")}";`
|
|
1430
2837
|
].join(
|
|
1431
2838
|
"\n"
|
|
1432
2839
|
)}
|
|
@@ -1441,8 +2848,8 @@ ${endpoint.flatMap((it) => it.schemas).join(",\n")}
|
|
|
1441
2848
|
};
|
|
1442
2849
|
}
|
|
1443
2850
|
function toProps(spec, schemaOrRef, aggregator = []) {
|
|
1444
|
-
if (
|
|
1445
|
-
const schema =
|
|
2851
|
+
if (isRef10(schemaOrRef)) {
|
|
2852
|
+
const schema = followRef7(spec, schemaOrRef.$ref);
|
|
1446
2853
|
return toProps(spec, schema, aggregator);
|
|
1447
2854
|
} else if (schemaOrRef.type === "object") {
|
|
1448
2855
|
for (const [name] of Object.entries(schemaOrRef.properties ?? {})) {
|
|
@@ -1486,6 +2893,9 @@ function bodyInputs(config, ctSchema) {
|
|
|
1486
2893
|
);
|
|
1487
2894
|
}
|
|
1488
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
|
+
|
|
1489
2899
|
// packages/typescript/src/lib/http/interceptors.txt
|
|
1490
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";
|
|
1491
2901
|
|
|
@@ -1496,7 +2906,7 @@ var parse_response_default = 'import { parse } from "fast-content-type-parse";\n
|
|
|
1496
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";
|
|
1497
2907
|
|
|
1498
2908
|
// packages/typescript/src/lib/http/request.txt
|
|
1499
|
-
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";
|
|
1500
2910
|
|
|
1501
2911
|
// packages/typescript/src/lib/http/response.txt
|
|
1502
2912
|
var response_default = `export const KIND = Symbol('APIDATA');
|
|
@@ -1909,16 +3319,323 @@ export type SuccessfulResponse =
|
|
|
1909
3319
|
| NoContent;
|
|
1910
3320
|
`;
|
|
1911
3321
|
|
|
1912
|
-
// packages/typescript/src/lib/
|
|
1913
|
-
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";
|
|
3324
|
+
|
|
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();
|
|
3341
|
+
constructor(spec) {
|
|
3342
|
+
this.spec = spec;
|
|
3343
|
+
}
|
|
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);
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
if (schemaObj.additionalProperties && typeof schemaObj.additionalProperties === "object") {
|
|
3356
|
+
result["additionalPropExample"] = this.handle(
|
|
3357
|
+
schemaObj.additionalProperties
|
|
3358
|
+
);
|
|
3359
|
+
}
|
|
3360
|
+
return result;
|
|
3361
|
+
}
|
|
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;
|
|
3374
|
+
}
|
|
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;
|
|
3421
|
+
} else {
|
|
3422
|
+
value = schema.type === "integer" ? 42 : 42.42;
|
|
3423
|
+
}
|
|
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;
|
|
3433
|
+
}
|
|
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);
|
|
3449
|
+
}
|
|
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;
|
|
3455
|
+
}
|
|
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);
|
|
3465
|
+
}
|
|
3466
|
+
anyOf(schemas) {
|
|
3467
|
+
if (schemas.length === 0)
|
|
3468
|
+
return {};
|
|
3469
|
+
return this.handle(schemas[0]);
|
|
3470
|
+
}
|
|
3471
|
+
oneOf(schemas) {
|
|
3472
|
+
if (schemas.length === 0)
|
|
3473
|
+
return {};
|
|
3474
|
+
return this.handle(schemas[0]);
|
|
3475
|
+
}
|
|
3476
|
+
enum(schema) {
|
|
3477
|
+
return Array.isArray(schema.enum) && schema.enum.length > 0 ? schema.enum[0] : void 0;
|
|
3478
|
+
}
|
|
3479
|
+
handle(schemaOrRef) {
|
|
3480
|
+
if (isRef11(schemaOrRef)) {
|
|
3481
|
+
return this.ref(schemaOrRef.$ref);
|
|
3482
|
+
}
|
|
3483
|
+
const schema = isRef11(schemaOrRef) ? followRef8(this.spec, schemaOrRef.$ref) : schemaOrRef;
|
|
3484
|
+
if (schema.example !== void 0) {
|
|
3485
|
+
return schema.example;
|
|
3486
|
+
}
|
|
3487
|
+
if (schema.default !== void 0) {
|
|
3488
|
+
return schema.default;
|
|
3489
|
+
}
|
|
3490
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
3491
|
+
return this.allOf(schema.allOf);
|
|
3492
|
+
}
|
|
3493
|
+
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
3494
|
+
return this.anyOf(schema.anyOf);
|
|
3495
|
+
}
|
|
3496
|
+
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
3497
|
+
return this.oneOf(schema.oneOf);
|
|
3498
|
+
}
|
|
3499
|
+
if (schema.enum && Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
3500
|
+
return this.enum(schema);
|
|
3501
|
+
}
|
|
3502
|
+
const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
3503
|
+
if (types.length === 0) {
|
|
3504
|
+
if (schema.properties || schema.additionalProperties) {
|
|
3505
|
+
return this.object(schema);
|
|
3506
|
+
} else if (schema.items) {
|
|
3507
|
+
return this.array(schema);
|
|
3508
|
+
}
|
|
3509
|
+
return "example";
|
|
3510
|
+
}
|
|
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";
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
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);
|
|
3582
|
+
}
|
|
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);
|
|
3598
|
+
}
|
|
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
|
+
});`;
|
|
3619
|
+
}
|
|
3620
|
+
};
|
|
1914
3621
|
|
|
1915
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
|
+
];
|
|
1916
3633
|
function security(spec) {
|
|
1917
3634
|
const security2 = spec.security || [];
|
|
1918
3635
|
const components = spec.components || {};
|
|
1919
3636
|
const securitySchemes = components.securitySchemes || {};
|
|
1920
3637
|
const paths = Object.values(spec.paths ?? {});
|
|
1921
|
-
const options =
|
|
3638
|
+
const options = securityToOptions2(spec, security2, securitySchemes);
|
|
1922
3639
|
for (const it of paths) {
|
|
1923
3640
|
for (const method of methods) {
|
|
1924
3641
|
const operation = it[method];
|
|
@@ -1927,13 +3644,20 @@ function security(spec) {
|
|
|
1927
3644
|
}
|
|
1928
3645
|
Object.assign(
|
|
1929
3646
|
options,
|
|
1930
|
-
|
|
3647
|
+
securityToOptions2(
|
|
3648
|
+
spec,
|
|
3649
|
+
operation.security || [],
|
|
3650
|
+
securitySchemes,
|
|
3651
|
+
"input"
|
|
3652
|
+
)
|
|
1931
3653
|
);
|
|
1932
3654
|
}
|
|
1933
3655
|
}
|
|
1934
3656
|
return options;
|
|
1935
3657
|
}
|
|
1936
3658
|
async function generate(spec, settings) {
|
|
3659
|
+
spec = "x-sdk-augmented" in spec ? spec : augmentSpec({ spec });
|
|
3660
|
+
const generator = new TypeScriptGenerator(spec, settings);
|
|
1937
3661
|
const style = Object.assign(
|
|
1938
3662
|
{},
|
|
1939
3663
|
{
|
|
@@ -1943,7 +3667,29 @@ async function generate(spec, settings) {
|
|
|
1943
3667
|
},
|
|
1944
3668
|
settings.style ?? {}
|
|
1945
3669
|
);
|
|
3670
|
+
const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
|
|
1946
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
|
+
};
|
|
1947
3693
|
const makeImport = (moduleSpecifier) => {
|
|
1948
3694
|
return settings.useTsExtension ? `${moduleSpecifier}.ts` : moduleSpecifier;
|
|
1949
3695
|
};
|
|
@@ -1954,36 +3700,34 @@ async function generate(spec, settings) {
|
|
|
1954
3700
|
makeImport
|
|
1955
3701
|
}
|
|
1956
3702
|
);
|
|
1957
|
-
const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
|
|
1958
3703
|
const options = security(spec);
|
|
1959
|
-
const clientName = settings.name || "
|
|
3704
|
+
const clientName = pascalcase4((settings.name || "client").trim());
|
|
3705
|
+
const packageName = settings.name ? `@${spinalcase4(settings.name.trim().toLowerCase())}/sdk` : "sdk";
|
|
1960
3706
|
const inputFiles = generateInputs(groups, commonZod, makeImport);
|
|
1961
|
-
await
|
|
3707
|
+
await settings.writer(output, {
|
|
1962
3708
|
"outputs/.gitkeep": "",
|
|
1963
3709
|
"inputs/.gitkeep": "",
|
|
1964
3710
|
"models/.getkeep": ""
|
|
1965
|
-
// 'README.md': readme,
|
|
1966
3711
|
});
|
|
1967
|
-
await
|
|
1968
|
-
"interceptors.ts": `
|
|
1969
|
-
import type { RequestConfig, HeadersInit } from './${makeImport("request")}';
|
|
1970
|
-
${interceptors_default}`,
|
|
3712
|
+
await settings.writer(join2(output, "http"), {
|
|
1971
3713
|
"parse-response.ts": parse_response_default,
|
|
1972
|
-
"send-request.ts": `import z from 'zod';
|
|
1973
|
-
import type { Interceptor } from './${makeImport("interceptors")}';
|
|
1974
|
-
import { buffered } from './${makeImport("parse-response")}';
|
|
1975
|
-
import { parseInput } from './${makeImport("parser")}';
|
|
1976
|
-
import type { RequestConfig } from './${makeImport("request")}';
|
|
1977
|
-
import { APIError, APIResponse } from './${makeImport("response")}';
|
|
1978
|
-
|
|
1979
|
-
${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputType: style.outputType })}`,
|
|
1980
3714
|
"response.ts": response_default,
|
|
1981
3715
|
"parser.ts": parser_default,
|
|
1982
|
-
"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}`
|
|
1983
3727
|
});
|
|
1984
|
-
await
|
|
3728
|
+
await settings.writer(join2(output, "outputs"), outputs);
|
|
1985
3729
|
const modelsImports = Object.entries(commonSchemas).map(([name]) => name);
|
|
1986
|
-
await
|
|
3730
|
+
await settings.writer(output, {
|
|
1987
3731
|
"client.ts": client_default(
|
|
1988
3732
|
{
|
|
1989
3733
|
name: clientName,
|
|
@@ -2008,47 +3752,114 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2008
3752
|
])
|
|
2009
3753
|
)
|
|
2010
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
|
+
}
|
|
2011
3780
|
const folders = [
|
|
2012
|
-
getFolderExports(
|
|
3781
|
+
getFolderExports(
|
|
3782
|
+
join2(output, "outputs"),
|
|
3783
|
+
settings.readFolder,
|
|
3784
|
+
settings.useTsExtension
|
|
3785
|
+
),
|
|
2013
3786
|
getFolderExports(
|
|
2014
3787
|
join2(output, "inputs"),
|
|
3788
|
+
settings.readFolder,
|
|
2015
3789
|
settings.useTsExtension,
|
|
2016
3790
|
["ts"],
|
|
2017
|
-
(dirent) => dirent.
|
|
3791
|
+
(dirent) => dirent.isFolder && ["schemas"].includes(dirent.fileName)
|
|
3792
|
+
),
|
|
3793
|
+
getFolderExports(
|
|
3794
|
+
join2(output, "api"),
|
|
3795
|
+
settings.readFolder,
|
|
3796
|
+
settings.useTsExtension
|
|
2018
3797
|
),
|
|
2019
|
-
getFolderExports(join2(output, "api"), settings.useTsExtension),
|
|
2020
3798
|
getFolderExports(
|
|
2021
3799
|
join2(output, "http"),
|
|
3800
|
+
settings.readFolder,
|
|
2022
3801
|
settings.useTsExtension,
|
|
2023
3802
|
["ts"],
|
|
2024
|
-
(dirent) => !["response.ts", "parser.ts"].includes(dirent.
|
|
3803
|
+
(dirent) => !["response.ts", "parser.ts"].includes(dirent.fileName)
|
|
2025
3804
|
)
|
|
2026
3805
|
];
|
|
2027
3806
|
if (modelsImports.length) {
|
|
2028
3807
|
folders.push(
|
|
2029
|
-
getFolderExports(
|
|
3808
|
+
getFolderExports(
|
|
3809
|
+
join2(output, "models"),
|
|
3810
|
+
settings.readFolder,
|
|
3811
|
+
settings.useTsExtension
|
|
3812
|
+
)
|
|
2030
3813
|
);
|
|
2031
3814
|
}
|
|
2032
3815
|
const [outputIndex, inputsIndex, apiIndex, httpIndex, modelsIndex] = await Promise.all(folders);
|
|
2033
|
-
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, {
|
|
2034
3825
|
"api/index.ts": apiIndex,
|
|
2035
3826
|
"outputs/index.ts": outputIndex,
|
|
2036
3827
|
"inputs/index.ts": inputsIndex || null,
|
|
2037
3828
|
"http/index.ts": httpIndex,
|
|
2038
3829
|
...modelsImports.length ? { "models/index.ts": modelsIndex } : {}
|
|
2039
3830
|
});
|
|
2040
|
-
await
|
|
2041
|
-
"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
|
+
)
|
|
2042
3839
|
});
|
|
2043
3840
|
if (settings.mode === "full") {
|
|
2044
|
-
|
|
3841
|
+
const configFiles = {
|
|
2045
3842
|
"package.json": {
|
|
2046
3843
|
ignoreIfExists: true,
|
|
2047
3844
|
content: JSON.stringify(
|
|
2048
3845
|
{
|
|
2049
|
-
name:
|
|
3846
|
+
name: packageName,
|
|
3847
|
+
version: "0.0.1",
|
|
2050
3848
|
type: "module",
|
|
2051
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
|
+
},
|
|
2052
3863
|
dependencies: {
|
|
2053
3864
|
"fast-content-type-parse": "^3.0.0",
|
|
2054
3865
|
zod: "^3.24.2"
|
|
@@ -2080,27 +3891,32 @@ ${template2(send_request_default, {})({ throwError: !style.errorAsValue, outputT
|
|
|
2080
3891
|
2
|
|
2081
3892
|
)
|
|
2082
3893
|
}
|
|
2083
|
-
}
|
|
3894
|
+
};
|
|
3895
|
+
if (settings.readme) {
|
|
3896
|
+
configFiles["README.md"] = {
|
|
3897
|
+
ignoreIfExists: false,
|
|
3898
|
+
content: toReadme(spec, {
|
|
3899
|
+
generateSnippet: (...args) => generator.snippet(...args)
|
|
3900
|
+
})
|
|
3901
|
+
};
|
|
3902
|
+
}
|
|
3903
|
+
await settings.writer(settings.output, configFiles);
|
|
2084
3904
|
}
|
|
2085
3905
|
await settings.formatCode?.({
|
|
2086
3906
|
output,
|
|
2087
3907
|
env: npmRunPathEnv()
|
|
2088
3908
|
});
|
|
2089
3909
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
nodeWatch(path, {
|
|
2097
|
-
persistent: true,
|
|
2098
|
-
recursive: true
|
|
2099
|
-
})
|
|
2100
|
-
).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
|
+
};
|
|
2101
3916
|
}
|
|
2102
3917
|
export {
|
|
3918
|
+
TypeScriptGenerator,
|
|
2103
3919
|
generate,
|
|
2104
|
-
|
|
3920
|
+
readJson
|
|
2105
3921
|
};
|
|
2106
3922
|
//# sourceMappingURL=index.js.map
|