@sdk-it/dart 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1070 -73
- package/dist/index.js.map +4 -4
- package/dist/lib/generate.d.ts +3 -0
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/security.d.ts +3 -0
- package/dist/lib/security.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,30 +1,932 @@
|
|
|
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, pluralize2) {
|
|
39
|
+
if (typeof __require === "function" && typeof exports === "object" && typeof module === "object") {
|
|
40
|
+
module.exports = pluralize2();
|
|
41
|
+
} else if (typeof define === "function" && define.amd) {
|
|
42
|
+
define(function() {
|
|
43
|
+
return pluralize2();
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
root.pluralize = pluralize2();
|
|
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 pluralize2(word, count, inclusive) {
|
|
121
|
+
var pluralized = count === 1 ? pluralize2.singular(word) : pluralize2.plural(word);
|
|
122
|
+
return (inclusive ? count + " " : "") + pluralized;
|
|
123
|
+
}
|
|
124
|
+
pluralize2.plural = replaceWord(
|
|
125
|
+
irregularSingles,
|
|
126
|
+
irregularPlurals,
|
|
127
|
+
pluralRules
|
|
128
|
+
);
|
|
129
|
+
pluralize2.isPlural = checkWord(
|
|
130
|
+
irregularSingles,
|
|
131
|
+
irregularPlurals,
|
|
132
|
+
pluralRules
|
|
133
|
+
);
|
|
134
|
+
pluralize2.singular = replaceWord(
|
|
135
|
+
irregularPlurals,
|
|
136
|
+
irregularSingles,
|
|
137
|
+
singularRules
|
|
138
|
+
);
|
|
139
|
+
pluralize2.isSingular = checkWord(
|
|
140
|
+
irregularPlurals,
|
|
141
|
+
irregularSingles,
|
|
142
|
+
singularRules
|
|
143
|
+
);
|
|
144
|
+
pluralize2.addPluralRule = function(rule, replacement) {
|
|
145
|
+
pluralRules.push([sanitizeRule(rule), replacement]);
|
|
146
|
+
};
|
|
147
|
+
pluralize2.addSingularRule = function(rule, replacement) {
|
|
148
|
+
singularRules.push([sanitizeRule(rule), replacement]);
|
|
149
|
+
};
|
|
150
|
+
pluralize2.addUncountableRule = function(word) {
|
|
151
|
+
if (typeof word === "string") {
|
|
152
|
+
uncountables[word.toLowerCase()] = true;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
pluralize2.addPluralRule(word, "$0");
|
|
156
|
+
pluralize2.addSingularRule(word, "$0");
|
|
157
|
+
};
|
|
158
|
+
pluralize2.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 pluralize2.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 pluralize2.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 pluralize2.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(pluralize2.addUncountableRule);
|
|
387
|
+
return pluralize2;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
1
392
|
// packages/dart/src/lib/generate.ts
|
|
2
393
|
import { parse as partContentType } from "fast-content-type-parse";
|
|
3
394
|
import { merge as merge2 } from "lodash-es";
|
|
4
395
|
import assert2 from "node:assert";
|
|
5
|
-
import { writeFile } from "node:fs/promises";
|
|
396
|
+
import { readdir, writeFile } from "node:fs/promises";
|
|
6
397
|
import { join } from "node:path";
|
|
7
398
|
import { camelcase as camelcase3 } from "stringcase";
|
|
8
399
|
import yaml from "yaml";
|
|
9
400
|
import {
|
|
10
401
|
followRef as followRef3,
|
|
11
|
-
isEmpty as
|
|
12
|
-
isRef as
|
|
402
|
+
isEmpty as isEmpty3,
|
|
403
|
+
isRef as isRef4,
|
|
13
404
|
notRef as notRef2,
|
|
14
405
|
pascalcase as pascalcase2,
|
|
15
406
|
snakecase as snakecase2
|
|
16
407
|
} from "@sdk-it/core";
|
|
17
|
-
import {
|
|
408
|
+
import {
|
|
409
|
+
getFolderExportsV2,
|
|
410
|
+
writeFiles
|
|
411
|
+
} from "@sdk-it/core/file-system.js";
|
|
18
412
|
|
|
19
|
-
// packages/spec/dist/lib/
|
|
20
|
-
import {
|
|
413
|
+
// packages/spec/dist/lib/operation.js
|
|
414
|
+
import { camelcase } from "stringcase";
|
|
415
|
+
import { followRef, isRef as isRef2 } from "@sdk-it/core/ref.js";
|
|
21
416
|
|
|
22
|
-
// packages/spec/dist/lib/
|
|
23
|
-
import {
|
|
417
|
+
// packages/spec/dist/lib/pagination/pagination.js
|
|
418
|
+
import { isRef } from "@sdk-it/core/ref.js";
|
|
419
|
+
import { isEmpty } from "@sdk-it/core/utils.js";
|
|
420
|
+
|
|
421
|
+
// packages/spec/dist/lib/pagination/pagination-result.js
|
|
422
|
+
var import_pluralize = __toESM(require_pluralize(), 1);
|
|
423
|
+
var PRIMARY_TOP_TIER_KEYWORDS = [
|
|
424
|
+
"data",
|
|
425
|
+
"items",
|
|
426
|
+
"results",
|
|
427
|
+
"value"
|
|
428
|
+
];
|
|
429
|
+
var PRIMARY_OTHER_KEYWORDS = [
|
|
430
|
+
"records",
|
|
431
|
+
"content",
|
|
432
|
+
"list",
|
|
433
|
+
"payload",
|
|
434
|
+
"entities",
|
|
435
|
+
"collection",
|
|
436
|
+
"users",
|
|
437
|
+
"products",
|
|
438
|
+
"orders",
|
|
439
|
+
"bookings",
|
|
440
|
+
"articles",
|
|
441
|
+
"posts",
|
|
442
|
+
"documents",
|
|
443
|
+
"events"
|
|
444
|
+
];
|
|
445
|
+
var SECONDARY_KEYWORDS = ["entries", "rows", "elements"];
|
|
446
|
+
var PLURAL_DEPRIORITIZE_LIST = [
|
|
447
|
+
"status",
|
|
448
|
+
"success",
|
|
449
|
+
"address",
|
|
450
|
+
"details",
|
|
451
|
+
"properties",
|
|
452
|
+
"params",
|
|
453
|
+
"headers",
|
|
454
|
+
"cookies",
|
|
455
|
+
"series",
|
|
456
|
+
"links",
|
|
457
|
+
"meta",
|
|
458
|
+
"metadata",
|
|
459
|
+
"statistics",
|
|
460
|
+
"settings",
|
|
461
|
+
"options",
|
|
462
|
+
"permissions",
|
|
463
|
+
"credentials",
|
|
464
|
+
"diagnostics",
|
|
465
|
+
"warnings",
|
|
466
|
+
"errors",
|
|
467
|
+
"actions",
|
|
468
|
+
"attributes",
|
|
469
|
+
"categories",
|
|
470
|
+
"features",
|
|
471
|
+
"includes",
|
|
472
|
+
"tags"
|
|
473
|
+
];
|
|
474
|
+
var HAS_MORE_PRIMARY_POSITIVE_EXACT = [
|
|
475
|
+
"hasmore",
|
|
476
|
+
"hasnext",
|
|
477
|
+
"hasnextpage",
|
|
478
|
+
"moreitems",
|
|
479
|
+
"moreitemsavailable",
|
|
480
|
+
"nextpage",
|
|
481
|
+
"nextpageexists",
|
|
482
|
+
"nextpageavailable",
|
|
483
|
+
"hasadditionalresults",
|
|
484
|
+
"moreresultsavailable",
|
|
485
|
+
"canloadmore",
|
|
486
|
+
"hasadditional",
|
|
487
|
+
"additionalitems",
|
|
488
|
+
"fetchmore"
|
|
489
|
+
];
|
|
490
|
+
var HAS_MORE_SECONDARY_POSITIVE_EXACT = ["more", "next"];
|
|
491
|
+
var HAS_MORE_PRIMARY_INVERTED_EXACT = [
|
|
492
|
+
"islast",
|
|
493
|
+
"lastpage",
|
|
494
|
+
"endofresults",
|
|
495
|
+
"endoflist",
|
|
496
|
+
"nomoreitems",
|
|
497
|
+
"nomoredata",
|
|
498
|
+
"allitemsloaded",
|
|
499
|
+
"iscomplete",
|
|
500
|
+
"completed"
|
|
501
|
+
];
|
|
502
|
+
var HAS_MORE_POSITIVE_REGEX_PATTERNS = [
|
|
503
|
+
"\\bhas_?more\\b",
|
|
504
|
+
"\\bhas_?next\\b",
|
|
505
|
+
// e.g., itemsHasNext, items_has_next
|
|
506
|
+
"\\bmore_?items\\b",
|
|
507
|
+
"\\bnext_?page\\b",
|
|
508
|
+
// e.g., userNextPageFlag
|
|
509
|
+
"\\badditional\\b",
|
|
510
|
+
// e.g., hasAdditionalData, additional_results_exist
|
|
511
|
+
"\\bcontinuation\\b",
|
|
512
|
+
// e.g., continuationAvailable, has_continuation_token
|
|
513
|
+
"\\bmore_?results\\b",
|
|
514
|
+
"\\bpage_?available\\b",
|
|
515
|
+
"\\bnext(?:_?(page))?\\b"
|
|
516
|
+
];
|
|
517
|
+
var COMPILED_HAS_MORE_POSITIVE_REGEXES = HAS_MORE_POSITIVE_REGEX_PATTERNS.map((p) => new RegExp(p, "i"));
|
|
518
|
+
var HAS_MORE_INVERTED_REGEX_PATTERNS = [
|
|
519
|
+
"\\bis_?last\\b",
|
|
520
|
+
// e.g., pageIsLast
|
|
521
|
+
"\\blast_?page\\b",
|
|
522
|
+
// e.g., resultsAreLastPage
|
|
523
|
+
"\\bend_?of_?(data|results|list|items|stream)\\b",
|
|
524
|
+
"\\bno_?more_?(items|data|results)?\\b",
|
|
525
|
+
"\\ball_?(items_?)?loaded\\b",
|
|
526
|
+
"\\bis_?complete\\b"
|
|
527
|
+
];
|
|
528
|
+
var COMPILED_HAS_MORE_INVERTED_REGEXES = HAS_MORE_INVERTED_REGEX_PATTERNS.map((p) => new RegExp(p, "i"));
|
|
529
|
+
function getItemsName(properties) {
|
|
530
|
+
const arrayPropertyNames = [];
|
|
531
|
+
for (const propName in properties) {
|
|
532
|
+
if (propName in properties) {
|
|
533
|
+
const propSchema = properties[propName];
|
|
534
|
+
if (propSchema && propSchema.type === "array") {
|
|
535
|
+
arrayPropertyNames.push(propName);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (arrayPropertyNames.length === 0) {
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
if (arrayPropertyNames.length === 1) {
|
|
543
|
+
return arrayPropertyNames[0];
|
|
544
|
+
}
|
|
545
|
+
let bestCandidate = null;
|
|
546
|
+
let candidateRank = Infinity;
|
|
547
|
+
const updateCandidate = (propName, rank) => {
|
|
548
|
+
if (rank < candidateRank) {
|
|
549
|
+
bestCandidate = propName;
|
|
550
|
+
candidateRank = rank;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
for (const propName of arrayPropertyNames) {
|
|
554
|
+
const lowerPropName = propName.toLowerCase();
|
|
555
|
+
if (PRIMARY_TOP_TIER_KEYWORDS.includes(lowerPropName)) {
|
|
556
|
+
updateCandidate(propName, 2);
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
if (candidateRank > 3 && PRIMARY_OTHER_KEYWORDS.includes(lowerPropName)) {
|
|
560
|
+
updateCandidate(propName, 3);
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
if (candidateRank > 4 && SECONDARY_KEYWORDS.includes(lowerPropName)) {
|
|
564
|
+
updateCandidate(propName, 4);
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
if (candidateRank > 5 && import_pluralize.default.isPlural(propName) && !PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
|
|
568
|
+
updateCandidate(propName, 5);
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
if (candidateRank > 6 && import_pluralize.default.isPlural(propName) && PLURAL_DEPRIORITIZE_LIST.includes(lowerPropName)) {
|
|
572
|
+
updateCandidate(propName, 6);
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (bestCandidate) {
|
|
577
|
+
return bestCandidate;
|
|
578
|
+
}
|
|
579
|
+
return arrayPropertyNames[0];
|
|
580
|
+
}
|
|
581
|
+
function guess(properties) {
|
|
582
|
+
const booleanPropertyNames = [];
|
|
583
|
+
for (const propName in properties) {
|
|
584
|
+
if (Object.prototype.hasOwnProperty.call(properties, propName)) {
|
|
585
|
+
const propSchema = properties[propName];
|
|
586
|
+
if (propSchema && propSchema.type === "boolean" || propSchema.type === "integer") {
|
|
587
|
+
booleanPropertyNames.push(propName);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (booleanPropertyNames.length === 0) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
if (booleanPropertyNames.length === 1) {
|
|
595
|
+
return booleanPropertyNames[0];
|
|
596
|
+
}
|
|
597
|
+
let bestCandidate = null;
|
|
598
|
+
let candidateRank = Infinity;
|
|
599
|
+
const updateCandidate = (propName, rank) => {
|
|
600
|
+
if (rank < candidateRank) {
|
|
601
|
+
bestCandidate = propName;
|
|
602
|
+
candidateRank = rank;
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
for (const propName of booleanPropertyNames) {
|
|
606
|
+
const normalizedForExactMatch = propName.toLowerCase().replace(/[-_]/g, "");
|
|
607
|
+
let currentPropRank = Infinity;
|
|
608
|
+
if (HAS_MORE_PRIMARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {
|
|
609
|
+
currentPropRank = 1;
|
|
610
|
+
} else if (HAS_MORE_SECONDARY_POSITIVE_EXACT.includes(normalizedForExactMatch)) {
|
|
611
|
+
currentPropRank = 2;
|
|
612
|
+
} else {
|
|
613
|
+
let foundPositiveRegex = false;
|
|
614
|
+
for (const regex of COMPILED_HAS_MORE_POSITIVE_REGEXES) {
|
|
615
|
+
if (regex.test(propName)) {
|
|
616
|
+
currentPropRank = 3;
|
|
617
|
+
foundPositiveRegex = true;
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (!foundPositiveRegex) {
|
|
622
|
+
if (HAS_MORE_PRIMARY_INVERTED_EXACT.includes(normalizedForExactMatch)) {
|
|
623
|
+
currentPropRank = 4;
|
|
624
|
+
} else {
|
|
625
|
+
for (const regex of COMPILED_HAS_MORE_INVERTED_REGEXES) {
|
|
626
|
+
if (regex.test(propName)) {
|
|
627
|
+
currentPropRank = 5;
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
updateCandidate(propName, currentPropRank);
|
|
635
|
+
}
|
|
636
|
+
return bestCandidate;
|
|
637
|
+
}
|
|
638
|
+
function getHasMoreName(properties) {
|
|
639
|
+
const rootGuess = guess(properties);
|
|
640
|
+
if (rootGuess) {
|
|
641
|
+
return rootGuess;
|
|
642
|
+
}
|
|
643
|
+
for (const propName in properties) {
|
|
644
|
+
const propSchema = properties[propName];
|
|
645
|
+
if (propSchema.type === "object" && propSchema.properties) {
|
|
646
|
+
const nested = getHasMoreName(propSchema.properties);
|
|
647
|
+
if (nested) {
|
|
648
|
+
return propName + "." + nested;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// packages/spec/dist/lib/pagination/pagination.js
|
|
656
|
+
var OFFSET_PARAM_REGEXES = [
|
|
657
|
+
/\boffset\b/i,
|
|
658
|
+
/\bskip\b/i,
|
|
659
|
+
/\bstart(?:ing_at|_index)?\b/i,
|
|
660
|
+
// e.g., start, starting_at, start_index
|
|
661
|
+
/\bfrom\b/i
|
|
662
|
+
];
|
|
663
|
+
var GENERIC_LIMIT_PARAM_REGEXES = [
|
|
664
|
+
/\blimit\b/i,
|
|
665
|
+
/\bcount\b/i,
|
|
666
|
+
/\b(?:page_?)?size\b/i,
|
|
667
|
+
// e.g., size, page_size, pagesize
|
|
668
|
+
/\bmax_results\b/i,
|
|
669
|
+
/\bnum_results\b/i,
|
|
670
|
+
/\bshow\b/i,
|
|
671
|
+
// Can sometimes mean limit
|
|
672
|
+
/\bper_?page\b/i,
|
|
673
|
+
// e.g., per_page, perpage
|
|
674
|
+
/\bper-page\b/i,
|
|
675
|
+
/\btake\b/i
|
|
676
|
+
];
|
|
677
|
+
var PAGE_NUMBER_REGEXES = [
|
|
678
|
+
/^page$/i,
|
|
679
|
+
// Exact match for "page"
|
|
680
|
+
/^p$/i,
|
|
681
|
+
// Exact match for "p" (common shorthand)
|
|
682
|
+
/\bpage_?(?:number|num|idx|index)\b/i
|
|
683
|
+
// e.g., page_number, pageNumber, page_num, page_idx
|
|
684
|
+
];
|
|
685
|
+
var PAGE_SIZE_REGEXES = [
|
|
686
|
+
/\bpage_?size\b/i,
|
|
687
|
+
// e.g., page_size, pagesize
|
|
688
|
+
/^size$/i,
|
|
689
|
+
// Exact "size"
|
|
690
|
+
// /\bsize\b/i, // Broader "size" - can be ambiguous, prefer more specific ones first
|
|
691
|
+
/\blimit\b/i,
|
|
692
|
+
// Limit is often used for page size
|
|
693
|
+
/\bcount\b/i,
|
|
694
|
+
// Count can also be used for page size
|
|
695
|
+
/\bper_?page\b/i,
|
|
696
|
+
// e.g., per_page, perpage
|
|
697
|
+
/\bper-page\b/i,
|
|
698
|
+
/\bnum_?(?:items|records|results)\b/i,
|
|
699
|
+
// e.g., num_items, numitems
|
|
700
|
+
/\bresults_?per_?page\b/i
|
|
701
|
+
];
|
|
702
|
+
var CURSOR_REGEXES = [
|
|
703
|
+
/\bcursor\b/i,
|
|
704
|
+
/\bafter(?:_?cursor)?\b/i,
|
|
705
|
+
// e.g., after, after_cursor
|
|
706
|
+
/\bbefore(?:_?cursor)?\b/i,
|
|
707
|
+
// e.g., before, before_cursor
|
|
708
|
+
/\b(next|prev|previous)_?(?:page_?)?token\b/i,
|
|
709
|
+
// e.g., next_page_token, nextPageToken, prev_token
|
|
710
|
+
/\b(next|prev|previous)_?cursor\b/i,
|
|
711
|
+
// e.g., next_cursor, previousCursor
|
|
712
|
+
/\bcontinuation(?:_?token)?\b/i,
|
|
713
|
+
// e.g., continuation, continuation_token
|
|
714
|
+
/\bpage(?:_?(token|id))?\b/i,
|
|
715
|
+
// e.g., after, after_cursor
|
|
716
|
+
/\bstart_?(?:key|cursor|token|after)\b/i
|
|
717
|
+
// e.g., start_key, startCursor, startToken, startAfter
|
|
718
|
+
];
|
|
719
|
+
var CURSOR_LIMIT_REGEXES = [
|
|
720
|
+
/\blimit\b/i,
|
|
721
|
+
/\bcount\b/i,
|
|
722
|
+
/\bsize\b/i,
|
|
723
|
+
// General size
|
|
724
|
+
/\bfirst\b/i,
|
|
725
|
+
// Common in Relay-style cursor pagination (forward pagination)
|
|
726
|
+
/\blast\b/i,
|
|
727
|
+
// Common in Relay-style cursor pagination (backward pagination)
|
|
728
|
+
/\bpage_?size\b/i,
|
|
729
|
+
// Sometimes page_size is used with cursors
|
|
730
|
+
/\bnum_?(?:items|records|results)\b/i,
|
|
731
|
+
// e.g., num_items
|
|
732
|
+
/\bmax_?items\b/i,
|
|
733
|
+
/\btake\b/i
|
|
734
|
+
];
|
|
735
|
+
function findParamAndKeyword(queryParams, regexes, excludeParamName) {
|
|
736
|
+
for (const param of queryParams) {
|
|
737
|
+
if (param.name === excludeParamName) {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
for (const regex of regexes) {
|
|
741
|
+
const match = param.name.match(regex);
|
|
742
|
+
if (match) {
|
|
743
|
+
return { param, keyword: match[0] };
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
function isOffsetPagination(operation, parameters) {
|
|
750
|
+
const offsetMatch = findParamAndKeyword(parameters, OFFSET_PARAM_REGEXES);
|
|
751
|
+
if (!offsetMatch)
|
|
752
|
+
return null;
|
|
753
|
+
const limitMatch = findParamAndKeyword(
|
|
754
|
+
parameters,
|
|
755
|
+
GENERIC_LIMIT_PARAM_REGEXES,
|
|
756
|
+
offsetMatch.param.name
|
|
757
|
+
);
|
|
758
|
+
if (!limitMatch)
|
|
759
|
+
return null;
|
|
760
|
+
return {
|
|
761
|
+
type: "offset",
|
|
762
|
+
offsetParamName: offsetMatch.param.name,
|
|
763
|
+
offsetKeyword: offsetMatch.keyword,
|
|
764
|
+
limitParamName: limitMatch.param.name,
|
|
765
|
+
limitKeyword: limitMatch.keyword
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
function isPagePagination(operation) {
|
|
769
|
+
const queryParams = operation.parameters.filter((p) => p.in === "query").filter(
|
|
770
|
+
(it) => it.schema && !isRef(it.schema) && it.schema.type === "integer"
|
|
771
|
+
);
|
|
772
|
+
if (queryParams.length < 2)
|
|
773
|
+
return null;
|
|
774
|
+
const pageNoMatch = findParamAndKeyword(queryParams, PAGE_NUMBER_REGEXES);
|
|
775
|
+
if (!pageNoMatch)
|
|
776
|
+
return null;
|
|
777
|
+
const pageSizeMatch = findParamAndKeyword(
|
|
778
|
+
queryParams,
|
|
779
|
+
PAGE_SIZE_REGEXES,
|
|
780
|
+
pageNoMatch.param.name
|
|
781
|
+
);
|
|
782
|
+
if (!pageSizeMatch)
|
|
783
|
+
return null;
|
|
784
|
+
return {
|
|
785
|
+
type: "page",
|
|
786
|
+
pageNumberParamName: pageNoMatch.param.name,
|
|
787
|
+
pageNumberKeyword: pageNoMatch.keyword,
|
|
788
|
+
pageSizeParamName: pageSizeMatch.param.name,
|
|
789
|
+
pageSizeKeyword: pageSizeMatch.keyword
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
function isCursorPagination(operation) {
|
|
793
|
+
const queryParams = operation.parameters.filter((p) => p.in === "query");
|
|
794
|
+
if (queryParams.length < 2)
|
|
795
|
+
return null;
|
|
796
|
+
const cursorMatch = findParamAndKeyword(queryParams, CURSOR_REGEXES);
|
|
797
|
+
if (!cursorMatch)
|
|
798
|
+
return null;
|
|
799
|
+
const limitMatch = findParamAndKeyword(
|
|
800
|
+
queryParams,
|
|
801
|
+
CURSOR_LIMIT_REGEXES,
|
|
802
|
+
cursorMatch.param.name
|
|
803
|
+
);
|
|
804
|
+
if (!limitMatch)
|
|
805
|
+
return null;
|
|
806
|
+
return {
|
|
807
|
+
type: "cursor",
|
|
808
|
+
cursorParamName: cursorMatch.param.name,
|
|
809
|
+
cursorKeyword: cursorMatch.keyword,
|
|
810
|
+
limitParamName: limitMatch.param.name,
|
|
811
|
+
limitKeyword: limitMatch.keyword
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
function guessPagination(operation, body, response) {
|
|
815
|
+
const bodyParameters = body && body.properties ? Object.keys(body.properties).map((it) => ({ name: it })) : [];
|
|
816
|
+
const parameters = operation.parameters;
|
|
817
|
+
if (isEmpty(operation.parameters) && isEmpty(bodyParameters)) {
|
|
818
|
+
return { type: "none", reason: "no parameters" };
|
|
819
|
+
}
|
|
820
|
+
if (!response) {
|
|
821
|
+
return { type: "none", reason: "no response" };
|
|
822
|
+
}
|
|
823
|
+
if (!response.properties) {
|
|
824
|
+
return { type: "none", reason: "empty response" };
|
|
825
|
+
}
|
|
826
|
+
const properties = response.properties;
|
|
827
|
+
const itemsKey = getItemsName(properties);
|
|
828
|
+
if (!itemsKey) {
|
|
829
|
+
return { type: "none", reason: "no items key" };
|
|
830
|
+
}
|
|
831
|
+
const hasMoreKey = getHasMoreName(excludeKey(properties, itemsKey));
|
|
832
|
+
if (!hasMoreKey) {
|
|
833
|
+
return { type: "none", reason: "no hasMore key" };
|
|
834
|
+
}
|
|
835
|
+
const pagination = isOffsetPagination(operation, [...parameters, ...bodyParameters]) || isPagePagination(operation) || isCursorPagination(operation);
|
|
836
|
+
return pagination ? { ...pagination, items: itemsKey, hasMore: hasMoreKey } : { type: "none", reason: "no pagination" };
|
|
837
|
+
}
|
|
838
|
+
function excludeKey(obj, key) {
|
|
839
|
+
const { [key]: _, ...rest } = obj;
|
|
840
|
+
return rest;
|
|
841
|
+
}
|
|
24
842
|
|
|
25
843
|
// packages/spec/dist/lib/operation.js
|
|
26
|
-
|
|
27
|
-
|
|
844
|
+
function augmentSpec(config) {
|
|
845
|
+
config.spec.paths ??= {};
|
|
846
|
+
const paths = {};
|
|
847
|
+
for (const [path, pathItem] of Object.entries(config.spec.paths)) {
|
|
848
|
+
const { parameters = [], ...methods } = pathItem;
|
|
849
|
+
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
850
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
851
|
+
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
852
|
+
const formatTag = config.tag ?? defaults.tag;
|
|
853
|
+
const operationId = formatOperationId(operation, fixedPath, method);
|
|
854
|
+
const operationTag = formatTag(operation, fixedPath);
|
|
855
|
+
const requestBody = isRef2(operation.requestBody) ? followRef(config.spec, operation.requestBody.$ref) : operation.requestBody;
|
|
856
|
+
const tunedOperation = {
|
|
857
|
+
...operation,
|
|
858
|
+
parameters: [...parameters, ...operation.parameters ?? []].map(
|
|
859
|
+
(it) => isRef2(it) ? followRef(config.spec, it.$ref) : it
|
|
860
|
+
),
|
|
861
|
+
tags: [operationTag],
|
|
862
|
+
operationId,
|
|
863
|
+
responses: resolveResponses(config.spec, operation),
|
|
864
|
+
requestBody
|
|
865
|
+
};
|
|
866
|
+
tunedOperation["x-pagination"] = toPagination(
|
|
867
|
+
config.spec,
|
|
868
|
+
tunedOperation
|
|
869
|
+
);
|
|
870
|
+
Object.assign(paths, {
|
|
871
|
+
[fixedPath]: {
|
|
872
|
+
...paths[fixedPath],
|
|
873
|
+
[method]: tunedOperation
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return { ...config.spec, paths };
|
|
879
|
+
}
|
|
880
|
+
function toPagination(spec, tunedOperation) {
|
|
881
|
+
if (tunedOperation["x-pagination"]) {
|
|
882
|
+
return tunedOperation["x-pagination"];
|
|
883
|
+
}
|
|
884
|
+
const schema = getResponseContentSchema(
|
|
885
|
+
spec,
|
|
886
|
+
tunedOperation.responses["200"],
|
|
887
|
+
"application/json"
|
|
888
|
+
);
|
|
889
|
+
const pagination = guessPagination(
|
|
890
|
+
tunedOperation,
|
|
891
|
+
tunedOperation.requestBody ? getRequestContentSchema(
|
|
892
|
+
spec,
|
|
893
|
+
tunedOperation.requestBody,
|
|
894
|
+
"application/json"
|
|
895
|
+
) : void 0,
|
|
896
|
+
schema
|
|
897
|
+
);
|
|
898
|
+
if (pagination && pagination.type !== "none" && schema) {
|
|
899
|
+
return pagination;
|
|
900
|
+
}
|
|
901
|
+
return void 0;
|
|
902
|
+
}
|
|
903
|
+
function getResponseContentSchema(spec, response, type) {
|
|
904
|
+
if (!response) {
|
|
905
|
+
return void 0;
|
|
906
|
+
}
|
|
907
|
+
const content = response.content;
|
|
908
|
+
if (!content) {
|
|
909
|
+
return void 0;
|
|
910
|
+
}
|
|
911
|
+
for (const contentType in content) {
|
|
912
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
913
|
+
return isRef2(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
return void 0;
|
|
917
|
+
}
|
|
918
|
+
function getRequestContentSchema(spec, requestBody, type) {
|
|
919
|
+
const content = requestBody.content;
|
|
920
|
+
if (!content) {
|
|
921
|
+
return void 0;
|
|
922
|
+
}
|
|
923
|
+
for (const contentType in content) {
|
|
924
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
925
|
+
return isRef2(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return void 0;
|
|
929
|
+
}
|
|
28
930
|
var defaults = {
|
|
29
931
|
operationId: (operation, path, method) => {
|
|
30
932
|
if (operation.operationId) {
|
|
@@ -46,7 +948,7 @@ function resolveResponses(spec, operation) {
|
|
|
46
948
|
const responses = operation.responses ?? {};
|
|
47
949
|
const resolved = {};
|
|
48
950
|
for (const status in responses) {
|
|
49
|
-
const response =
|
|
951
|
+
const response = isRef2(responses[status]) ? followRef(spec, responses[status].$ref) : responses[status];
|
|
50
952
|
resolved[status] = response;
|
|
51
953
|
}
|
|
52
954
|
return resolved;
|
|
@@ -55,28 +957,19 @@ function forEachOperation(config, callback) {
|
|
|
55
957
|
const result = [];
|
|
56
958
|
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
57
959
|
const { parameters = [], ...methods } = pathItem;
|
|
58
|
-
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
59
960
|
for (const [method, operation] of Object.entries(methods)) {
|
|
60
|
-
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
61
|
-
const formatTag = config.tag ?? defaults.tag;
|
|
62
|
-
const operationName = formatOperationId(operation, fixedPath, method);
|
|
63
|
-
const operationTag = formatTag(operation, fixedPath);
|
|
64
961
|
const metadata = operation["x-oaiMeta"] ?? {};
|
|
962
|
+
const operationTag = operation.tags?.[0];
|
|
65
963
|
result.push(
|
|
66
964
|
callback(
|
|
67
965
|
{
|
|
68
966
|
name: metadata.name,
|
|
69
967
|
method,
|
|
70
|
-
path
|
|
968
|
+
path,
|
|
71
969
|
groupName: operationTag,
|
|
72
970
|
tag: operationTag
|
|
73
971
|
},
|
|
74
|
-
|
|
75
|
-
...operation,
|
|
76
|
-
parameters: [...parameters, ...operation.parameters ?? []],
|
|
77
|
-
operationId: operationName,
|
|
78
|
-
responses: resolveResponses(config.spec, operation)
|
|
79
|
-
}
|
|
972
|
+
operation
|
|
80
973
|
)
|
|
81
974
|
);
|
|
82
975
|
}
|
|
@@ -287,6 +1180,68 @@ function isSuccessStatusCode(statusCode) {
|
|
|
287
1180
|
statusCode = Number(statusCode);
|
|
288
1181
|
return statusCode >= 200 && statusCode < 300;
|
|
289
1182
|
}
|
|
1183
|
+
function patchParameters(spec, objectSchema, operation) {
|
|
1184
|
+
const securitySchemes = spec.components?.securitySchemes ?? {};
|
|
1185
|
+
const securityOptions = securityToOptions(
|
|
1186
|
+
spec,
|
|
1187
|
+
operation.security ?? [],
|
|
1188
|
+
securitySchemes
|
|
1189
|
+
);
|
|
1190
|
+
objectSchema.properties ??= {};
|
|
1191
|
+
objectSchema.required ??= [];
|
|
1192
|
+
for (const param of operation.parameters) {
|
|
1193
|
+
if (param.required) {
|
|
1194
|
+
objectSchema.required.push(param.name);
|
|
1195
|
+
}
|
|
1196
|
+
objectSchema.properties[param.name] = isRef2(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
1197
|
+
}
|
|
1198
|
+
for (const param of securityOptions) {
|
|
1199
|
+
objectSchema.required = (objectSchema.required ?? []).filter(
|
|
1200
|
+
(name) => name !== param.name
|
|
1201
|
+
);
|
|
1202
|
+
objectSchema.properties[param.name] = isRef2(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
function securityToOptions(spec, security, securitySchemes, staticIn) {
|
|
1206
|
+
securitySchemes ??= {};
|
|
1207
|
+
const parameters = [];
|
|
1208
|
+
for (const it of security) {
|
|
1209
|
+
const [name] = Object.keys(it);
|
|
1210
|
+
if (!name) {
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
const schema = isRef2(securitySchemes[name]) ? followRef(spec, securitySchemes[name].$ref) : securitySchemes[name];
|
|
1214
|
+
if (schema.type === "http") {
|
|
1215
|
+
parameters.push({
|
|
1216
|
+
in: staticIn ?? "header",
|
|
1217
|
+
name: "authorization",
|
|
1218
|
+
schema: { type: "string" }
|
|
1219
|
+
});
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
if (schema.type === "apiKey") {
|
|
1223
|
+
if (!schema.in) {
|
|
1224
|
+
throw new Error(`apiKey security schema must have an "in" field`);
|
|
1225
|
+
}
|
|
1226
|
+
if (!schema.name) {
|
|
1227
|
+
throw new Error(`apiKey security schema must have a "name" field`);
|
|
1228
|
+
}
|
|
1229
|
+
parameters.push({
|
|
1230
|
+
in: staticIn ?? schema.in,
|
|
1231
|
+
name: schema.name,
|
|
1232
|
+
schema: { type: "string" }
|
|
1233
|
+
});
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
return parameters;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// packages/spec/dist/lib/loaders/local-loader.js
|
|
1241
|
+
import { parse } from "yaml";
|
|
1242
|
+
|
|
1243
|
+
// packages/spec/dist/lib/loaders/remote-loader.js
|
|
1244
|
+
import { parse as parse2 } from "yaml";
|
|
290
1245
|
|
|
291
1246
|
// packages/dart/src/lib/dart-emitter.ts
|
|
292
1247
|
import { merge } from "lodash-es";
|
|
@@ -295,8 +1250,8 @@ import { camelcase as camelcase2, snakecase } from "stringcase";
|
|
|
295
1250
|
import {
|
|
296
1251
|
cleanRef,
|
|
297
1252
|
followRef as followRef2,
|
|
298
|
-
isEmpty,
|
|
299
|
-
isRef as
|
|
1253
|
+
isEmpty as isEmpty2,
|
|
1254
|
+
isRef as isRef3,
|
|
300
1255
|
notRef,
|
|
301
1256
|
parseRef,
|
|
302
1257
|
pascalcase
|
|
@@ -344,7 +1299,7 @@ var DartSerializer = class {
|
|
|
344
1299
|
this.#spec.components.schemas ??= {};
|
|
345
1300
|
this.#spec.components.responses ??= {};
|
|
346
1301
|
const checkSchema = (schema) => {
|
|
347
|
-
if (
|
|
1302
|
+
if (isRef3(schema)) {
|
|
348
1303
|
const { model } = parseRef(schema.$ref);
|
|
349
1304
|
return model === schemaName;
|
|
350
1305
|
}
|
|
@@ -377,7 +1332,7 @@ var DartSerializer = class {
|
|
|
377
1332
|
matches: `json['${camelcase2(context.name)}'] is Map<String, dynamic>`
|
|
378
1333
|
};
|
|
379
1334
|
}
|
|
380
|
-
if (
|
|
1335
|
+
if (isEmpty2(schema.properties)) {
|
|
381
1336
|
if (context.noEmit !== true) {
|
|
382
1337
|
this.#emit(
|
|
383
1338
|
className,
|
|
@@ -563,7 +1518,7 @@ return ${matches.join(" && ")};
|
|
|
563
1518
|
// fixme: this method should no longer be needed because the logic in it is being preprocessed before emitting begins
|
|
564
1519
|
#allOf(className, schemas, context) {
|
|
565
1520
|
const name = pascalcase(context.propName || className);
|
|
566
|
-
const refs = schemas.filter(
|
|
1521
|
+
const refs = schemas.filter(isRef3);
|
|
567
1522
|
const nonRefs = schemas.filter(notRef);
|
|
568
1523
|
if (nonRefs.some((it) => it.type && it.type !== "object")) {
|
|
569
1524
|
assert(false, `allOf ${name} must be an object`);
|
|
@@ -587,7 +1542,7 @@ return ${matches.join(" && ")};
|
|
|
587
1542
|
};
|
|
588
1543
|
}
|
|
589
1544
|
const nullSchemaIndex = schemas.findIndex((schema) => {
|
|
590
|
-
if (
|
|
1545
|
+
if (isRef3(schema)) {
|
|
591
1546
|
const refSchema = followRef2(this.#spec, schema.$ref);
|
|
592
1547
|
return refSchema.type === "null";
|
|
593
1548
|
}
|
|
@@ -628,7 +1583,7 @@ return ${matches.join(" && ")};
|
|
|
628
1583
|
const patterns = [];
|
|
629
1584
|
const objects = schemas.filter(notRef).filter((it) => it.type === "object");
|
|
630
1585
|
for (const schema of schemas) {
|
|
631
|
-
if (
|
|
1586
|
+
if (isRef3(schema)) {
|
|
632
1587
|
const refType = this.#ref(className, schema.$ref, true, context);
|
|
633
1588
|
patterns.push({
|
|
634
1589
|
pattern: `case ${refType.type || "Map<String, dynamic>"} map when ${refType.use}.matches(map): return ${refType.use}.fromJson(map);`,
|
|
@@ -879,7 +1834,7 @@ return false;
|
|
|
879
1834
|
};
|
|
880
1835
|
}
|
|
881
1836
|
#serialize(className, schema, required = true, context = {}) {
|
|
882
|
-
if (
|
|
1837
|
+
if (isRef3(schema)) {
|
|
883
1838
|
return this.#ref(className, schema.$ref, required, context);
|
|
884
1839
|
}
|
|
885
1840
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
@@ -943,14 +1898,14 @@ return false;
|
|
|
943
1898
|
}
|
|
944
1899
|
};
|
|
945
1900
|
function isObjectSchema(schema) {
|
|
946
|
-
return !
|
|
1901
|
+
return !isRef3(schema) && (schema.type === "object" || !!schema.properties);
|
|
947
1902
|
}
|
|
948
1903
|
|
|
949
1904
|
// packages/dart/src/lib/http/dispatcher.txt
|
|
950
1905
|
var dispatcher_default = "import 'dart:convert';\nimport 'dart:io';\n\nimport 'package:http/http.dart' as http;\nimport 'package:http_parser/http_parser.dart';\nimport 'package:mime/mime.dart' as mime;\n\nimport './interceptors.dart';\nimport './responses.dart';\n\nclass Dispatcher {\n final List<Interceptor> interceptors;\n\n Dispatcher(this.interceptors);\n\n Future<http.StreamedResponse> multipart(\n RequestConfig config,\n Map<String, dynamic> body,\n ) async {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n final request = http.MultipartRequest(\n modifiedConfig.method,\n modifiedConfig.url,\n );\n request.headers.addAll(modifiedConfig.headers);\n for (var entry in body.entries) {\n final key = entry.key;\n final value = entry.value;\n if (value is File) {\n final mimeType = mime.lookupMimeType(value.path);\n request.files.add(\n http.MultipartFile(\n key,\n value.openRead(),\n await value.length(),\n filename: value.uri.pathSegments.last,\n contentType: mimeType != null ? MediaType.parse(mimeType) : null,\n ),\n );\n } else {\n request.fields[key] = value.toString();\n }\n }\n\n return request.send();\n }\n\n Future<http.StreamedResponse> empty(RequestConfig config) {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n request.headers.addAll(modifiedConfig.headers);\n return request.send();\n }\n\n Future<http.StreamedResponse> json(RequestConfig config, dynamic body) {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n request.headers.addAll(modifiedConfig.headers);\n\n request.headers['Content-Type'] = 'application/json';\n if ((body is Map || body is List)) {\n request.body = jsonEncode(body);\n } else if (body is String) {\n request.body = body;\n } else {\n throw ArgumentError('Unsupported body type: ${body.runtimeType}');\n }\n\n return request.send();\n }\n}\n\nclass Receiver {\n final List<Interceptor> interceptors;\n Receiver(this.interceptors);\n\n dynamic _parse(http.Response response) {\n final contentTypeHeader = response.headers['content-type'];\n final parsed = parseContentType(contentTypeHeader);\n if (parsed.type == 'application/json') {\n return jsonDecode(response.body);\n } else if (parsed.type == 'text/plain') {\n return response.body;\n } else if (parsed.type == 'application/octet-stream') {\n return response.bodyBytes;\n } else {\n throw UnsupportedError('Unsupported content type: ${parsed.type}');\n }\n }\n\n dynamic json(http.StreamedResponse stream) async {\n if (stream.statusCode >= 200 && stream.statusCode < 300) {\n final response = await http.Response.fromStream(stream);\n return _parse(response);\n }\n switch (stream.statusCode) {\n case 400:\n throw BadRequestError('');\n case 401:\n throw UnauthorizedError('');\n case 403:\n throw ForbiddenError('');\n case 404:\n throw NotFoundError('');\n case 500:\n throw InternalServerError('');\n case 402:\n throw PaymentRequiredError('');\n case 405:\n throw MethodNotAllowedError('');\n case 406:\n throw NotAcceptableError('');\n case 409:\n throw ConflictError('');\n case 410:\n throw GoneError('');\n case 422:\n throw UnprocessableEntityError('');\n case 429:\n throw TooManyRequestsError('');\n case 413:\n throw PayloadTooLargeError('');\n case 415:\n throw UnsupportedMediaTypeError('');\n case 501:\n throw NotImplementedError('');\n case 502:\n throw BadGatewayError('');\n case 503:\n throw ServiceUnavailableError('');\n case 504:\n throw GatewayTimeoutError('');\n default:\n throw UnknownApiError('', stream.statusCode);\n }\n }\n}\n\n({String type, Map<String, String> parameters}) parseContentType(\n String? contentTypeHeader,\n) {\n if (contentTypeHeader == null || contentTypeHeader.isEmpty) {\n return (type: '', parameters: {});\n }\n final parts = contentTypeHeader.split(';');\n final type = parts[0].trim();\n final parameters = <String, String>{};\n for (var i = 1; i < parts.length; i++) {\n final param = parts[i].split('=');\n if (param.length == 2) {\n parameters[param[0].trim()] = param[1].trim();\n }\n }\n\n return (type: type, parameters: parameters);\n}\n";
|
|
951
1906
|
|
|
952
1907
|
// packages/dart/src/lib/http/interceptors.txt
|
|
953
|
-
var interceptors_default = "abstract class Interceptor {\n RequestConfig before(RequestConfig config);\n void after();\n}\n\nclass BaseUrlInterceptor extends Interceptor {\n final String Function() getBaseUrl;\n BaseUrlInterceptor(this.getBaseUrl);\n\n @override\n RequestConfig before(RequestConfig config) {\n final baseUrl = getBaseUrl();\n if (config.url.scheme.isEmpty) {\n config.url = Uri.parse(baseUrl + config.url.toString());\n }\n return config;\n }\n\n @override\n void after() {\n //\n }\n}\n\nclass RequestConfig {\n final String method;\n Uri url;\n final Map<String, String> headers;\n RequestConfig({required this.method, required this.url, required this.headers});\n}\n";
|
|
1908
|
+
var interceptors_default = "abstract class Interceptor {\n RequestConfig before(RequestConfig config);\n void after();\n}\n\nclass BaseUrlInterceptor extends Interceptor {\n final String Function() getBaseUrl;\n BaseUrlInterceptor(this.getBaseUrl);\n\n @override\n RequestConfig before(RequestConfig config) {\n final baseUrl = getBaseUrl();\n if (config.url.scheme.isEmpty) {\n config.url = Uri.parse(baseUrl + config.url.toString());\n }\n return config;\n }\n\n @override\n void after() {\n //\n }\n}\n\n\nclass LoggingInterceptor extends Interceptor {\n // ANSI color codes\n static const String _reset = '\\x1B[0m';\n static const String _green = '\\x1B[32m';\n static const String _yellow = '\\x1B[33m';\n static const String _blue = '\\x1B[34m';\n static const String _magenta = '\\x1B[35m';\n static const String _cyan = '\\x1B[36m';\n\n @override\n RequestConfig before(RequestConfig config) {\n print('${_cyan}[LOG] --- HTTP REQUEST ---$_reset');\n print('${_yellow}[LOG] Method: ${config.method.toUpperCase()}$_reset');\n print('${_green}[LOG] URL: ${config.url}$_reset');\n print('${_magenta}[ContentType] ${config.headers['content-type']}$_reset');\n if (config.headers.isNotEmpty) {\n print('${_blue}[LOG] Headers: ${config.headers}$_reset');\n } else {\n print('${_blue}[LOG] Headers: <none>$_reset');\n }\n print('${_cyan}[LOG] --------------$_reset');\n return config;\n }\n\n @override\n void after() {\n // Optionally log after the request\n }\n}\n\nclass RequestConfig {\n final String method;\n Uri url;\n final Map<String, String> headers;\n RequestConfig({required this.method, required this.url, required this.headers});\n}\n";
|
|
954
1909
|
|
|
955
1910
|
// packages/dart/src/lib/http/responses.txt
|
|
956
1911
|
var responses_default = "sealed class ApiError {\n final String message;\n final int? statusCode;\n final String status;\n const ApiError(this.message, {this.statusCode, this.status = ''});\n\n @override\n String toString() =>\n 'ApiError(status: $status, statusCode: $statusCode, message: $message)';\n}\n\nbase class BadRequestError extends ApiError {\n const BadRequestError(String message)\n : super(message, statusCode: 400, status: 'BadRequest');\n}\n\nbase class UnauthorizedError extends ApiError {\n const UnauthorizedError(String message)\n : super(message, statusCode: 401, status: 'Unauthorized');\n}\n\nbase class ForbiddenError extends ApiError {\n const ForbiddenError(String message)\n : super(message, statusCode: 403, status: 'Forbidden');\n}\n\nbase class NotFoundError extends ApiError {\n const NotFoundError(String message)\n : super(message, statusCode: 404, status: 'NotFound');\n}\n\nbase class InternalServerError extends ApiError {\n const InternalServerError(String message)\n : super(message, statusCode: 500, status: 'InternalServerError');\n}\n\nbase class UnknownApiError extends ApiError {\n const UnknownApiError(String message, int statusCode)\n : super(message, statusCode: statusCode, status: 'UnknownApiError');\n}\n\nbase class PaymentRequiredError extends ApiError {\n const PaymentRequiredError(String message)\n : super(message, statusCode: 402, status: 'PaymentRequired');\n}\n\nbase class MethodNotAllowedError extends ApiError {\n const MethodNotAllowedError(String message)\n : super(message, statusCode: 405, status: 'MethodNotAllowed');\n}\n\nbase class NotAcceptableError extends ApiError {\n const NotAcceptableError(String message)\n : super(message, statusCode: 406, status: 'NotAcceptable');\n}\n\nbase class ConflictError extends ApiError {\n const ConflictError(String message)\n : super(message, statusCode: 409, status: 'Conflict');\n}\n\nbase class GoneError extends ApiError {\n const GoneError(String message)\n : super(message, statusCode: 410, status: 'Gone');\n}\n\nbase class UnprocessableEntityError extends ApiError {\n const UnprocessableEntityError(String message)\n : super(message, statusCode: 422, status: 'UnprocessableEntity');\n}\n\nbase class TooManyRequestsError extends ApiError {\n const TooManyRequestsError(String message)\n : super(message, statusCode: 429, status: 'TooManyRequests');\n}\n\nbase class PayloadTooLargeError extends ApiError {\n const PayloadTooLargeError(String message)\n : super(message, statusCode: 413, status: 'PayloadTooLarge');\n}\n\nbase class UnsupportedMediaTypeError extends ApiError {\n const UnsupportedMediaTypeError(String message)\n : super(message, statusCode: 415, status: 'UnsupportedMediaType');\n}\n\nbase class NotImplementedError extends ApiError {\n const NotImplementedError(String message)\n : super(message, statusCode: 501, status: 'NotImplemented');\n}\n\nbase class BadGatewayError extends ApiError {\n const BadGatewayError(String message)\n : super(message, statusCode: 502, status: 'BadGateway');\n}\n\nbase class ServiceUnavailableError extends ApiError {\n const ServiceUnavailableError(String message)\n : super(message, statusCode: 503, status: 'ServiceUnavailable');\n}\n\nbase class GatewayTimeoutError extends ApiError {\n const GatewayTimeoutError(String message)\n : super(message, statusCode: 504, status: 'GatewayTimeout');\n}\n";
|
|
@@ -958,14 +1913,14 @@ var responses_default = "sealed class ApiError {\n final String message;\n fin
|
|
|
958
1913
|
// packages/dart/src/lib/generate.ts
|
|
959
1914
|
function tuneSpec(spec, schemas, refs) {
|
|
960
1915
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
961
|
-
if (
|
|
1916
|
+
if (isRef4(schema))
|
|
962
1917
|
continue;
|
|
963
|
-
if (!
|
|
1918
|
+
if (!isEmpty3(schema.anyOf) && !isEmpty3(schema.oneOf)) {
|
|
964
1919
|
delete schema.anyOf;
|
|
965
1920
|
}
|
|
966
|
-
if (!
|
|
1921
|
+
if (!isEmpty3(schema.allOf)) {
|
|
967
1922
|
const schemas2 = schema.allOf;
|
|
968
|
-
const refs2 = schemas2.filter(
|
|
1923
|
+
const refs2 = schemas2.filter(isRef4);
|
|
969
1924
|
const nonRefs = schemas2.filter(notRef2);
|
|
970
1925
|
if (nonRefs.some((it) => it.type && it.type !== "object")) {
|
|
971
1926
|
assert2(false, `allOf ${name} must be an object`);
|
|
@@ -980,12 +1935,12 @@ function tuneSpec(spec, schemas, refs) {
|
|
|
980
1935
|
Object.assign(schema, objectSchema);
|
|
981
1936
|
}
|
|
982
1937
|
if (schema.type === "object") {
|
|
983
|
-
if (!
|
|
1938
|
+
if (!isEmpty3(schema.oneOf)) {
|
|
984
1939
|
for (const oneOfIdx in schema.oneOf) {
|
|
985
1940
|
const oneOf = schema.oneOf[oneOfIdx];
|
|
986
|
-
if (
|
|
1941
|
+
if (isRef4(oneOf))
|
|
987
1942
|
continue;
|
|
988
|
-
if (!
|
|
1943
|
+
if (!isEmpty3(oneOf.required) && schema.properties) {
|
|
989
1944
|
schema.oneOf[oneOfIdx] = schema.properties[oneOf.required[0]];
|
|
990
1945
|
}
|
|
991
1946
|
}
|
|
@@ -995,7 +1950,7 @@ function tuneSpec(spec, schemas, refs) {
|
|
|
995
1950
|
}
|
|
996
1951
|
schema.properties ??= {};
|
|
997
1952
|
for (const [propName, value] of Object.entries(schema.properties)) {
|
|
998
|
-
if (
|
|
1953
|
+
if (isRef4(value))
|
|
999
1954
|
continue;
|
|
1000
1955
|
const refName = pascalcase2(`${name} ${propName.replace("[]", "")}`);
|
|
1001
1956
|
refs.push({ name: refName, value });
|
|
@@ -1010,7 +1965,7 @@ function tuneSpec(spec, schemas, refs) {
|
|
|
1010
1965
|
tuneSpec(spec, props, refs);
|
|
1011
1966
|
}
|
|
1012
1967
|
} else if (schema.type === "array") {
|
|
1013
|
-
if (
|
|
1968
|
+
if (isRef4(schema.items))
|
|
1014
1969
|
continue;
|
|
1015
1970
|
const refName = name;
|
|
1016
1971
|
refs.push({ name: refName, value: schema.items ?? {} });
|
|
@@ -1021,6 +1976,16 @@ function tuneSpec(spec, schemas, refs) {
|
|
|
1021
1976
|
}
|
|
1022
1977
|
}
|
|
1023
1978
|
async function generate(spec, settings) {
|
|
1979
|
+
spec = "x-sdk-augmented" in spec ? spec : augmentSpec({ spec });
|
|
1980
|
+
settings.writer ??= writeFiles;
|
|
1981
|
+
settings.readFolder ??= async (folder) => {
|
|
1982
|
+
const files = await readdir(folder, { withFileTypes: true });
|
|
1983
|
+
return files.map((file) => ({
|
|
1984
|
+
fileName: file.name,
|
|
1985
|
+
filePath: join(file.parentPath, file.name),
|
|
1986
|
+
isFolder: file.isDirectory()
|
|
1987
|
+
}));
|
|
1988
|
+
};
|
|
1024
1989
|
const clientName = settings.name || "Client";
|
|
1025
1990
|
const output = join(settings.output, "lib");
|
|
1026
1991
|
const groups = {};
|
|
@@ -1036,12 +2001,12 @@ async function generate(spec, settings) {
|
|
|
1036
2001
|
if (!isSuccessStatusCode(status))
|
|
1037
2002
|
continue;
|
|
1038
2003
|
const response2 = operation.responses[status];
|
|
1039
|
-
if (!
|
|
2004
|
+
if (!isEmpty3(response2.content)) {
|
|
1040
2005
|
for (const [contentType, mediaType] of Object.entries(
|
|
1041
2006
|
response2.content
|
|
1042
2007
|
)) {
|
|
1043
2008
|
if (parseJsonContentType(contentType)) {
|
|
1044
|
-
if (mediaType.schema && !
|
|
2009
|
+
if (mediaType.schema && !isRef4(mediaType.schema)) {
|
|
1045
2010
|
const outputName = pascalcase2(`${operation.operationId} output`);
|
|
1046
2011
|
spec.components.schemas[outputName] = mediaType.schema;
|
|
1047
2012
|
operation.responses[status].content ??= {};
|
|
@@ -1066,7 +2031,7 @@ async function generate(spec, settings) {
|
|
|
1066
2031
|
}
|
|
1067
2032
|
group.methods.push(`
|
|
1068
2033
|
Future<${response ? response.returnType : "http.StreamedResponse"}> ${camelcase3(operation.operationId)}(
|
|
1069
|
-
${
|
|
2034
|
+
${isEmpty3(operation.requestBody) ? "" : `${input.inputName} input`}
|
|
1070
2035
|
) async {
|
|
1071
2036
|
final stream = await this.dispatcher.${input.contentType}(RequestConfig(
|
|
1072
2037
|
method: '${entry.method}',
|
|
@@ -1131,7 +2096,7 @@ import './http.dart';
|
|
|
1131
2096
|
${Object.keys(groups).map((name) => `late final ${pascalcase2(name)}Client ${camelcase3(name)};`).join("\n")}
|
|
1132
2097
|
|
|
1133
2098
|
${clientName}(this.options) {
|
|
1134
|
-
final interceptors = [BaseUrlInterceptor(() => this.options.baseUrl)];
|
|
2099
|
+
final interceptors = [BaseUrlInterceptor(() => this.options.baseUrl), LoggingInterceptor()];
|
|
1135
2100
|
final dispatcher = Dispatcher(interceptors);
|
|
1136
2101
|
final receiver = Receiver(interceptors);
|
|
1137
2102
|
${Object.keys(groups).map(
|
|
@@ -1154,39 +2119,55 @@ class Options {
|
|
|
1154
2119
|
}
|
|
1155
2120
|
|
|
1156
2121
|
`;
|
|
1157
|
-
await
|
|
2122
|
+
await settings.writer(output, {
|
|
1158
2123
|
...models,
|
|
1159
2124
|
...inputs,
|
|
1160
2125
|
...outputs
|
|
1161
2126
|
});
|
|
1162
|
-
await
|
|
1163
|
-
"models/index.dart": await getFolderExportsV2(
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
"
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
2127
|
+
await settings.writer(output, {
|
|
2128
|
+
"models/index.dart": await getFolderExportsV2(
|
|
2129
|
+
join(output, "models"),
|
|
2130
|
+
settings.readFolder,
|
|
2131
|
+
{
|
|
2132
|
+
exportSyntax: "export",
|
|
2133
|
+
extensions: "dart"
|
|
2134
|
+
}
|
|
2135
|
+
),
|
|
2136
|
+
"inputs/index.dart": await getFolderExportsV2(
|
|
2137
|
+
join(output, "inputs"),
|
|
2138
|
+
settings.readFolder,
|
|
2139
|
+
{
|
|
2140
|
+
exportSyntax: "export",
|
|
2141
|
+
extensions: "dart"
|
|
2142
|
+
}
|
|
2143
|
+
),
|
|
2144
|
+
"outputs/index.dart": await getFolderExportsV2(
|
|
2145
|
+
join(output, "outputs"),
|
|
2146
|
+
settings.readFolder,
|
|
2147
|
+
{
|
|
2148
|
+
exportSyntax: "export",
|
|
2149
|
+
extensions: "dart"
|
|
2150
|
+
}
|
|
2151
|
+
),
|
|
1175
2152
|
"interceptors.dart": interceptors_default,
|
|
1176
2153
|
"http.dart": dispatcher_default,
|
|
1177
2154
|
"responses.dart": responses_default,
|
|
1178
2155
|
...clazzez
|
|
1179
2156
|
});
|
|
1180
|
-
await
|
|
1181
|
-
"package.dart": `${await getFolderExportsV2(
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
2157
|
+
await settings.writer(output, {
|
|
2158
|
+
"package.dart": `${await getFolderExportsV2(
|
|
2159
|
+
join(output),
|
|
2160
|
+
settings.readFolder,
|
|
2161
|
+
{
|
|
2162
|
+
exportSyntax: "export",
|
|
2163
|
+
extensions: "dart",
|
|
2164
|
+
ignore(dirent) {
|
|
2165
|
+
return !dirent.isFolder && dirent.fileName === "package.dart";
|
|
2166
|
+
}
|
|
1186
2167
|
}
|
|
1187
|
-
|
|
2168
|
+
)}${client}`
|
|
1188
2169
|
});
|
|
1189
|
-
await
|
|
2170
|
+
await settings.writer(settings.output, {
|
|
1190
2171
|
"pubspec.yaml": {
|
|
1191
2172
|
ignoreIfExists: true,
|
|
1192
2173
|
content: yaml.stringify({
|
|
@@ -1211,16 +2192,18 @@ function toInputs(spec, { entry, operation }) {
|
|
|
1211
2192
|
const inputName = pascalcase2(`${operation.operationId} input`);
|
|
1212
2193
|
let contentType = "empty";
|
|
1213
2194
|
let encode = "";
|
|
1214
|
-
if (!
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1217
|
-
const ctSchema = isRef3(requestBody.content[type].schema) ? followRef3(spec, requestBody.content[type].schema.$ref) : requestBody.content[type].schema;
|
|
2195
|
+
if (!isEmpty3(operation.requestBody)) {
|
|
2196
|
+
for (const type in operation.requestBody.content) {
|
|
2197
|
+
const ctSchema = isRef4(operation.requestBody.content[type].schema) ? followRef3(spec, operation.requestBody.content[type].schema.$ref) : operation.requestBody.content[type].schema;
|
|
1218
2198
|
if (!ctSchema) {
|
|
1219
2199
|
console.warn(
|
|
1220
2200
|
`Schema not found for ${type} in ${entry.method} ${entry.path}`
|
|
1221
2201
|
);
|
|
1222
2202
|
continue;
|
|
1223
2203
|
}
|
|
2204
|
+
ctSchema.properties ??= {};
|
|
2205
|
+
ctSchema.required ??= [];
|
|
2206
|
+
patchParameters(spec, ctSchema, operation);
|
|
1224
2207
|
const serializer = new DartSerializer(spec, (name, content) => {
|
|
1225
2208
|
inputs[join(`inputs/${name}.dart`)] = `import 'dart:io';import 'dart:typed_data';import '../models/index.dart'; import './index.dart';
|
|
1226
2209
|
|
|
@@ -1237,6 +2220,20 @@ ${content}`;
|
|
|
1237
2220
|
contentType = mediaType;
|
|
1238
2221
|
}
|
|
1239
2222
|
}
|
|
2223
|
+
} else {
|
|
2224
|
+
const ctSchema = {
|
|
2225
|
+
type: "object"
|
|
2226
|
+
};
|
|
2227
|
+
patchParameters(spec, ctSchema, operation);
|
|
2228
|
+
const serializer = new DartSerializer(spec, (name, content) => {
|
|
2229
|
+
inputs[join(`inputs/${name}.dart`)] = `import 'dart:io';import 'dart:typed_data';import '../models/index.dart'; import './index.dart';
|
|
2230
|
+
|
|
2231
|
+
${content}`;
|
|
2232
|
+
});
|
|
2233
|
+
const serialized = serializer.handle(inputName, ctSchema, true, {
|
|
2234
|
+
alias: isObjectSchema(ctSchema) ? void 0 : inputName
|
|
2235
|
+
});
|
|
2236
|
+
encode = serialized.encode;
|
|
1240
2237
|
}
|
|
1241
2238
|
return { inputs, inputName, contentType, encode };
|
|
1242
2239
|
}
|
|
@@ -1245,7 +2242,7 @@ function toOutput(spec, operation) {
|
|
|
1245
2242
|
operation.responses ??= {};
|
|
1246
2243
|
const outputs = {};
|
|
1247
2244
|
for (const status in operation.responses) {
|
|
1248
|
-
const response =
|
|
2245
|
+
const response = isRef4(operation.responses[status]) ? followRef3(spec, operation.responses[status].$ref) : operation.responses[status];
|
|
1249
2246
|
for (const type in response.content) {
|
|
1250
2247
|
const { schema } = response.content[type];
|
|
1251
2248
|
if (!schema) {
|