@sdk-it/dart 0.21.0 → 0.22.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 +600 -1771
- package/dist/index.js.map +4 -4
- package/dist/lib/dart-emitter.d.ts +9 -9
- package/dist/lib/dart-emitter.d.ts.map +1 -1
- package/dist/lib/generate.d.ts +2 -1
- package/dist/lib/generate.d.ts.map +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,1456 +1,299 @@
|
|
|
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
|
-
|
|
392
1
|
// packages/dart/src/lib/generate.ts
|
|
393
2
|
import { parse as partContentType } from "fast-content-type-parse";
|
|
394
|
-
import { merge as merge2 } from "lodash-es";
|
|
395
|
-
import assert2 from "node:assert";
|
|
396
3
|
import { readdir, writeFile } from "node:fs/promises";
|
|
397
4
|
import { join } from "node:path";
|
|
398
|
-
import { camelcase as
|
|
5
|
+
import { camelcase as camelcase2 } from "stringcase";
|
|
399
6
|
import yaml from "yaml";
|
|
400
7
|
import {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
isRef as isRef4,
|
|
404
|
-
notRef as notRef2,
|
|
8
|
+
isEmpty as isEmpty2,
|
|
9
|
+
isRef as isRef2,
|
|
405
10
|
pascalcase as pascalcase2,
|
|
11
|
+
resolveRef as resolveRef2,
|
|
406
12
|
snakecase as snakecase2
|
|
407
13
|
} from "@sdk-it/core";
|
|
408
14
|
import {
|
|
15
|
+
createWriterProxy,
|
|
409
16
|
getFolderExportsV2,
|
|
410
17
|
writeFiles
|
|
411
18
|
} from "@sdk-it/core/file-system.js";
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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
|
-
}
|
|
842
|
-
|
|
843
|
-
// packages/spec/dist/lib/operation.js
|
|
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
|
-
}
|
|
930
|
-
var defaults = {
|
|
931
|
-
operationId: (operation, path, method) => {
|
|
932
|
-
if (operation.operationId) {
|
|
933
|
-
return camelcase(operation.operationId);
|
|
934
|
-
}
|
|
935
|
-
const metadata = operation["x-oaiMeta"];
|
|
936
|
-
if (metadata && metadata.name) {
|
|
937
|
-
return camelcase(metadata.name);
|
|
938
|
-
}
|
|
939
|
-
return camelcase(
|
|
940
|
-
[method, ...path.replace(/[\\/\\{\\}]/g, " ").split(" ")].filter(Boolean).join(" ").trim()
|
|
941
|
-
);
|
|
942
|
-
},
|
|
943
|
-
tag: (operation, path) => {
|
|
944
|
-
return operation.tags?.[0] ? sanitizeTag(operation.tags?.[0]) : determineGenericTag(path, operation);
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
function resolveResponses(spec, operation) {
|
|
948
|
-
const responses = operation.responses ?? {};
|
|
949
|
-
const resolved = {};
|
|
950
|
-
for (const status in responses) {
|
|
951
|
-
const response = isRef2(responses[status]) ? followRef(spec, responses[status].$ref) : responses[status];
|
|
952
|
-
resolved[status] = response;
|
|
953
|
-
}
|
|
954
|
-
return resolved;
|
|
955
|
-
}
|
|
956
|
-
function forEachOperation(config, callback) {
|
|
957
|
-
const result = [];
|
|
958
|
-
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
959
|
-
const { parameters = [], ...methods } = pathItem;
|
|
960
|
-
for (const [method, operation] of Object.entries(methods)) {
|
|
961
|
-
const metadata = operation["x-oaiMeta"] ?? {};
|
|
962
|
-
const operationTag = operation.tags?.[0];
|
|
963
|
-
result.push(
|
|
964
|
-
callback(
|
|
965
|
-
{
|
|
966
|
-
name: metadata.name,
|
|
967
|
-
method,
|
|
968
|
-
path,
|
|
969
|
-
groupName: operationTag,
|
|
970
|
-
tag: operationTag
|
|
971
|
-
},
|
|
972
|
-
operation
|
|
973
|
-
)
|
|
974
|
-
);
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
return result;
|
|
978
|
-
}
|
|
979
|
-
var reservedKeywords = /* @__PURE__ */ new Set([
|
|
980
|
-
"await",
|
|
981
|
-
// Reserved in async functions
|
|
982
|
-
"break",
|
|
983
|
-
"case",
|
|
984
|
-
"catch",
|
|
985
|
-
"class",
|
|
986
|
-
"const",
|
|
987
|
-
"continue",
|
|
988
|
-
"debugger",
|
|
989
|
-
"default",
|
|
990
|
-
"delete",
|
|
991
|
-
"do",
|
|
992
|
-
"else",
|
|
993
|
-
"enum",
|
|
994
|
-
"export",
|
|
995
|
-
"extends",
|
|
996
|
-
"false",
|
|
997
|
-
"finally",
|
|
998
|
-
"for",
|
|
999
|
-
"function",
|
|
1000
|
-
"if",
|
|
1001
|
-
"implements",
|
|
1002
|
-
// Strict mode
|
|
1003
|
-
"import",
|
|
1004
|
-
"in",
|
|
1005
|
-
"instanceof",
|
|
1006
|
-
"interface",
|
|
1007
|
-
// Strict mode
|
|
1008
|
-
"let",
|
|
1009
|
-
// Strict mode
|
|
1010
|
-
"new",
|
|
1011
|
-
"null",
|
|
1012
|
-
"package",
|
|
1013
|
-
// Strict mode
|
|
1014
|
-
"private",
|
|
1015
|
-
// Strict mode
|
|
1016
|
-
"protected",
|
|
1017
|
-
// Strict mode
|
|
1018
|
-
"public",
|
|
1019
|
-
// Strict mode
|
|
1020
|
-
"return",
|
|
1021
|
-
"static",
|
|
1022
|
-
// Strict mode
|
|
1023
|
-
"super",
|
|
1024
|
-
"switch",
|
|
1025
|
-
"this",
|
|
1026
|
-
"throw",
|
|
1027
|
-
"true",
|
|
1028
|
-
"try",
|
|
1029
|
-
"typeof",
|
|
1030
|
-
"var",
|
|
1031
|
-
"void",
|
|
1032
|
-
"while",
|
|
1033
|
-
"with",
|
|
1034
|
-
"yield",
|
|
1035
|
-
// Strict mode / Generator functions
|
|
1036
|
-
// 'arguments' is not technically a reserved word, but it's a special identifier within functions
|
|
1037
|
-
// and assigning to it or declaring it can cause issues or unexpected behavior.
|
|
1038
|
-
"arguments"
|
|
1039
|
-
]);
|
|
1040
|
-
function sanitizeTag(camelCasedTag) {
|
|
1041
|
-
if (/^\d/.test(camelCasedTag)) {
|
|
1042
|
-
return `_${camelCasedTag}`;
|
|
1043
|
-
}
|
|
1044
|
-
return reservedKeywords.has(camelcase(camelCasedTag)) ? `${camelCasedTag}_` : camelCasedTag;
|
|
1045
|
-
}
|
|
1046
|
-
function determineGenericTag(pathString, operation) {
|
|
1047
|
-
const operationId = operation.operationId || "";
|
|
1048
|
-
const VERSION_REGEX = /^[vV]\d+$/;
|
|
1049
|
-
const commonVerbs = /* @__PURE__ */ new Set([
|
|
1050
|
-
// Verbs to potentially strip from operationId prefix
|
|
1051
|
-
"get",
|
|
1052
|
-
"list",
|
|
1053
|
-
"create",
|
|
1054
|
-
"update",
|
|
1055
|
-
"delete",
|
|
1056
|
-
"post",
|
|
1057
|
-
"put",
|
|
1058
|
-
"patch",
|
|
1059
|
-
"do",
|
|
1060
|
-
"send",
|
|
1061
|
-
"add",
|
|
1062
|
-
"remove",
|
|
1063
|
-
"set",
|
|
1064
|
-
"find",
|
|
1065
|
-
"search",
|
|
1066
|
-
"check",
|
|
1067
|
-
"make"
|
|
1068
|
-
]);
|
|
1069
|
-
const segments = pathString.split("/").filter(Boolean);
|
|
1070
|
-
const potentialCandidates = segments.filter(
|
|
1071
|
-
(segment) => segment && !segment.startsWith("{") && !segment.endsWith("}") && !VERSION_REGEX.test(segment)
|
|
1072
|
-
);
|
|
1073
|
-
for (let i = potentialCandidates.length - 1; i >= 0; i--) {
|
|
1074
|
-
const segment = potentialCandidates[i];
|
|
1075
|
-
if (!segment.startsWith("@")) {
|
|
1076
|
-
return sanitizeTag(camelcase(segment));
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
const canFallbackToPathSegment = potentialCandidates.length > 0;
|
|
1080
|
-
if (operationId) {
|
|
1081
|
-
const lowerOpId = operationId.toLowerCase();
|
|
1082
|
-
const parts = operationId.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").replace(/([a-zA-Z])(\d)/g, "$1_$2").replace(/(\d)([a-zA-Z])/g, "$1_$2").toLowerCase().split(/[_-\s]+/);
|
|
1083
|
-
const validParts = parts.filter(Boolean);
|
|
1084
|
-
if (commonVerbs.has(lowerOpId) && validParts.length === 1 && canFallbackToPathSegment) {
|
|
1085
|
-
} else if (validParts.length > 0) {
|
|
1086
|
-
const firstPart = validParts[0];
|
|
1087
|
-
const isFirstPartVerb = commonVerbs.has(firstPart);
|
|
1088
|
-
if (isFirstPartVerb && validParts.length > 1) {
|
|
1089
|
-
const verbPrefixLength = firstPart.length;
|
|
1090
|
-
let nextPartStartIndex = -1;
|
|
1091
|
-
if (operationId.length > verbPrefixLength) {
|
|
1092
|
-
const charAfterPrefix = operationId[verbPrefixLength];
|
|
1093
|
-
if (charAfterPrefix >= "A" && charAfterPrefix <= "Z") {
|
|
1094
|
-
nextPartStartIndex = verbPrefixLength;
|
|
1095
|
-
} else if (charAfterPrefix >= "0" && charAfterPrefix <= "9") {
|
|
1096
|
-
nextPartStartIndex = verbPrefixLength;
|
|
1097
|
-
} else if (["_", "-"].includes(charAfterPrefix)) {
|
|
1098
|
-
nextPartStartIndex = verbPrefixLength + 1;
|
|
1099
|
-
} else {
|
|
1100
|
-
const match = operationId.substring(verbPrefixLength).match(/[A-Z0-9]/);
|
|
1101
|
-
if (match && match.index !== void 0) {
|
|
1102
|
-
nextPartStartIndex = verbPrefixLength + match.index;
|
|
1103
|
-
}
|
|
1104
|
-
if (nextPartStartIndex === -1 && operationId.length > verbPrefixLength) {
|
|
1105
|
-
nextPartStartIndex = verbPrefixLength;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
if (nextPartStartIndex !== -1 && nextPartStartIndex < operationId.length) {
|
|
1110
|
-
const remainingOriginalSubstring = operationId.substring(nextPartStartIndex);
|
|
1111
|
-
const potentialTag = camelcase(remainingOriginalSubstring);
|
|
1112
|
-
if (potentialTag) {
|
|
1113
|
-
return sanitizeTag(potentialTag);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
const potentialTagJoined = camelcase(validParts.slice(1).join("_"));
|
|
1117
|
-
if (potentialTagJoined) {
|
|
1118
|
-
return sanitizeTag(potentialTagJoined);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
const potentialTagFull = camelcase(operationId);
|
|
1122
|
-
if (potentialTagFull) {
|
|
1123
|
-
const isResultSingleVerb = validParts.length === 1 && isFirstPartVerb;
|
|
1124
|
-
if (!(isResultSingleVerb && canFallbackToPathSegment)) {
|
|
1125
|
-
if (potentialTagFull.length > 0) {
|
|
1126
|
-
return sanitizeTag(potentialTagFull);
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
const firstPartCamel = camelcase(firstPart);
|
|
1131
|
-
if (firstPartCamel) {
|
|
1132
|
-
const isFirstPartCamelVerb = commonVerbs.has(firstPartCamel);
|
|
1133
|
-
if (!isFirstPartCamelVerb || validParts.length === 1 || !canFallbackToPathSegment) {
|
|
1134
|
-
return sanitizeTag(firstPartCamel);
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
if (isFirstPartVerb && validParts.length > 1 && validParts[1] && canFallbackToPathSegment) {
|
|
1138
|
-
const secondPartCamel = camelcase(validParts[1]);
|
|
1139
|
-
if (secondPartCamel) {
|
|
1140
|
-
return sanitizeTag(secondPartCamel);
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
if (potentialCandidates.length > 0) {
|
|
1146
|
-
let firstCandidate = potentialCandidates[0];
|
|
1147
|
-
if (firstCandidate.startsWith("@")) {
|
|
1148
|
-
firstCandidate = firstCandidate.substring(1);
|
|
1149
|
-
}
|
|
1150
|
-
if (firstCandidate) {
|
|
1151
|
-
return sanitizeTag(camelcase(firstCandidate));
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
console.warn(
|
|
1155
|
-
`Could not determine a suitable tag for path: ${pathString}, operationId: ${operationId}. Using 'unknown'.`
|
|
1156
|
-
);
|
|
1157
|
-
return "unknown";
|
|
1158
|
-
}
|
|
1159
|
-
function parseJsonContentType(contentType) {
|
|
1160
|
-
if (!contentType) {
|
|
1161
|
-
return null;
|
|
1162
|
-
}
|
|
1163
|
-
let mainType = contentType.trim();
|
|
1164
|
-
const semicolonIndex = mainType.indexOf(";");
|
|
1165
|
-
if (semicolonIndex !== -1) {
|
|
1166
|
-
mainType = mainType.substring(0, semicolonIndex).trim();
|
|
1167
|
-
}
|
|
1168
|
-
mainType = mainType.toLowerCase();
|
|
1169
|
-
if (mainType.endsWith("/json")) {
|
|
1170
|
-
return mainType.split("/")[1];
|
|
1171
|
-
} else if (mainType.endsWith("+json")) {
|
|
1172
|
-
return mainType.split("+")[1];
|
|
1173
|
-
}
|
|
1174
|
-
return null;
|
|
1175
|
-
}
|
|
1176
|
-
function isStreamingContentType(contentType) {
|
|
1177
|
-
return contentType === "application/octet-stream";
|
|
1178
|
-
}
|
|
1179
|
-
function isSuccessStatusCode(statusCode) {
|
|
1180
|
-
statusCode = Number(statusCode);
|
|
1181
|
-
return statusCode >= 200 && statusCode < 300;
|
|
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";
|
|
19
|
+
import {
|
|
20
|
+
augmentSpec,
|
|
21
|
+
cleanFiles,
|
|
22
|
+
forEachOperation,
|
|
23
|
+
isSseContentType,
|
|
24
|
+
isStreamingContentType,
|
|
25
|
+
isSuccessStatusCode,
|
|
26
|
+
parseJsonContentType,
|
|
27
|
+
readWriteMetadata
|
|
28
|
+
} from "@sdk-it/spec";
|
|
1245
29
|
|
|
1246
30
|
// packages/dart/src/lib/dart-emitter.ts
|
|
1247
31
|
import { merge } from "lodash-es";
|
|
1248
32
|
import assert from "node:assert";
|
|
1249
|
-
import { camelcase
|
|
33
|
+
import { camelcase, snakecase } from "stringcase";
|
|
1250
34
|
import {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
35
|
+
followRef,
|
|
36
|
+
isEmpty,
|
|
37
|
+
isRef,
|
|
38
|
+
joinSkipDigits,
|
|
1255
39
|
notRef,
|
|
1256
40
|
parseRef,
|
|
1257
|
-
pascalcase
|
|
41
|
+
pascalcase,
|
|
42
|
+
resolveRef
|
|
1258
43
|
} from "@sdk-it/core";
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
44
|
+
import {
|
|
45
|
+
coerceTypes,
|
|
46
|
+
formatName,
|
|
47
|
+
getRefUsage,
|
|
48
|
+
isPrimitiveSchema,
|
|
49
|
+
sanitizeTag
|
|
50
|
+
} from "@sdk-it/spec";
|
|
51
|
+
function coearceObject(schema) {
|
|
52
|
+
schema = structuredClone(schema);
|
|
53
|
+
if (schema["x-properties"]) {
|
|
54
|
+
schema.properties = {
|
|
55
|
+
...schema.properties ?? {},
|
|
56
|
+
...schema["x-properties"] ?? {}
|
|
57
|
+
};
|
|
1269
58
|
}
|
|
1270
|
-
if (
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
let nameToFormat = it;
|
|
1280
|
-
if (nameToFormat.startsWith("[")) {
|
|
1281
|
-
nameToFormat = nameToFormat.slice(1);
|
|
1282
|
-
}
|
|
1283
|
-
if (nameToFormat.endsWith("]")) {
|
|
1284
|
-
nameToFormat = nameToFormat.slice(0, -1);
|
|
1285
|
-
}
|
|
1286
|
-
return snakecase(nameToFormat);
|
|
59
|
+
if (schema["x-required"]) {
|
|
60
|
+
schema.required = Array.from(
|
|
61
|
+
/* @__PURE__ */ new Set([
|
|
62
|
+
...Array.isArray(schema.required) ? schema.required : [],
|
|
63
|
+
...schema["x-required"] || []
|
|
64
|
+
])
|
|
65
|
+
);
|
|
1287
66
|
}
|
|
1288
|
-
return
|
|
1289
|
-
}
|
|
67
|
+
return schema;
|
|
68
|
+
}
|
|
1290
69
|
var DartSerializer = class {
|
|
1291
70
|
#spec;
|
|
1292
|
-
#
|
|
1293
|
-
|
|
71
|
+
#emitHandler;
|
|
72
|
+
#emitHistory = /* @__PURE__ */ new Set();
|
|
73
|
+
#emit(name, content, schema) {
|
|
74
|
+
if (this.#emitHistory.has(content)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.#emitHistory.add(content);
|
|
78
|
+
this.#emitHandler?.(name, content, schema);
|
|
79
|
+
}
|
|
80
|
+
constructor(spec) {
|
|
1294
81
|
this.#spec = spec;
|
|
1295
|
-
this.#emit = emit;
|
|
1296
82
|
}
|
|
1297
|
-
|
|
1298
|
-
this.#
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
const { model } = parseRef(schema.$ref);
|
|
1304
|
-
return model === schemaName;
|
|
1305
|
-
}
|
|
1306
|
-
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
1307
|
-
return schema.oneOf.some(
|
|
1308
|
-
(subSchema) => checkSchema(subSchema)
|
|
1309
|
-
);
|
|
1310
|
-
}
|
|
1311
|
-
if (schema.type === "array" && schema.items && notRef(schema.items) && schema.items.oneOf) {
|
|
1312
|
-
return checkSchema(schema.items);
|
|
1313
|
-
}
|
|
1314
|
-
return false;
|
|
1315
|
-
};
|
|
1316
|
-
for (const [key, value] of Object.entries(this.#spec.components.schemas)) {
|
|
1317
|
-
if (checkSchema(value)) {
|
|
1318
|
-
list.push(key);
|
|
1319
|
-
}
|
|
83
|
+
onEmit(emit) {
|
|
84
|
+
this.#emitHandler = emit;
|
|
85
|
+
}
|
|
86
|
+
#formatKeyName(name) {
|
|
87
|
+
if (name.startsWith("$")) {
|
|
88
|
+
return `\\${name}`;
|
|
1320
89
|
}
|
|
1321
|
-
return
|
|
90
|
+
return name;
|
|
1322
91
|
}
|
|
1323
92
|
#object(className, schema, context) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
use: "Map<String, dynamic>",
|
|
1329
|
-
encode: "input",
|
|
1330
|
-
toJson: `this.${camelcase2(context.name)}`,
|
|
1331
|
-
fromJson: `json['${camelcase2(context.name)}']`,
|
|
1332
|
-
matches: `json['${camelcase2(context.name)}'] is Map<String, dynamic>`
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
if (isEmpty2(schema.properties)) {
|
|
1336
|
-
if (context.noEmit !== true) {
|
|
1337
|
-
this.#emit(
|
|
93
|
+
const { properties = {}, required = [] } = coearceObject(schema);
|
|
94
|
+
if (schema.additionalProperties || isEmpty(properties)) {
|
|
95
|
+
if (context.requestize) {
|
|
96
|
+
return this.#object(
|
|
1338
97
|
className,
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
}`
|
|
98
|
+
{
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
$body: { "x-special": true }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
context
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (context.noEmit !== true && !context.propName) {
|
|
108
|
+
this.#emit(
|
|
109
|
+
pascalcase(formatName(className)),
|
|
110
|
+
`typedef ${pascalcase(className)} = Map<String, dynamic>;`,
|
|
111
|
+
schema
|
|
1354
112
|
);
|
|
1355
113
|
}
|
|
1356
114
|
return {
|
|
1357
115
|
content: "",
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
fromJson:
|
|
1362
|
-
matches: `${
|
|
116
|
+
use: `Map<String, dynamic>`,
|
|
117
|
+
encode: "input",
|
|
118
|
+
encodeV2: "",
|
|
119
|
+
fromJson: context.parsable,
|
|
120
|
+
matches: `${context.parsable} is Map<String, dynamic>`
|
|
1363
121
|
};
|
|
1364
122
|
}
|
|
123
|
+
let requestContent = "";
|
|
1365
124
|
const props = [];
|
|
1366
125
|
const toJsonProperties = [];
|
|
1367
126
|
const constructorParams = [];
|
|
1368
127
|
const fromJsonParams = [];
|
|
1369
128
|
const matches = [];
|
|
1370
|
-
|
|
129
|
+
const headers = [];
|
|
130
|
+
const params = [];
|
|
131
|
+
const queryParams = [];
|
|
132
|
+
const bodyParams = [];
|
|
133
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
1371
134
|
const propName = key.replace("[]", "");
|
|
1372
|
-
const
|
|
1373
|
-
const
|
|
135
|
+
const safePropName = camelcase(formatName(propName));
|
|
136
|
+
const requiredProp = required.includes(key);
|
|
137
|
+
const jsonKey = this.#formatKeyName(propName);
|
|
138
|
+
const serializedType = this.handle(className, propSchema, requiredProp, {
|
|
1374
139
|
name: propName,
|
|
1375
|
-
|
|
1376
|
-
|
|
140
|
+
safeName: safePropName,
|
|
141
|
+
required: requiredProp,
|
|
142
|
+
propName: isRef(propSchema) ? pascalcase(propName) : joinSkipDigits([className, propName], "_"),
|
|
143
|
+
parsable: `json['${jsonKey}']`
|
|
1377
144
|
});
|
|
1378
|
-
const nullable2 =
|
|
1379
|
-
const nullableSuffix = nullable2 ? "?" : "";
|
|
145
|
+
const nullable2 = serializedType.nullable || !requiredProp;
|
|
146
|
+
const nullableSuffix = serializedType.use === "dynamic" ? "" : nullable2 ? "?" : "";
|
|
147
|
+
const withValue = serializedType.literal !== void 0 ? ` = ${serializedType.literal}` : "";
|
|
1380
148
|
props.push(
|
|
1381
|
-
`final ${
|
|
149
|
+
`final ${serializedType.use}${nullableSuffix} ${safePropName} ${withValue};`
|
|
1382
150
|
);
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
constructorParams.push(
|
|
1386
|
-
`${required ? "required " : ""}this.${camelcase2(propName)},`
|
|
151
|
+
toJsonProperties.push(
|
|
152
|
+
`'${jsonKey}': ${safePropName}${serializedType.encodeV2}`
|
|
1387
153
|
);
|
|
1388
|
-
if (
|
|
154
|
+
if (!withValue) {
|
|
155
|
+
fromJsonParams.push(`${safePropName}: ${serializedType.fromJson}`);
|
|
156
|
+
constructorParams.push(
|
|
157
|
+
`${requiredProp ? "required " : ""}this.${safePropName},`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
if (requiredProp) {
|
|
1389
161
|
matches.push(`(
|
|
1390
|
-
json.containsKey('${
|
|
1391
|
-
? ${nullable2 ? `json['${
|
|
162
|
+
json.containsKey('${jsonKey}')
|
|
163
|
+
? ${nullable2 ? `json['${jsonKey}'] == null` : `json['${jsonKey}'] != null`} ${serializedType.matches ? `&& ${serializedType.matches}` : ""}
|
|
1392
164
|
: false)`);
|
|
1393
165
|
} else {
|
|
1394
166
|
matches.push(`(
|
|
1395
|
-
json.containsKey('${
|
|
1396
|
-
? ${nullable2 ? `json['${
|
|
167
|
+
json.containsKey('${jsonKey}')
|
|
168
|
+
? ${nullable2 ? `json['${jsonKey}'] == null` : `json['${jsonKey}'] != null`} ${serializedType.matches ? `|| ${serializedType.matches}` : ""}
|
|
1397
169
|
: true)`);
|
|
1398
170
|
}
|
|
171
|
+
const { "x-in": source, "x-special": special } = propSchema;
|
|
172
|
+
if (source) {
|
|
173
|
+
switch (source) {
|
|
174
|
+
case "header":
|
|
175
|
+
headers.push(`'${jsonKey}': ${safePropName}`);
|
|
176
|
+
break;
|
|
177
|
+
case "path":
|
|
178
|
+
params.push(`'${jsonKey}': ${safePropName}`);
|
|
179
|
+
break;
|
|
180
|
+
case "query":
|
|
181
|
+
queryParams.push(`'${jsonKey}': ${safePropName}`);
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
bodyParams.push(`'${jsonKey}': ${safePropName}`);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
if (special) {
|
|
188
|
+
bodyParams.push(`$body${serializedType.encodeV2}`);
|
|
189
|
+
} else {
|
|
190
|
+
bodyParams.push(
|
|
191
|
+
`'${jsonKey}': ${safePropName}${serializedType.encodeV2}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
1399
195
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
196
|
+
if (context.requestize) {
|
|
197
|
+
const body = bodyParams.length === 1 && bodyParams[0].startsWith("$body") ? bodyParams[0] : `${bodyParams.length ? `{${bodyParams.join(", ")}}` : "{}"}`;
|
|
198
|
+
requestContent = `
|
|
199
|
+
RequestInput toRequest() =>
|
|
200
|
+
RequestInput(
|
|
201
|
+
headers: ${headers.length ? `{${headers.join(", ")}}` : "{}"},
|
|
202
|
+
query: ${queryParams.length ? `{${queryParams.join(", ")}}` : "{}"},
|
|
203
|
+
params: ${params.length ? `{${params.join(", ")}}` : "{}"},
|
|
204
|
+
body: ${body}
|
|
205
|
+
);`;
|
|
206
|
+
}
|
|
207
|
+
const constructorP = constructorParams.length ? `{${constructorParams.join("\n")}}` : "";
|
|
208
|
+
const fixedClassName = pascalcase(sanitizeTag(className));
|
|
209
|
+
const content = `class ${fixedClassName} {
|
|
1402
210
|
${props.join("\n")}
|
|
1403
|
-
${
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
return ${className}(
|
|
211
|
+
const ${fixedClassName}(${constructorP}): super();
|
|
212
|
+
factory ${fixedClassName}.fromJson(Map<String, dynamic> json) {
|
|
213
|
+
return ${fixedClassName}(
|
|
1407
214
|
${fromJsonParams.join(",\n")});
|
|
1408
215
|
}
|
|
1409
216
|
Map<String, dynamic> toJson() => {
|
|
1410
217
|
${toJsonProperties.join(",\n")}
|
|
1411
218
|
};
|
|
1412
|
-
static bool matches(Map<String, dynamic> json) {
|
|
1413
|
-
|
|
1414
|
-
}
|
|
219
|
+
static bool matches(Map<String, dynamic> json) {return ${matches.join(" && ")};}
|
|
220
|
+
|
|
221
|
+
${requestContent}
|
|
222
|
+
|
|
1415
223
|
}`;
|
|
1416
|
-
if (context.noEmit !== true) {
|
|
1417
|
-
this.#emit(
|
|
224
|
+
if (context.noEmit !== true && !context.propName) {
|
|
225
|
+
this.#emit(fixedClassName, content, schema);
|
|
1418
226
|
}
|
|
1419
227
|
const nullable = !context.required || context.nullable === true;
|
|
228
|
+
const generatedClassName = context.forJson || className;
|
|
1420
229
|
return {
|
|
1421
|
-
use:
|
|
230
|
+
use: fixedClassName,
|
|
1422
231
|
content,
|
|
1423
232
|
encode: "input.toJson()",
|
|
1424
|
-
|
|
1425
|
-
fromJson:
|
|
1426
|
-
matches: `${
|
|
233
|
+
encodeV2: `${context.required ? "" : "?"}.toJson()`,
|
|
234
|
+
fromJson: `${generatedClassName}.fromJson(${context.parsable})`,
|
|
235
|
+
matches: `${generatedClassName}.matches(${context.parsable})`
|
|
1427
236
|
};
|
|
1428
237
|
}
|
|
1429
|
-
#
|
|
1430
|
-
|
|
238
|
+
#oneOfObject(className, varientName, schemaOrRef, context) {
|
|
239
|
+
const schema = resolveRef(this.#spec, schemaOrRef);
|
|
240
|
+
const entries = Object.entries(schema.properties || {});
|
|
241
|
+
if (entries.length === 1) {
|
|
242
|
+
const [key, prop] = entries[0];
|
|
243
|
+
const serializedType2 = this.handle(
|
|
244
|
+
pascalcase(`${className} ${varientName}`),
|
|
245
|
+
prop,
|
|
246
|
+
true,
|
|
247
|
+
{
|
|
248
|
+
...context,
|
|
249
|
+
propName: joinSkipDigits([varientName, key], "_"),
|
|
250
|
+
safeName: varientName,
|
|
251
|
+
parsable: `json['${varientName}']`
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
return {
|
|
255
|
+
typeStr: `${serializedType2.use}${serializedType2.nullable ? "?" : ""} ${key}`,
|
|
256
|
+
returnValue: `_Value({'${key}': ${key}${serializedType2.encodeV2}});`,
|
|
257
|
+
fromJson: serializedType2.fromJson
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const serializedType = this.handle(className, schemaOrRef, true, {
|
|
261
|
+
...context,
|
|
262
|
+
propName: joinSkipDigits([className, varientName], "_"),
|
|
263
|
+
safeName: varientName,
|
|
264
|
+
parsable: `json['${varientName}']`
|
|
265
|
+
});
|
|
266
|
+
return {
|
|
267
|
+
typeStr: `${serializedType.use} value`,
|
|
268
|
+
returnValue: `_Value(value.toJson());`,
|
|
269
|
+
fromJson: serializedType.fromJson
|
|
270
|
+
};
|
|
1431
271
|
}
|
|
1432
272
|
#array(className, schema, required = false, context) {
|
|
1433
273
|
if (!schema.items) {
|
|
1434
274
|
return {
|
|
1435
275
|
content: "",
|
|
1436
276
|
use: "List<dynamic>",
|
|
1437
|
-
|
|
1438
|
-
fromJson: `List<dynamic>.from(${context.
|
|
277
|
+
encodeV2: "",
|
|
278
|
+
fromJson: `List<dynamic>.from(${context.parsable})`,
|
|
1439
279
|
matches: ""
|
|
1440
280
|
};
|
|
1441
281
|
}
|
|
1442
|
-
const itemsType = this.handle(className, schema.items, true,
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
.
|
|
1448
|
-
|
|
1449
|
-
|
|
282
|
+
const itemsType = this.handle(className, schema.items, true, {
|
|
283
|
+
...context,
|
|
284
|
+
parsable: "it"
|
|
285
|
+
});
|
|
286
|
+
const fromJson = required ? context.name ? `(${context.parsable} as List)
|
|
287
|
+
.map((it) => ${itemsType.simple ? `it as ${itemsType.use}` : `${itemsType.fromJson}`})
|
|
288
|
+
.toList()` : `(json as List)
|
|
289
|
+
.map((it) => ${itemsType.simple ? `it as ${itemsType.use}` : `${itemsType.fromJson}`})
|
|
290
|
+
.toList()` : context.name ? `${context.parsable} != null
|
|
291
|
+
? (${context.parsable} as List)
|
|
292
|
+
.map((it) => ${itemsType.simple ? `it as ${itemsType.use}` : `${itemsType.fromJson}`})
|
|
1450
293
|
.toList()
|
|
1451
294
|
: null` : `json != null
|
|
1452
|
-
? (json as List
|
|
1453
|
-
.map((it) => ${itemsType.simple ?
|
|
295
|
+
? (json as List)
|
|
296
|
+
.map((it) => ${itemsType.simple ? `it as ${itemsType.use}` : `${itemsType.fromJson}`})
|
|
1454
297
|
.toList()
|
|
1455
298
|
: null`;
|
|
1456
299
|
return {
|
|
@@ -1458,8 +301,9 @@ return ${matches.join(" && ")};
|
|
|
1458
301
|
content: "",
|
|
1459
302
|
use: `List<${itemsType.use}>`,
|
|
1460
303
|
fromJson,
|
|
1461
|
-
|
|
1462
|
-
|
|
304
|
+
simple: true,
|
|
305
|
+
encodeV2: `${itemsType.simple ? "" : `${context.required ? "" : "?"}.map((it) => ${itemsType.simple ? "it" : `it.toJson()`}).toList()`}`,
|
|
306
|
+
matches: context.parsable ? `(${context.parsable} as List).every((it) => ${itemsType.matches})` : `${context.parsable} is List && ${context.parsable}.every((it) => ${itemsType.matches})`
|
|
1463
307
|
};
|
|
1464
308
|
}
|
|
1465
309
|
/**
|
|
@@ -1471,14 +315,15 @@ return ${matches.join(" && ")};
|
|
|
1471
315
|
return this.#string(schema, context);
|
|
1472
316
|
case "number":
|
|
1473
317
|
case "integer":
|
|
1474
|
-
return this
|
|
318
|
+
return this.#number(schema, context);
|
|
1475
319
|
case "boolean":
|
|
1476
320
|
return {
|
|
1477
321
|
content: "",
|
|
1478
322
|
use: "bool",
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
323
|
+
encodeV2: "",
|
|
324
|
+
simple: true,
|
|
325
|
+
fromJson: context.parsable,
|
|
326
|
+
matches: `${context.parsable} is bool`
|
|
1482
327
|
};
|
|
1483
328
|
case "object":
|
|
1484
329
|
return this.#object(className, schema, context);
|
|
@@ -1487,38 +332,51 @@ return ${matches.join(" && ")};
|
|
|
1487
332
|
case "null":
|
|
1488
333
|
return {
|
|
1489
334
|
content: "",
|
|
335
|
+
encodeV2: "",
|
|
336
|
+
simple: true,
|
|
1490
337
|
use: "Null",
|
|
1491
|
-
|
|
1492
|
-
fromJson: `json['${context.name}']`
|
|
338
|
+
fromJson: context.parsable
|
|
1493
339
|
};
|
|
1494
340
|
default:
|
|
1495
341
|
return {
|
|
1496
342
|
content: "",
|
|
1497
343
|
use: "dynamic",
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
fromJson:
|
|
344
|
+
encodeV2: "",
|
|
345
|
+
simple: true,
|
|
346
|
+
fromJson: context.parsable,
|
|
347
|
+
matches: "",
|
|
348
|
+
nullable: false
|
|
1501
349
|
};
|
|
1502
350
|
}
|
|
1503
351
|
}
|
|
1504
352
|
#ref(className, $ref, required, context) {
|
|
1505
|
-
const schemaName =
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
required,
|
|
1510
|
-
{
|
|
353
|
+
const schemaName = pascalcase(sanitizeTag(parseRef($ref).model));
|
|
354
|
+
const schema = followRef(this.#spec, $ref);
|
|
355
|
+
if (isPrimitiveSchema(schema)) {
|
|
356
|
+
return this.handle(schemaName, schema, required, {
|
|
1511
357
|
...context,
|
|
1512
358
|
propName: schemaName,
|
|
1513
|
-
noEmit:
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
359
|
+
noEmit: true,
|
|
360
|
+
// default to json in case this method is root level
|
|
361
|
+
parsable: context.parsable || "json"
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
const generatedClassName = context.forJson || schemaName;
|
|
365
|
+
const isDynamicObject = schema.type === "object" ? !!schema.additionalProperties || isEmpty(schema.properties) : schema.anyOf ? false : !schema.oneOf;
|
|
366
|
+
return {
|
|
367
|
+
use: pascalcase(schemaName),
|
|
368
|
+
content: "",
|
|
369
|
+
encode: "input.toJson()",
|
|
370
|
+
encodeV2: isDynamicObject ? "" : `${context.required ? "" : "?"}.toJson()`,
|
|
371
|
+
fromJson: isDynamicObject ? `${generatedClassName}.from(json)` : `${generatedClassName}.fromJson(${context.parsable || "json"})`,
|
|
372
|
+
matches: isDynamicObject ? `${context.parsable} is ${generatedClassName}` : `${generatedClassName}.matches(${context.parsable})`,
|
|
373
|
+
simple: isDynamicObject
|
|
374
|
+
};
|
|
1517
375
|
}
|
|
1518
376
|
// fixme: this method should no longer be needed because the logic in it is being preprocessed before emitting begins
|
|
1519
377
|
#allOf(className, schemas, context) {
|
|
1520
378
|
const name = pascalcase(context.propName || className);
|
|
1521
|
-
const refs = schemas.filter(
|
|
379
|
+
const refs = schemas.filter(isRef);
|
|
1522
380
|
const nonRefs = schemas.filter(notRef);
|
|
1523
381
|
if (nonRefs.some((it) => it.type && it.type !== "object")) {
|
|
1524
382
|
assert(false, `allOf ${name} must be an object`);
|
|
@@ -1526,174 +384,169 @@ return ${matches.join(" && ")};
|
|
|
1526
384
|
const objectSchema = merge(
|
|
1527
385
|
{},
|
|
1528
386
|
...nonRefs,
|
|
1529
|
-
...refs.map((ref) =>
|
|
387
|
+
...refs.map((ref) => followRef(this.#spec, ref.$ref))
|
|
1530
388
|
);
|
|
1531
389
|
delete objectSchema.allOf;
|
|
1532
390
|
return this.handle(name, objectSchema, true, context);
|
|
1533
391
|
}
|
|
1534
|
-
#anyOf(className, schemas, context) {
|
|
1535
|
-
if (schemas.length === 0) {
|
|
1536
|
-
return {
|
|
1537
|
-
content: "",
|
|
1538
|
-
nullable: false,
|
|
1539
|
-
use: "dynamic",
|
|
1540
|
-
toJson: `${camelcase2(context.name)}`,
|
|
1541
|
-
fromJson: `json['${context.name}']`
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
const nullSchemaIndex = schemas.findIndex((schema) => {
|
|
1545
|
-
if (isRef3(schema)) {
|
|
1546
|
-
const refSchema = followRef2(this.#spec, schema.$ref);
|
|
1547
|
-
return refSchema.type === "null";
|
|
1548
|
-
}
|
|
1549
|
-
return schema.type === "null";
|
|
1550
|
-
});
|
|
1551
|
-
const anyOfSchemas = schemas.slice(0);
|
|
1552
|
-
if (nullSchemaIndex >= 0) {
|
|
1553
|
-
anyOfSchemas.splice(nullSchemaIndex, 1);
|
|
1554
|
-
}
|
|
1555
|
-
return this.handle(className, anyOfSchemas[0], true, {
|
|
1556
|
-
...context,
|
|
1557
|
-
nullable: nullSchemaIndex >= 0
|
|
1558
|
-
});
|
|
1559
|
-
}
|
|
1560
392
|
#mixinise(name, context) {
|
|
1561
|
-
const mixins = this.#
|
|
393
|
+
const mixins = getRefUsage(this.#spec, name);
|
|
1562
394
|
if (context.mixin) {
|
|
1563
395
|
mixins.unshift(context.mixin);
|
|
1564
396
|
}
|
|
1565
|
-
const withMixins = mixins.length > 1 ? `
|
|
397
|
+
const withMixins = mixins.length > 1 ? ` implements ${mixins.join(", ")}` : mixins.length === 1 ? `extends ${mixins[0]}` : "";
|
|
1566
398
|
return {
|
|
1567
399
|
withMixins,
|
|
1568
400
|
mixins
|
|
1569
401
|
};
|
|
1570
402
|
}
|
|
1571
|
-
#
|
|
1572
|
-
|
|
403
|
+
#buildClass(options) {
|
|
404
|
+
return [
|
|
405
|
+
options.abstract ? "abstract" : "",
|
|
406
|
+
options.mixins?.length ? "" : "mixin",
|
|
407
|
+
`class ${options.name} ${options.withMixins} ${options.implements?.length ? `implements ${options.implements.join(", ")}` : ""}`,
|
|
408
|
+
"{",
|
|
409
|
+
options.content.join("\n"),
|
|
410
|
+
"}"
|
|
411
|
+
].filter(Boolean).join("\n");
|
|
412
|
+
}
|
|
413
|
+
#oneOf(className, schema, context) {
|
|
414
|
+
const varients = schema["x-varients"];
|
|
415
|
+
const schemas = schema.oneOf || schema.anyOf || [];
|
|
416
|
+
const name = pascalcase(sanitizeTag(context.propName || className));
|
|
1573
417
|
if (schemas.length === 0) {
|
|
1574
418
|
return {
|
|
1575
419
|
content: "",
|
|
1576
420
|
nullable: false,
|
|
1577
421
|
use: "dynamic",
|
|
1578
|
-
|
|
1579
|
-
fromJson:
|
|
422
|
+
encodeV2: "",
|
|
423
|
+
fromJson: context.parsable
|
|
1580
424
|
};
|
|
1581
425
|
}
|
|
1582
426
|
const content = [];
|
|
1583
427
|
const patterns = [];
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
${name}
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
}}`);
|
|
1619
|
-
patterns.push({
|
|
1620
|
-
pattern: `case List(): return ${name}List(List<${itemsType.use}>.from(json));`,
|
|
1621
|
-
name: `${name}List`
|
|
1622
|
-
});
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
if (objects.length) {
|
|
1626
|
-
const candidates = {};
|
|
1627
|
-
for (const schema of objects) {
|
|
1628
|
-
if (schema.additionalProperties === true) {
|
|
428
|
+
content.push(`class _Value implements ${name} {
|
|
429
|
+
final dynamic value;
|
|
430
|
+
const _Value(this.value);
|
|
431
|
+
@override
|
|
432
|
+
toJson() => value;
|
|
433
|
+
}`);
|
|
434
|
+
for (const { name: varientName, ...varient } of varients) {
|
|
435
|
+
switch (varientName) {
|
|
436
|
+
case "empty":
|
|
437
|
+
patterns.push({
|
|
438
|
+
name: `static ${name} ${formatName(varientName)}() => _Value("");`,
|
|
439
|
+
pattern: `case '': return ${name}.${formatName(varientName)}();`
|
|
440
|
+
});
|
|
441
|
+
continue;
|
|
442
|
+
case "uri":
|
|
443
|
+
patterns.push({
|
|
444
|
+
name: `static ${name} ${formatName(varientName)}(Uri value) => _Value(value);`,
|
|
445
|
+
pattern: `case String: return ${name}.${formatName(varientName)}(Uri.parse(json));`
|
|
446
|
+
});
|
|
447
|
+
continue;
|
|
448
|
+
case "number":
|
|
449
|
+
patterns.push({
|
|
450
|
+
name: `static ${name} ${formatName(varientName)}(num value) => _Value(value);`,
|
|
451
|
+
pattern: `case num: return ${name}.${formatName(varientName)}(json);`
|
|
452
|
+
});
|
|
453
|
+
continue;
|
|
454
|
+
case "object": {
|
|
455
|
+
const result = this.handle(className, schemas[varient.position]);
|
|
456
|
+
patterns.push({
|
|
457
|
+
name: `static ${name} ${formatName(varientName)}(${result.use} value) => _Value(value);`,
|
|
458
|
+
pattern: `case Map<String, dynamic> map: return ${name}.${formatName(varientName)}(${pascalcase(
|
|
459
|
+
`${name} ${formatName(varientName)}`
|
|
460
|
+
)}.fromJson(map));`
|
|
461
|
+
});
|
|
1629
462
|
continue;
|
|
1630
|
-
}
|
|
1631
|
-
assert(
|
|
1632
|
-
schema.properties,
|
|
1633
|
-
`Schema ${name} has no properties which are required in oneOf in order to determine the discriminator.`
|
|
1634
|
-
);
|
|
1635
|
-
for (const [propName, propSchema] of Object.entries(
|
|
1636
|
-
schema.properties
|
|
1637
|
-
)) {
|
|
1638
|
-
if (notRef(propSchema) && propSchema.enum && // fixme: the enum can have more than one value as long as it is not duplicated else where on the other schemas
|
|
1639
|
-
propSchema.enum.length === 1) {
|
|
1640
|
-
candidates[propName] ??= /* @__PURE__ */ new Set();
|
|
1641
|
-
candidates[propName].add(String(propSchema.enum[0]));
|
|
1642
|
-
}
|
|
1643
463
|
}
|
|
1644
464
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
discriminatorProp = name2;
|
|
465
|
+
switch (varient.type) {
|
|
466
|
+
case "string":
|
|
467
|
+
patterns.push({
|
|
468
|
+
name: `static ${name} ${formatName(varientName)}(String value) => _Value(value);`,
|
|
469
|
+
pattern: `case String: return ${name}.${formatName(varientName)}(json);`
|
|
470
|
+
});
|
|
1652
471
|
break;
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
472
|
+
case "object": {
|
|
473
|
+
const { typeStr, returnValue, fromJson } = this.#oneOfObject(
|
|
474
|
+
name,
|
|
475
|
+
formatName(varientName),
|
|
476
|
+
schemas[varient.position],
|
|
477
|
+
context
|
|
478
|
+
);
|
|
479
|
+
const staticStr = varient.static ? `&& json['${varient.source}'] == '${formatName(varientName)}'` : "";
|
|
480
|
+
const caseStr = `case Map<String, dynamic> json when json.containsKey('${varient.source}') ${staticStr}`;
|
|
481
|
+
const returnStr = `return ${name}.${formatName(varientName)}(${fromJson})`;
|
|
1659
482
|
patterns.push({
|
|
1660
|
-
|
|
1661
|
-
|
|
483
|
+
name: `static ${name} ${formatName(varientName)}(${typeStr}) => ${returnValue}`,
|
|
484
|
+
pattern: `${caseStr}: ${returnStr};`
|
|
1662
485
|
});
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
case "array": {
|
|
489
|
+
const serializedType = this.handle(
|
|
490
|
+
className,
|
|
491
|
+
schemas[varient.position],
|
|
492
|
+
true,
|
|
493
|
+
{
|
|
494
|
+
...context,
|
|
495
|
+
noEmit: true,
|
|
496
|
+
parsable: "json"
|
|
497
|
+
}
|
|
498
|
+
);
|
|
499
|
+
patterns.push({
|
|
500
|
+
name: `static ${name} ${formatName(varientName)}(${serializedType.use} value) => _Value(value);`,
|
|
501
|
+
pattern: `case ${serializedType.use} json: return ${name}.${formatName(varientName)}(${serializedType.fromJson});`
|
|
1667
502
|
});
|
|
1668
|
-
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
default: {
|
|
1669
506
|
}
|
|
1670
507
|
}
|
|
1671
508
|
}
|
|
1672
509
|
const { mixins, withMixins } = this.#mixinise(name, context);
|
|
1673
|
-
content.
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
510
|
+
content.push(
|
|
511
|
+
this.#buildClass({
|
|
512
|
+
name,
|
|
513
|
+
abstract: true,
|
|
514
|
+
mixins,
|
|
515
|
+
withMixins,
|
|
516
|
+
content: [
|
|
517
|
+
// 'dynamic get value;',
|
|
518
|
+
"dynamic toJson();",
|
|
519
|
+
...patterns.map((it) => it.name),
|
|
520
|
+
`${name}();`,
|
|
521
|
+
`factory ${name}.fromJson(dynamic json)`,
|
|
522
|
+
`{`,
|
|
523
|
+
`switch (json) {`,
|
|
524
|
+
...patterns.map((it) => it.pattern),
|
|
525
|
+
`default: throw ArgumentError("Invalid type: \${json}");`,
|
|
526
|
+
`}`,
|
|
527
|
+
`}`,
|
|
528
|
+
`static bool matches(dynamic value) {
|
|
529
|
+
try {
|
|
530
|
+
${name}.fromJson(value);
|
|
531
|
+
return true;
|
|
532
|
+
} catch (error) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
}`
|
|
536
|
+
]
|
|
537
|
+
})
|
|
538
|
+
);
|
|
539
|
+
if (context.noEmit !== true) {
|
|
540
|
+
this.#emit(name, content.join("\n"), {
|
|
541
|
+
oneOf: schemas
|
|
542
|
+
});
|
|
543
|
+
}
|
|
1691
544
|
return {
|
|
1692
545
|
content: content.join("\n"),
|
|
1693
546
|
use: name,
|
|
1694
|
-
|
|
1695
|
-
fromJson: `${name}.fromJson(
|
|
1696
|
-
matches: `${name}.matches(
|
|
547
|
+
encodeV2: `${context.required ? "" : "?"}.toJson()`,
|
|
548
|
+
fromJson: `${name}.fromJson(${context.parsable})`,
|
|
549
|
+
matches: `${name}.matches(${context.parsable})`
|
|
1697
550
|
};
|
|
1698
551
|
}
|
|
1699
552
|
#simple(type) {
|
|
@@ -1706,6 +559,12 @@ return ${matches.join(" && ")};
|
|
|
1706
559
|
return "int";
|
|
1707
560
|
case "boolean":
|
|
1708
561
|
return "bool";
|
|
562
|
+
case "object":
|
|
563
|
+
return "Map<String, dynamic>";
|
|
564
|
+
case "array":
|
|
565
|
+
return "List<dynamic>";
|
|
566
|
+
case "null":
|
|
567
|
+
return "Null";
|
|
1709
568
|
default:
|
|
1710
569
|
return "dynamic";
|
|
1711
570
|
}
|
|
@@ -1713,17 +572,17 @@ return ${matches.join(" && ")};
|
|
|
1713
572
|
#enum(className, schema, context) {
|
|
1714
573
|
const name = context.propName || className;
|
|
1715
574
|
const values = schema.enum;
|
|
1716
|
-
const valType = this.#simple(schema
|
|
1717
|
-
const { mixins, withMixins } = this.#mixinise(
|
|
575
|
+
const valType = this.#simple(coerceTypes(schema)[0]);
|
|
576
|
+
const { mixins, withMixins } = this.#mixinise(name, context);
|
|
1718
577
|
const content = `
|
|
1719
|
-
class _EnumValue implements ${pascalcase(name)} {
|
|
578
|
+
class _EnumValue implements ${pascalcase(formatName(name))} {
|
|
1720
579
|
final ${valType} value;
|
|
1721
580
|
const _EnumValue(this.value);
|
|
1722
581
|
@override
|
|
1723
|
-
toJson()
|
|
582
|
+
toJson() => value;
|
|
1724
583
|
}
|
|
1725
|
-
abstract ${mixins.length ? "" : "mixin"} class ${pascalcase(name)} ${withMixins} {
|
|
1726
|
-
${values.map((it) => `static const _EnumValue ${formatName(it)} = _EnumValue(${typeof it === "number" ? it : `'${it}'`});`).join("\n")}
|
|
584
|
+
abstract ${mixins.length ? "" : "mixin"} class ${pascalcase(formatName(name))} ${withMixins} {
|
|
585
|
+
${values.map((it) => `static const _EnumValue ${formatName(snakecase(formatName(it)))} = _EnumValue(${typeof it === "number" ? it : `'${it}'`});`).join("\n")}
|
|
1727
586
|
dynamic toJson();
|
|
1728
587
|
|
|
1729
588
|
${valType} get value;
|
|
@@ -1731,7 +590,7 @@ return ${matches.join(" && ")};
|
|
|
1731
590
|
static _EnumValue fromJson(${valType} value) {
|
|
1732
591
|
switch (value) {
|
|
1733
592
|
${values.map(
|
|
1734
|
-
(it) => `case ${typeof it === "number" ? it : `'${it}'`}: return ${formatName(it)};`
|
|
593
|
+
(it) => `case ${typeof it === "number" ? it : `'${it}'`}: return ${formatName(snakecase(formatName(it)))};`
|
|
1735
594
|
).join("\n")}
|
|
1736
595
|
default:
|
|
1737
596
|
throw ArgumentError.value(value, "value", "No enum value with that name");
|
|
@@ -1749,15 +608,28 @@ return false;
|
|
|
1749
608
|
|
|
1750
609
|
}`;
|
|
1751
610
|
if (context.noEmit !== true) {
|
|
1752
|
-
this.#emit(name, content);
|
|
611
|
+
this.#emit(pascalcase(formatName(name)), content, schema);
|
|
1753
612
|
}
|
|
1754
613
|
return {
|
|
1755
|
-
|
|
614
|
+
use: pascalcase(formatName(name)),
|
|
615
|
+
type: this.#simple(coerceTypes(schema)[0]),
|
|
1756
616
|
content,
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
617
|
+
encodeV2: `${context.required ? "" : "?"}.toJson()`,
|
|
618
|
+
fromJson: `${pascalcase(name)}.fromJson(${context.parsable})`,
|
|
619
|
+
matches: `${pascalcase(name)}.matches(${context.parsable})`
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
#const(className, schema, context) {
|
|
623
|
+
const valType = this.#simple(coerceTypes(schema)[0]);
|
|
624
|
+
return {
|
|
625
|
+
content: "",
|
|
626
|
+
literal: valType === "String" ? `'${schema.const}'` : schema.const,
|
|
627
|
+
use: valType,
|
|
628
|
+
encode: "input",
|
|
629
|
+
encodeV2: "",
|
|
630
|
+
fromJson: context.parsable,
|
|
631
|
+
matches: context.parsable,
|
|
632
|
+
simple: true
|
|
1761
633
|
};
|
|
1762
634
|
}
|
|
1763
635
|
/**
|
|
@@ -1772,46 +644,44 @@ return false;
|
|
|
1772
644
|
content: "",
|
|
1773
645
|
use: "DateTime",
|
|
1774
646
|
simple: true,
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
fromJson: context.name ? `json['${context.name}'] != null ? DateTime.parse(json['${context.name}']) : null` : "json",
|
|
1779
|
-
matches: `json['${context.name}'] is String`
|
|
647
|
+
encodeV2: `${context.required ? "" : "?"}.toIso8601String()`,
|
|
648
|
+
fromJson: context.parsable ? context.required ? `DateTime.parse(${context.parsable})` : `${context.parsable} != null ? DateTime.parse(${context.parsable}) : null` : "json",
|
|
649
|
+
matches: `${context.parsable} is String`
|
|
1780
650
|
};
|
|
1781
651
|
case "binary":
|
|
1782
652
|
case "byte":
|
|
1783
653
|
return {
|
|
1784
654
|
content: "",
|
|
1785
655
|
use: "File",
|
|
1786
|
-
|
|
656
|
+
encodeV2: "",
|
|
1787
657
|
simple: true,
|
|
1788
|
-
fromJson: context.
|
|
1789
|
-
matches:
|
|
658
|
+
fromJson: context.parsable,
|
|
659
|
+
matches: `${context.parsable} is Uint8List`
|
|
1790
660
|
};
|
|
1791
661
|
default:
|
|
1792
662
|
return {
|
|
1793
663
|
encode: "input",
|
|
1794
664
|
use: `String`,
|
|
1795
665
|
content: "",
|
|
666
|
+
encodeV2: "",
|
|
1796
667
|
simple: true,
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
matches: `json['${context.name}'] is String`
|
|
668
|
+
fromJson: `${context.parsable} as String`,
|
|
669
|
+
matches: `${context.parsable} is String`
|
|
1800
670
|
};
|
|
1801
671
|
}
|
|
1802
672
|
}
|
|
1803
673
|
/**
|
|
1804
674
|
* Handle number/integer types with formats
|
|
1805
675
|
*/
|
|
1806
|
-
number(schema, context) {
|
|
676
|
+
#number(schema, context) {
|
|
1807
677
|
if (schema.type === "integer") {
|
|
1808
678
|
return {
|
|
1809
679
|
content: "",
|
|
1810
680
|
use: "int",
|
|
1811
681
|
simple: true,
|
|
1812
|
-
|
|
1813
|
-
fromJson:
|
|
1814
|
-
matches:
|
|
682
|
+
encodeV2: "",
|
|
683
|
+
fromJson: context.parsable,
|
|
684
|
+
matches: `${context.parsable} is int`
|
|
1815
685
|
};
|
|
1816
686
|
}
|
|
1817
687
|
if (["float", "double"].includes(schema.format)) {
|
|
@@ -1819,37 +689,40 @@ return false;
|
|
|
1819
689
|
content: "",
|
|
1820
690
|
use: "double",
|
|
1821
691
|
simple: true,
|
|
1822
|
-
|
|
1823
|
-
fromJson:
|
|
1824
|
-
matches:
|
|
692
|
+
encodeV2: "",
|
|
693
|
+
fromJson: context.parsable,
|
|
694
|
+
matches: `${context.parsable} is double`
|
|
1825
695
|
};
|
|
1826
696
|
}
|
|
1827
697
|
return {
|
|
1828
698
|
content: "",
|
|
1829
699
|
use: "num",
|
|
1830
700
|
simple: true,
|
|
1831
|
-
|
|
1832
|
-
fromJson:
|
|
1833
|
-
matches:
|
|
701
|
+
encodeV2: "",
|
|
702
|
+
fromJson: context.parsable,
|
|
703
|
+
matches: `${context.parsable} is double`
|
|
1834
704
|
};
|
|
1835
705
|
}
|
|
1836
706
|
#serialize(className, schema, required = true, context = {}) {
|
|
1837
|
-
if (
|
|
707
|
+
if (isRef(schema)) {
|
|
1838
708
|
return this.#ref(className, schema.$ref, required, context);
|
|
1839
709
|
}
|
|
1840
710
|
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
1841
711
|
return this.#allOf(className, schema.allOf, context);
|
|
1842
712
|
}
|
|
1843
713
|
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
1844
|
-
return this.#oneOf(className, schema
|
|
714
|
+
return this.#oneOf(className, schema, context);
|
|
1845
715
|
}
|
|
1846
716
|
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
1847
|
-
return this.#
|
|
717
|
+
return this.#oneOf(className, schema, context);
|
|
718
|
+
}
|
|
719
|
+
if (schema.const !== void 0) {
|
|
720
|
+
return this.#const(className, schema, context);
|
|
1848
721
|
}
|
|
1849
722
|
if (schema.enum && Array.isArray(schema.enum)) {
|
|
1850
723
|
return this.#enum(className, schema, context);
|
|
1851
724
|
}
|
|
1852
|
-
const types =
|
|
725
|
+
const types = coerceTypes(schema, false);
|
|
1853
726
|
let nullable = false;
|
|
1854
727
|
if ("nullable" in schema && schema.nullable) {
|
|
1855
728
|
nullable = true;
|
|
@@ -1866,10 +739,12 @@ return false;
|
|
|
1866
739
|
return this.#array(className, schema, true, context);
|
|
1867
740
|
}
|
|
1868
741
|
return {
|
|
742
|
+
// Unknown type -> fallback
|
|
1869
743
|
content: "",
|
|
1870
744
|
use: "dynamic",
|
|
1871
|
-
|
|
1872
|
-
|
|
745
|
+
encodeV2: "",
|
|
746
|
+
simple: true,
|
|
747
|
+
fromJson: context.parsable,
|
|
1873
748
|
nullable: false,
|
|
1874
749
|
matches: ""
|
|
1875
750
|
// keep it empty as 'type is dynamic' is always true
|
|
@@ -1891,93 +766,39 @@ return false;
|
|
|
1891
766
|
forJson: alias
|
|
1892
767
|
});
|
|
1893
768
|
if (alias) {
|
|
1894
|
-
this.#emit(
|
|
769
|
+
this.#emit(
|
|
770
|
+
pascalcase(formatName(className)),
|
|
771
|
+
`typedef ${pascalcase(alias)} = ${serialized.use};`,
|
|
772
|
+
resolveRef(this.#spec, schema)
|
|
773
|
+
);
|
|
1895
774
|
return serialized;
|
|
1896
775
|
}
|
|
1897
776
|
return serialized;
|
|
1898
777
|
}
|
|
1899
778
|
};
|
|
1900
779
|
function isObjectSchema(schema) {
|
|
1901
|
-
return !
|
|
780
|
+
return !isRef(schema) && (schema.type === "object" || !!coearceObject(schema).properties);
|
|
1902
781
|
}
|
|
1903
782
|
|
|
1904
783
|
// packages/dart/src/lib/http/dispatcher.txt
|
|
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
|
|
784
|
+
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 void _setHeaders(\n http.BaseRequest request,\n RequestConfig config, [\n String? contentType,\n ]) {\n request.headers.addAll(config.headers);\n for (var entry in config.input.headers.entries) {\n final value = entry.value;\n if (value != null) {\n request.headers[entry.key] = value;\n }\n }\n if (contentType != null) {\n request.headers['Content-Type'] = contentType;\n }\n }\n\n void _setParams(RequestConfig config) {\n final params = config.input.params;\n if (params.isEmpty) return;\n\n String path = config.url.toString();\n for (var entry in params.entries) {\n path = path.replaceAll('{${entry.key}}', entry.value.toString());\n }\n config.url = Uri.parse(path);\n }\n\n void _setQuery(RequestConfig config) {\n final query = config.input.query;\n if (query.isEmpty) return;\n\n final uri = config.url;\n final queryParameters = Map<String, String>.from(uri.queryParameters);\n\n for (var entry in query.entries) {\n if (entry.value != null) {\n queryParameters[entry.key] = entry.value.toString();\n }\n }\n\n config.url = uri.replace(queryParameters: queryParameters);\n }\n\n Future<http.StreamedResponse> formdata(RequestConfig config) async {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n _setParams(modifiedConfig);\n _setQuery(modifiedConfig);\n final request = http.MultipartRequest(\n modifiedConfig.method,\n modifiedConfig.url,\n );\n _setHeaders(request, modifiedConfig);\n\n for (var entry in config.input.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 _setParams(modifiedConfig);\n _setQuery(modifiedConfig);\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n _setHeaders(request, modifiedConfig);\n return request.send();\n }\n\n Future<http.StreamedResponse> json(RequestConfig config) {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n _setParams(modifiedConfig);\n _setQuery(modifiedConfig);\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n _setHeaders(request, modifiedConfig, 'application/json');\n\n if ((config.input.body is Map || config.input.body is List)) {\n request.body = jsonEncode(config.input.body);\n } else if (config.input.body is String) {\n request.body = config.input.body;\n } else {\n throw ArgumentError(\n 'Unsupported body type: ${config.input.body.runtimeType}',\n );\n }\n\n return request.send();\n }\n\n Future<http.StreamedResponse> binary(RequestConfig config) async {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n _setParams(modifiedConfig);\n _setQuery(modifiedConfig);\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n _setHeaders(request, modifiedConfig, 'application/octet-stream');\n\n switch (config.input.body) {\n case List<int> bytes:\n request.bodyBytes = bytes;\n case Stream<List<int>> stream:\n request.bodyBytes = await stream.expand((x) => x).toList();\n case String body:\n request.body = body;\n case File file:\n request.bodyBytes = await file.readAsBytes();\n default:\n throw ArgumentError(\n 'Unsupported body type for binary request: ${config.input.body.runtimeType}',\n );\n }\n\n return request.send();\n }\n\n Future<http.StreamedResponse> urlencoded(RequestConfig config) async {\n final modifiedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n _setParams(modifiedConfig);\n _setQuery(modifiedConfig);\n final request = http.Request(modifiedConfig.method, modifiedConfig.url);\n _setHeaders(request, modifiedConfig, 'application/x-www-form-urlencoded');\n\n // Convert body to URL-encoded string\n final bodyMap = config.input.body;\n request.body = bodyMap.entries\n .map(\n (entry) =>\n '${Uri.encodeComponent(entry.key)}=${Uri.encodeComponent(entry.value.toString())}',\n )\n .join('&');\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.startsWith('application/json')) {\n return jsonDecode(response.body);\n } else if (parsed.type.startsWith('text/')) {\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 Future<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 throw _handleError(stream);\n }\n\n Future<String> text(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 throw _handleError(stream);\n }\n\n _handleError(http.StreamedResponse stream) {\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\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";
|
|
1906
785
|
|
|
1907
786
|
// packages/dart/src/lib/http/interceptors.txt
|
|
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\
|
|
787
|
+
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 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 final RequestInput input;\n\n RequestConfig({\n required this.method,\n required this.url,\n required this.headers,\n this.input = const RequestInput.empty(),\n });\n}\n\nclass RequestInput {\n final Map<String, String?> headers;\n final Map<String, dynamic> query;\n final Map<String, dynamic> params;\n final dynamic body;\n RequestInput({\n this.headers = const {},\n this.query = const {},\n this.params = const {},\n required this.body,\n });\n\n const RequestInput.empty()\n : headers = const {},\n query = const {},\n params = const {},\n body = null;\n}\n";
|
|
1909
788
|
|
|
1910
789
|
// packages/dart/src/lib/http/responses.txt
|
|
1911
790
|
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";
|
|
1912
791
|
|
|
1913
792
|
// packages/dart/src/lib/generate.ts
|
|
1914
|
-
function
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
const refs2 = schemas2.filter(isRef4);
|
|
1924
|
-
const nonRefs = schemas2.filter(notRef2);
|
|
1925
|
-
if (nonRefs.some((it) => it.type && it.type !== "object")) {
|
|
1926
|
-
assert2(false, `allOf ${name} must be an object`);
|
|
1927
|
-
}
|
|
1928
|
-
const objectSchema = merge2(
|
|
1929
|
-
{},
|
|
1930
|
-
...nonRefs,
|
|
1931
|
-
...refs2.map((ref) => followRef3(spec, ref.$ref))
|
|
1932
|
-
);
|
|
1933
|
-
delete objectSchema.allOf;
|
|
1934
|
-
delete schema.allOf;
|
|
1935
|
-
Object.assign(schema, objectSchema);
|
|
1936
|
-
}
|
|
1937
|
-
if (schema.type === "object") {
|
|
1938
|
-
if (!isEmpty3(schema.oneOf)) {
|
|
1939
|
-
for (const oneOfIdx in schema.oneOf) {
|
|
1940
|
-
const oneOf = schema.oneOf[oneOfIdx];
|
|
1941
|
-
if (isRef4(oneOf))
|
|
1942
|
-
continue;
|
|
1943
|
-
if (!isEmpty3(oneOf.required) && schema.properties) {
|
|
1944
|
-
schema.oneOf[oneOfIdx] = schema.properties[oneOf.required[0]];
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
delete schema.type;
|
|
1948
|
-
tuneSpec(spec, schemas, refs);
|
|
1949
|
-
continue;
|
|
1950
|
-
}
|
|
1951
|
-
schema.properties ??= {};
|
|
1952
|
-
for (const [propName, value] of Object.entries(schema.properties)) {
|
|
1953
|
-
if (isRef4(value))
|
|
1954
|
-
continue;
|
|
1955
|
-
const refName = pascalcase2(`${name} ${propName.replace("[]", "")}`);
|
|
1956
|
-
refs.push({ name: refName, value });
|
|
1957
|
-
schema.properties[propName] = {
|
|
1958
|
-
$ref: `#/components/schemas/${refName}`
|
|
1959
|
-
};
|
|
1960
|
-
const props = Object.fromEntries(
|
|
1961
|
-
Object.entries(value.properties ?? {}).map(([key, value2]) => {
|
|
1962
|
-
return [pascalcase2(`${refName} ${key}`), value2];
|
|
1963
|
-
})
|
|
1964
|
-
);
|
|
1965
|
-
tuneSpec(spec, props, refs);
|
|
1966
|
-
}
|
|
1967
|
-
} else if (schema.type === "array") {
|
|
1968
|
-
if (isRef4(schema.items))
|
|
1969
|
-
continue;
|
|
1970
|
-
const refName = name;
|
|
1971
|
-
refs.push({ name: refName, value: schema.items ?? {} });
|
|
1972
|
-
schema.items = {
|
|
1973
|
-
$ref: `#/components/schemas/${refName}`
|
|
1974
|
-
};
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
async function generate(spec, settings) {
|
|
1979
|
-
spec = "x-sdk-augmented" in spec ? spec : augmentSpec({ spec });
|
|
1980
|
-
settings.writer ??= writeFiles;
|
|
793
|
+
async function generate(openapi, settings) {
|
|
794
|
+
const spec = augmentSpec({ spec: openapi }, true);
|
|
795
|
+
const clientName = settings.name || "Client";
|
|
796
|
+
const output = join(settings.output, "lib");
|
|
797
|
+
const { writer, files: writtenFiles } = createWriterProxy(
|
|
798
|
+
settings.writer ?? writeFiles,
|
|
799
|
+
settings.output
|
|
800
|
+
);
|
|
801
|
+
settings.writer = writer;
|
|
1981
802
|
settings.readFolder ??= async (folder) => {
|
|
1982
803
|
const files = await readdir(folder, { withFileTypes: true });
|
|
1983
804
|
return files.map((file) => ({
|
|
@@ -1986,80 +807,29 @@ async function generate(spec, settings) {
|
|
|
1986
807
|
isFolder: file.isDirectory()
|
|
1987
808
|
}));
|
|
1988
809
|
};
|
|
1989
|
-
const clientName = settings.name || "Client";
|
|
1990
|
-
const output = join(settings.output, "lib");
|
|
1991
810
|
const groups = {};
|
|
1992
|
-
spec
|
|
1993
|
-
spec.components.schemas ??= {};
|
|
1994
|
-
const inputs = {};
|
|
1995
|
-
const outputs = {};
|
|
1996
|
-
forEachOperation({ spec }, (entry, operation) => {
|
|
1997
|
-
operation.responses ??= {};
|
|
1998
|
-
spec.components ??= {};
|
|
1999
|
-
spec.components.schemas ??= {};
|
|
2000
|
-
for (const status in operation.responses) {
|
|
2001
|
-
if (!isSuccessStatusCode(status))
|
|
2002
|
-
continue;
|
|
2003
|
-
const response2 = operation.responses[status];
|
|
2004
|
-
if (!isEmpty3(response2.content)) {
|
|
2005
|
-
for (const [contentType, mediaType] of Object.entries(
|
|
2006
|
-
response2.content
|
|
2007
|
-
)) {
|
|
2008
|
-
if (parseJsonContentType(contentType)) {
|
|
2009
|
-
if (mediaType.schema && !isRef4(mediaType.schema)) {
|
|
2010
|
-
const outputName = pascalcase2(`${operation.operationId} output`);
|
|
2011
|
-
spec.components.schemas[outputName] = mediaType.schema;
|
|
2012
|
-
operation.responses[status].content ??= {};
|
|
2013
|
-
operation.responses[status].content[contentType].schema = {
|
|
2014
|
-
$ref: `#/components/schemas/${outputName}`
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
811
|
+
forEachOperation(spec, (entry, operation) => {
|
|
2021
812
|
console.log(`Processing ${entry.method} ${entry.path}`);
|
|
2022
|
-
const group = groups[entry.groupName]
|
|
813
|
+
const group = groups[entry.groupName] ??= {
|
|
2023
814
|
methods: [],
|
|
2024
815
|
use: `final ${entry.groupName} = new ${pascalcase2(entry.groupName)}();`
|
|
2025
|
-
}
|
|
816
|
+
};
|
|
2026
817
|
const input = toInputs(spec, { entry, operation });
|
|
2027
|
-
Object.assign(inputs, input.inputs);
|
|
2028
818
|
const response = toOutput(spec, operation);
|
|
2029
|
-
if (response) {
|
|
2030
|
-
Object.assign(outputs, response.outputs);
|
|
2031
|
-
}
|
|
2032
819
|
group.methods.push(`
|
|
2033
|
-
Future<${response ? response.returnType : "http.StreamedResponse"}> ${
|
|
2034
|
-
${
|
|
820
|
+
Future<${response ? response.returnType : "http.StreamedResponse"}> ${camelcase2(operation.operationId)}(
|
|
821
|
+
${input.haveInput ? `${input.inputName} input` : ""}
|
|
2035
822
|
) async {
|
|
2036
823
|
final stream = await this.dispatcher.${input.contentType}(RequestConfig(
|
|
2037
824
|
method: '${entry.method}',
|
|
2038
825
|
url: Uri.parse('${entry.path}'),
|
|
2039
826
|
headers: {},
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
827
|
+
${input.haveInput ? "input: input.toRequest()" : ""}));
|
|
828
|
+
${response ? `${response.decode};` : "return stream;"}
|
|
829
|
+
}
|
|
830
|
+
`);
|
|
2044
831
|
});
|
|
2045
|
-
const
|
|
2046
|
-
tuneSpec(spec, spec.components.schemas, newRefs);
|
|
2047
|
-
for (const ref of newRefs) {
|
|
2048
|
-
spec.components.schemas[ref.name] = ref.value;
|
|
2049
|
-
}
|
|
2050
|
-
await writeFile(
|
|
2051
|
-
join(process.cwd(), "openai.json"),
|
|
2052
|
-
JSON.stringify(spec, null, 2)
|
|
2053
|
-
);
|
|
2054
|
-
const models = Object.entries(spec.components.schemas).reduce((acc, [name, schema]) => {
|
|
2055
|
-
const serializer = new DartSerializer(spec, (name2, content) => {
|
|
2056
|
-
acc[`models/${snakecase2(name2)}.dart`] = `import 'dart:io';import 'dart:typed_data'; import './index.dart';
|
|
2057
|
-
|
|
2058
|
-
${content}`;
|
|
2059
|
-
});
|
|
2060
|
-
serializer.handle(pascalcase2(name), schema);
|
|
2061
|
-
return acc;
|
|
2062
|
-
}, {});
|
|
832
|
+
const models = serializeModels(spec);
|
|
2063
833
|
const clazzez = Object.entries(groups).reduce(
|
|
2064
834
|
(acc, [name, { methods }]) => {
|
|
2065
835
|
return {
|
|
@@ -2093,14 +863,14 @@ import './http.dart';
|
|
|
2093
863
|
|
|
2094
864
|
class ${clientName} {
|
|
2095
865
|
final Options options;
|
|
2096
|
-
${Object.keys(groups).map((name) => `late final ${pascalcase2(name)}Client ${
|
|
866
|
+
${Object.keys(groups).map((name) => `late final ${pascalcase2(name)}Client ${camelcase2(name)};`).join("\n")}
|
|
2097
867
|
|
|
2098
868
|
${clientName}(this.options) {
|
|
2099
869
|
final interceptors = [BaseUrlInterceptor(() => this.options.baseUrl), LoggingInterceptor()];
|
|
2100
870
|
final dispatcher = Dispatcher(interceptors);
|
|
2101
871
|
final receiver = Receiver(interceptors);
|
|
2102
872
|
${Object.keys(groups).map(
|
|
2103
|
-
(name) => `this.${
|
|
873
|
+
(name) => `this.${camelcase2(name)} = ${pascalcase2(name)}Client(dispatcher, receiver);`
|
|
2104
874
|
).join("\n")}
|
|
2105
875
|
|
|
2106
876
|
}
|
|
@@ -2119,11 +889,19 @@ class Options {
|
|
|
2119
889
|
}
|
|
2120
890
|
|
|
2121
891
|
`;
|
|
2122
|
-
await settings.writer(output,
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
892
|
+
await settings.writer(output, models);
|
|
893
|
+
const metadata = await readWriteMetadata(
|
|
894
|
+
settings.output,
|
|
895
|
+
Array.from(writtenFiles)
|
|
896
|
+
);
|
|
897
|
+
if (settings.cleanup !== false && writtenFiles.size > 0) {
|
|
898
|
+
await cleanFiles(metadata.content, settings.output, [
|
|
899
|
+
"/package.dart",
|
|
900
|
+
"/**/index.dart",
|
|
901
|
+
"pubspec.yaml",
|
|
902
|
+
"/metadata.json"
|
|
903
|
+
]);
|
|
904
|
+
}
|
|
2127
905
|
await settings.writer(output, {
|
|
2128
906
|
"models/index.dart": await getFolderExportsV2(
|
|
2129
907
|
join(output, "models"),
|
|
@@ -2183,101 +961,152 @@ class Options {
|
|
|
2183
961
|
})
|
|
2184
962
|
}
|
|
2185
963
|
});
|
|
964
|
+
await writeFile(
|
|
965
|
+
join(settings.output, "openapi.json"),
|
|
966
|
+
JSON.stringify(spec, null, 2)
|
|
967
|
+
);
|
|
2186
968
|
await settings.formatCode?.({
|
|
2187
969
|
output
|
|
2188
970
|
});
|
|
2189
971
|
}
|
|
2190
972
|
function toInputs(spec, { entry, operation }) {
|
|
2191
|
-
|
|
2192
|
-
const inputName = pascalcase2(`${operation.operationId} input`);
|
|
973
|
+
let inputName;
|
|
2193
974
|
let contentType = "empty";
|
|
2194
975
|
let encode = "";
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
const serializer = new DartSerializer(spec, (name, content) => {
|
|
2208
|
-
inputs[join(`inputs/${name}.dart`)] = `import 'dart:io';import 'dart:typed_data';import '../models/index.dart'; import './index.dart';
|
|
2209
|
-
|
|
2210
|
-
${content}`;
|
|
2211
|
-
});
|
|
2212
|
-
const serialized = serializer.handle(inputName, ctSchema, true, {
|
|
2213
|
-
alias: isObjectSchema(ctSchema) ? void 0 : inputName
|
|
2214
|
-
});
|
|
2215
|
-
encode = serialized.encode;
|
|
2216
|
-
const [mediaType, mediaSubType] = partContentType(type).type.split("/");
|
|
2217
|
-
if (mediaType === "application") {
|
|
2218
|
-
contentType = parseJsonContentType(type);
|
|
2219
|
-
} else {
|
|
2220
|
-
contentType = mediaType;
|
|
2221
|
-
}
|
|
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
|
|
976
|
+
let haveInput = false;
|
|
977
|
+
for (const type in operation.requestBody.content) {
|
|
978
|
+
const objectSchema = resolveRef2(
|
|
979
|
+
spec,
|
|
980
|
+
operation.requestBody.content[type].schema
|
|
981
|
+
);
|
|
982
|
+
const serializer = new DartSerializer(spec);
|
|
983
|
+
inputName = objectSchema["x-inputname"];
|
|
984
|
+
const serialized = serializer.handle(inputName, objectSchema, true, {
|
|
985
|
+
alias: isObjectSchema(objectSchema) ? void 0 : inputName,
|
|
986
|
+
requestize: objectSchema["x-requestbody"] === true,
|
|
987
|
+
noEmit: true
|
|
2235
988
|
});
|
|
2236
989
|
encode = serialized.encode;
|
|
990
|
+
const [mediaType, mediaSubType] = partContentType(type).type.split("/");
|
|
991
|
+
if (mediaSubType === "empty") {
|
|
992
|
+
contentType = "empty";
|
|
993
|
+
} else if (mediaSubType === "x-www-form-urlencoded") {
|
|
994
|
+
contentType = "urlencoded";
|
|
995
|
+
} else if (mediaSubType === "octet-stream") {
|
|
996
|
+
contentType = "binary";
|
|
997
|
+
} else if (mediaType === "application") {
|
|
998
|
+
contentType = parseJsonContentType(type);
|
|
999
|
+
} else if (mediaType === "multipart") {
|
|
1000
|
+
contentType = "formdata";
|
|
1001
|
+
} else {
|
|
1002
|
+
contentType = "binary";
|
|
1003
|
+
}
|
|
1004
|
+
if (!isEmpty2({ ...objectSchema.properties, ...objectSchema["x-properties"] })) {
|
|
1005
|
+
haveInput = true;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
if (!inputName) {
|
|
1009
|
+
throw new Error(
|
|
1010
|
+
`No input name found for operation ${operation.operationId} in ${entry.path}`
|
|
1011
|
+
);
|
|
2237
1012
|
}
|
|
2238
|
-
return {
|
|
1013
|
+
return { inputName, contentType, encode, haveInput };
|
|
2239
1014
|
}
|
|
2240
1015
|
function toOutput(spec, operation) {
|
|
2241
|
-
const outputName = pascalcase2(`${operation.operationId} output`);
|
|
2242
1016
|
operation.responses ??= {};
|
|
2243
|
-
const outputs = {};
|
|
2244
1017
|
for (const status in operation.responses) {
|
|
2245
|
-
|
|
1018
|
+
if (!isSuccessStatusCode(status))
|
|
1019
|
+
continue;
|
|
1020
|
+
const response = operation.responses[status];
|
|
1021
|
+
const outputName = response["x-response-name"];
|
|
1022
|
+
if ((response.headers ?? {})["Transfer-Encoding"]) {
|
|
1023
|
+
return streamedOutput();
|
|
1024
|
+
}
|
|
2246
1025
|
for (const type in response.content) {
|
|
2247
|
-
const
|
|
2248
|
-
if (!schema) {
|
|
2249
|
-
console.warn(
|
|
2250
|
-
`Schema not found for ${type} in ${operation.operationId}`
|
|
2251
|
-
);
|
|
2252
|
-
continue;
|
|
2253
|
-
}
|
|
2254
|
-
const serializer = new DartSerializer(spec, (name, content) => {
|
|
2255
|
-
});
|
|
1026
|
+
const schema = response.content[type].schema;
|
|
2256
1027
|
if (isStreamingContentType(type)) {
|
|
2257
|
-
return
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
decode: `return stream`,
|
|
2262
|
-
returnType: `http.StreamedResponse`
|
|
2263
|
-
};
|
|
1028
|
+
return streamedOutput();
|
|
1029
|
+
}
|
|
1030
|
+
if (isSseContentType(type)) {
|
|
1031
|
+
continue;
|
|
2264
1032
|
}
|
|
2265
1033
|
if (parseJsonContentType(type)) {
|
|
1034
|
+
if (!schema) {
|
|
1035
|
+
return streamedOutput();
|
|
1036
|
+
}
|
|
1037
|
+
const serializer = new DartSerializer(spec);
|
|
2266
1038
|
const serialized = serializer.handle(outputName, schema, true, {
|
|
2267
1039
|
// alias: outputName,
|
|
2268
1040
|
noEmit: true
|
|
2269
1041
|
});
|
|
2270
1042
|
return {
|
|
2271
1043
|
type: "json",
|
|
2272
|
-
outputName,
|
|
2273
|
-
outputs,
|
|
2274
1044
|
decode: `final json = await this.receiver.json(stream); return ${serialized.fromJson}`,
|
|
2275
1045
|
returnType: serialized.use
|
|
2276
1046
|
};
|
|
2277
1047
|
}
|
|
2278
1048
|
}
|
|
2279
1049
|
}
|
|
2280
|
-
return
|
|
1050
|
+
return streamedOutput();
|
|
1051
|
+
}
|
|
1052
|
+
function streamedOutput() {
|
|
1053
|
+
return {
|
|
1054
|
+
type: "stream",
|
|
1055
|
+
decode: `return stream`,
|
|
1056
|
+
returnType: `http.StreamedResponse`
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
function serializeModels(spec) {
|
|
1060
|
+
const serializer = new DartSerializer(spec);
|
|
1061
|
+
return Object.entries(spec.components.schemas).reduce(
|
|
1062
|
+
(acc, [name, schema]) => {
|
|
1063
|
+
serializer.onEmit((name2, content, schema2) => {
|
|
1064
|
+
const isResponseBody = schema2["x-responsebody"];
|
|
1065
|
+
const isRequestBody = schema2["x-requestbody"];
|
|
1066
|
+
const folder = isRequestBody ? "inputs" : isResponseBody ? "outputs" : "models";
|
|
1067
|
+
acc[join(folder, `${snakecase2(name2)}.dart`)] = [
|
|
1068
|
+
`import 'dart:io';`,
|
|
1069
|
+
`import 'dart:typed_data';`,
|
|
1070
|
+
// `import './index.dart';`,
|
|
1071
|
+
// `import '../interceptors.dart';`,
|
|
1072
|
+
`import '../package.dart';`,
|
|
1073
|
+
// folder === 'inputs' || folder === 'outputs'
|
|
1074
|
+
// ? `import '../models/index.dart';`
|
|
1075
|
+
// : `import '../inputs/index.dart';`,
|
|
1076
|
+
content
|
|
1077
|
+
].join("\n");
|
|
1078
|
+
});
|
|
1079
|
+
if (isRef2(schema)) {
|
|
1080
|
+
serializer.handle(pascalcase2(name), schema, true, {
|
|
1081
|
+
alias: isRef2(schema) ? name : void 0
|
|
1082
|
+
});
|
|
1083
|
+
return acc;
|
|
1084
|
+
}
|
|
1085
|
+
if (schema["x-requestbody"]) {
|
|
1086
|
+
serializer.handle(
|
|
1087
|
+
pascalcase2(name),
|
|
1088
|
+
schema.type !== "object" ? {
|
|
1089
|
+
type: "object",
|
|
1090
|
+
required: ["$body"],
|
|
1091
|
+
properties: {
|
|
1092
|
+
$body: {
|
|
1093
|
+
...schema,
|
|
1094
|
+
"x-special": true
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
} : schema,
|
|
1098
|
+
true,
|
|
1099
|
+
{
|
|
1100
|
+
requestize: true
|
|
1101
|
+
}
|
|
1102
|
+
);
|
|
1103
|
+
} else {
|
|
1104
|
+
serializer.handle(pascalcase2(name), schema, true, {});
|
|
1105
|
+
}
|
|
1106
|
+
return acc;
|
|
1107
|
+
},
|
|
1108
|
+
{}
|
|
1109
|
+
);
|
|
2281
1110
|
}
|
|
2282
1111
|
export {
|
|
2283
1112
|
generate
|