@sdk-it/dart 0.15.0 → 0.16.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 CHANGED
@@ -1,25 +1,682 @@
1
1
  // packages/dart/src/lib/generate.ts
2
- import { execSync } from "node:child_process";
2
+ import { merge as merge2 } from "lodash-es";
3
+ import assert2 from "node:assert";
4
+ import { writeFile } from "node:fs/promises";
3
5
  import { join } from "node:path";
4
- import "npm-run-path";
5
- import { camelcase, pascalcase, spinalcase } from "stringcase";
6
- import { forEachOperation, writeFiles } from "@sdk-it/core";
6
+ import { camelcase as camelcase2 } from "stringcase";
7
+ import {
8
+ followRef as followRef2,
9
+ forEachOperation,
10
+ getFolderExportsV2,
11
+ isEmpty as isEmpty2,
12
+ isRef as isRef2,
13
+ notRef as notRef2,
14
+ pascalcase as pascalcase2,
15
+ snakecase as snakecase2,
16
+ writeFiles
17
+ } from "@sdk-it/core";
18
+
19
+ // packages/dart/src/lib/dart-emitter.ts
20
+ import { merge } from "lodash-es";
21
+ import assert from "node:assert";
22
+ import { camelcase, snakecase } from "stringcase";
23
+ import {
24
+ cleanRef,
25
+ followRef,
26
+ isEmpty,
27
+ isRef,
28
+ notRef,
29
+ parseRef,
30
+ pascalcase
31
+ } from "@sdk-it/core";
32
+ var formatName = (it) => {
33
+ const startsWithDigitPattern = /^\d/;
34
+ if (typeof it === "number") {
35
+ return `$${it}`;
36
+ }
37
+ if (it === "default") {
38
+ return "$default";
39
+ }
40
+ if (typeof it === "string") {
41
+ if (startsWithDigitPattern.test(it)) {
42
+ return `$${it}`;
43
+ }
44
+ let nameToFormat = it;
45
+ if (nameToFormat.startsWith("[")) {
46
+ nameToFormat = nameToFormat.slice(1);
47
+ }
48
+ if (nameToFormat.endsWith("]")) {
49
+ nameToFormat = nameToFormat.slice(0, -1);
50
+ }
51
+ return snakecase(nameToFormat);
52
+ }
53
+ return snakecase(String(it));
54
+ };
55
+ var DartSerializer = class {
56
+ #spec;
57
+ #emit;
58
+ constructor(spec, emit) {
59
+ this.#spec = spec;
60
+ this.#emit = emit;
61
+ }
62
+ #getRefUsage(schemaName, list = []) {
63
+ this.#spec.components ??= {};
64
+ this.#spec.components.schemas ??= {};
65
+ this.#spec.components.responses ??= {};
66
+ const checkSchema = (schema) => {
67
+ if (isRef(schema)) {
68
+ const { model } = parseRef(schema.$ref);
69
+ return model === schemaName;
70
+ }
71
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
72
+ return schema.oneOf.some(
73
+ (subSchema) => checkSchema(subSchema)
74
+ );
75
+ }
76
+ if (schema.type === "array" && schema.items && notRef(schema.items) && schema.items.oneOf) {
77
+ return checkSchema(schema.items);
78
+ }
79
+ return false;
80
+ };
81
+ for (const [key, value] of Object.entries(this.#spec.components.schemas)) {
82
+ if (checkSchema(value)) {
83
+ list.push(key);
84
+ }
85
+ }
86
+ return list;
87
+ }
88
+ #object(className, schema, context) {
89
+ if (schema.additionalProperties) {
90
+ return {
91
+ content: "",
92
+ use: "Map<String, dynamic>",
93
+ toJson: `this.${camelcase(context.name)}`,
94
+ fromJson: `json['${camelcase(context.name)}']`,
95
+ matches: `json['${camelcase(context.name)}'] is Map<String, dynamic>`
96
+ };
97
+ }
98
+ if (isEmpty(schema.properties)) {
99
+ if (context.noEmit !== true) {
100
+ this.#emit(
101
+ className,
102
+ `class ${className} {
103
+ const ${className}(); // Add const constructor
104
+
105
+ factory ${className}.fromJson(Map<String, dynamic> json) {
106
+ return const ${className}();
107
+ }
108
+
109
+ Map<String, dynamic> toJson() => {};
110
+
111
+ /// Determines if a given map can be parsed into an instance of this class.
112
+ /// Returns true for any map since this class has no properties.
113
+ static bool matches(Map<String, dynamic> json) {
114
+ return true; // Any map is fine for an empty object
115
+ }
116
+ }`
117
+ );
118
+ }
119
+ return {
120
+ content: "",
121
+ use: className,
122
+ toJson: `${this.#safe(context.name, context.required)}`,
123
+ fromJson: `${className}.fromJson(json['${context.name}'])`,
124
+ matches: `${className}.matches(json['${context.name}'])`
125
+ };
126
+ }
127
+ const props = [];
128
+ const toJsonProperties = [];
129
+ const constructorParams = [];
130
+ const fromJsonParams = [];
131
+ const matches = [];
132
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
133
+ const propName = key.replace("[]", "");
134
+ const required = (schema.required ?? []).includes(key);
135
+ const typeStr = this.handle(className, propSchema, required, {
136
+ name: propName,
137
+ required,
138
+ propName: [className, propName].filter(Boolean).join("_")
139
+ });
140
+ const nullable2 = !required;
141
+ const nullableSuffix = nullable2 ? "?" : "";
142
+ props.push(
143
+ `final ${typeStr.use}${nullableSuffix} ${camelcase(propName)};`
144
+ );
145
+ fromJsonParams.push(`${camelcase(propName)}: ${typeStr.fromJson}`);
146
+ toJsonProperties.push(`'${propName}': ${typeStr.toJson}`);
147
+ constructorParams.push(
148
+ `${required ? "required " : ""}this.${camelcase(propName)},`
149
+ );
150
+ if (required) {
151
+ matches.push(`(
152
+ json.containsKey('${camelcase(propName)}')
153
+ ? ${nullable2 ? `json['${propName}'] == null` : `json['${propName}'] != null`} && ${typeStr.matches}
154
+ : false)`);
155
+ } else {
156
+ matches.push(`(
157
+ json.containsKey('${camelcase(propName)}')
158
+ ? ${nullable2 ? `json['${propName}'] == null` : `json['${propName}'] != null`} || ${typeStr.matches}
159
+ : true)`);
160
+ }
161
+ }
162
+ const { mixins, withMixins } = this.#mixinise(className, context);
163
+ const content = `class ${className} ${withMixins} {
164
+ ${props.join("\n")}
165
+ ${!mixins.length ? "const" : ""} ${className}({
166
+ ${constructorParams.join("\n")}})${mixins.length > 1 ? "" : `:super()`};
167
+ factory ${className}.fromJson(Map<String, dynamic> json) {
168
+ return ${className}(
169
+ ${fromJsonParams.join(",\n")});
170
+ }
171
+ Map<String, dynamic> toJson() => {
172
+ ${toJsonProperties.join(",\n")}
173
+ };
174
+ static bool matches(Map<String, dynamic> json) {
175
+ return ${matches.join(" && ")};
176
+ }
177
+ }`;
178
+ if (context.noEmit !== true) {
179
+ this.#emit(className, content);
180
+ }
181
+ const nullable = !context.required || context.nullable === true;
182
+ return {
183
+ use: className,
184
+ content,
185
+ toJson: `${this.#safe(context.name, context.required)}`,
186
+ fromJson: `${className}.fromJson(json['${context.name}'])`,
187
+ matches: `${className}.matches(json['${context.name}'])`
188
+ };
189
+ }
190
+ #safe(accces, required) {
191
+ return required ? `this.${camelcase(accces)}.toJson()` : `this.${camelcase(accces)} != null ? this.${camelcase(accces)}!.toJson() : null`;
192
+ }
193
+ #array(className, schema, required = false, context) {
194
+ const { items } = schema;
195
+ if (!items) {
196
+ return {
197
+ content: "",
198
+ use: "List<dynamic>",
199
+ toJson: "",
200
+ fromJson: "",
201
+ matches: ""
202
+ };
203
+ }
204
+ const itemsType = this.handle(className, items, true, context);
205
+ return {
206
+ content: "",
207
+ use: `List<${itemsType.use}>`,
208
+ fromJson: required ? `(json['${context.name}'] as List<${itemsType.simple ? itemsType.use : "dynamic"}>).map((it) => ${itemsType.simple ? "it" : `${itemsType.use}.fromJson(it)`}).toList()` : `json['${context.name}'] != null ? (json['${context.name}'] as List).map((it) => ${itemsType.fromJson}).toList() : null`,
209
+ toJson: `${context.required ? `this.${camelcase(context.name)}${itemsType.simple ? "" : ".map((it) => it.toJson()).toList()"}` : `this.${camelcase(context.name)}!= null? this.${camelcase(context.name)}${itemsType.simple ? "" : "!.map((it) => it.toJson()).toList()"} : null`}`,
210
+ matches: `json['${camelcase(context.name)}'].every((it) => ${itemsType.matches})`
211
+ };
212
+ }
213
+ /**
214
+ * Convert a basic type to Dart
215
+ */
216
+ primitive(className, type, schema, context, required = false) {
217
+ switch (type) {
218
+ case "string":
219
+ return this.#string(schema, context);
220
+ case "number":
221
+ case "integer":
222
+ return this.number(schema, context);
223
+ case "boolean":
224
+ return {
225
+ content: "",
226
+ use: "bool",
227
+ toJson: `${camelcase(context.name)}`,
228
+ fromJson: `json['${context.name}']`,
229
+ matches: `json['${context.name}'] is bool`
230
+ };
231
+ case "object":
232
+ return this.#object(className, schema, context);
233
+ case "array":
234
+ return this.#array(className, schema, required, context);
235
+ case "null":
236
+ return {
237
+ content: "",
238
+ use: "Null",
239
+ toJson: `${camelcase(context.name)}`,
240
+ fromJson: `json['${context.name}']`
241
+ };
242
+ default:
243
+ return {
244
+ content: "",
245
+ use: "dynamic",
246
+ toJson: `${camelcase(context.name)}`,
247
+ fromJson: `json['${context.name}']`
248
+ };
249
+ }
250
+ }
251
+ #ref($ref, required, context) {
252
+ const schemaName = cleanRef($ref).split("/").pop();
253
+ const result = this.handle(
254
+ context.alias || schemaName,
255
+ followRef(this.#spec, $ref),
256
+ required,
257
+ {
258
+ ...context,
259
+ propName: schemaName,
260
+ noEmit: !context.forceEmit
261
+ }
262
+ );
263
+ return result;
264
+ }
265
+ // fixme: this method should no longer be needed because the logic in it is being preprocessed before emitting begins
266
+ #allOf(className, schemas, context) {
267
+ const name = pascalcase(context.propName || className);
268
+ const refs = schemas.filter(isRef);
269
+ const nonRefs = schemas.filter(notRef);
270
+ if (nonRefs.some((it) => it.type && it.type !== "object")) {
271
+ assert(false, `allOf ${name} must be an object`);
272
+ }
273
+ const objectSchema = merge(
274
+ {},
275
+ ...nonRefs,
276
+ ...refs.map((ref) => followRef(this.#spec, ref.$ref))
277
+ );
278
+ delete objectSchema.allOf;
279
+ return this.handle(name, objectSchema, true, context);
280
+ }
281
+ anyOf(className, schemas, context) {
282
+ if (schemas.length === 0) {
283
+ return {
284
+ content: "",
285
+ use: "dynamic",
286
+ toJson: `${camelcase(context.name)}`,
287
+ fromJson: `json['${context.name}']`
288
+ };
289
+ }
290
+ return this.handle(className, schemas[0], true, context);
291
+ }
292
+ #mixinise(name, context) {
293
+ const mixins = this.#getRefUsage(name);
294
+ if (context.mixin) {
295
+ mixins.unshift(context.mixin);
296
+ }
297
+ const withMixins = mixins.length > 1 ? ` with ${mixins.join(", ")}` : mixins.length === 1 ? `extends ${mixins[0]}` : "";
298
+ return {
299
+ withMixins,
300
+ mixins
301
+ };
302
+ }
303
+ #oneOf(className, schemas, context) {
304
+ const name = pascalcase(context.propName || className);
305
+ if (schemas.length === 0) {
306
+ return {
307
+ content: "",
308
+ use: "dynamic",
309
+ toJson: `${camelcase(context.name)}`,
310
+ fromJson: `json['${context.name}']`
311
+ };
312
+ }
313
+ const content = [];
314
+ const patterns = [];
315
+ const objects = schemas.filter(notRef).filter((it) => it.type === "object");
316
+ for (const schema of schemas) {
317
+ if (isRef(schema)) {
318
+ const refType = this.#ref(schema.$ref, true, context);
319
+ patterns.push({
320
+ pattern: `case ${refType.type || "Map<String, dynamic>"} map when ${refType.use}.matches(map): return ${refType.use}.fromJson(map);`,
321
+ name: refType.use
322
+ });
323
+ } else if (schema.type === "string") {
324
+ content.push(`class ${name}Text with ${name} {
325
+ final String value;
326
+ ${name}Text(this.value);
327
+ @override
328
+ dynamic toJson() => value;
329
+ static bool matches(dynamic value) {
330
+ return value is String;
331
+ }}
332
+ `);
333
+ patterns.push({
334
+ pattern: `case String(): return ${name}Text(json);`,
335
+ name: `${name}Text`
336
+ });
337
+ } else if (schema.type === "array") {
338
+ const itemsType = this.handle(name, schema.items, true, {
339
+ ...context,
340
+ noEmit: true
341
+ });
342
+ content.push(`class ${name}List with ${name} {
343
+ final List<${itemsType.use}> value;
344
+ ${name}List(this.value);
345
+ @override
346
+ dynamic toJson() => value;
347
+ static bool matches(dynamic value) {
348
+ return value is List;
349
+ }}`);
350
+ patterns.push({
351
+ pattern: `case List(): return ${name}List(List<${itemsType.use}>.from(json));`,
352
+ name: `${name}List`
353
+ });
354
+ }
355
+ }
356
+ if (objects.length) {
357
+ const candidates = {};
358
+ for (const schema of objects) {
359
+ if (schema.additionalProperties === true) {
360
+ continue;
361
+ }
362
+ assert(
363
+ schema.properties,
364
+ `Schema ${name} has no properties which are required in oneOf in order to determine the discriminator.`
365
+ );
366
+ for (const [propName, propSchema] of Object.entries(
367
+ schema.properties
368
+ )) {
369
+ 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
370
+ propSchema.enum.length === 1) {
371
+ candidates[propName] ??= /* @__PURE__ */ new Set();
372
+ candidates[propName].add(String(propSchema.enum[0]));
373
+ }
374
+ }
375
+ }
376
+ let discriminatorProp;
377
+ for (const [name2, values] of Object.entries(candidates)) {
378
+ if (
379
+ // make sure we pick the prop that exists on all objects
380
+ values.size === objects.filter((it) => it.properties?.[name2]).length
381
+ ) {
382
+ discriminatorProp = name2;
383
+ break;
384
+ }
385
+ }
386
+ if (discriminatorProp) {
387
+ for (const schema of objects) {
388
+ const discriminatorValue = schema.properties[discriminatorProp].enum?.[0];
389
+ const varientName = `${name}${pascalcase(discriminatorValue)}`;
390
+ patterns.push({
391
+ pattern: `case Map<String, dynamic> map when ${varientName}.matches(json): return ${varientName}.fromJson(map);`,
392
+ name: varientName
393
+ });
394
+ const objResult = this.#object(varientName, schema, {
395
+ ...context,
396
+ noEmit: true,
397
+ mixin: name
398
+ });
399
+ content.push(objResult.content);
400
+ }
401
+ }
402
+ }
403
+ const { mixins, withMixins } = this.#mixinise(name, context);
404
+ content.unshift(`abstract ${mixins.length ? "" : "mixin"} class ${name} ${withMixins} {
405
+ dynamic toJson();
406
+ ${patterns.length ? `static ${name} fromJson(dynamic json) {
407
+ switch (json){
408
+ ${patterns.map((it) => it.pattern).join("\n")}
409
+ default:
410
+ throw ArgumentError("Invalid type for query property: \${json}");
411
+ }
412
+ }
413
+
414
+
415
+ ${patterns.length ? ` static bool matches(dynamic value) {
416
+ return ${patterns.map((it) => `value is ${it.name}`).join(" || ")};
417
+ }` : ""}
418
+
419
+ ` : ""}
420
+ }`);
421
+ this.#emit(name, content.join("\n"));
422
+ return {
423
+ content: content.join("\n"),
424
+ use: name,
425
+ toJson: `${this.#safe(context.name, context.required)}`,
426
+ fromJson: `${name}.fromJson(json['${context.name}'])`,
427
+ matches: `${name}.matches(json['${context.name}'])`
428
+ };
429
+ }
430
+ #simple(type) {
431
+ switch (type) {
432
+ case "string":
433
+ return "String";
434
+ case "number":
435
+ return "double";
436
+ case "integer":
437
+ return "int";
438
+ case "boolean":
439
+ return "bool";
440
+ default:
441
+ return "dynamic";
442
+ }
443
+ }
444
+ #enum(className, schema, context) {
445
+ const name = context.propName || className;
446
+ const values = schema.enum;
447
+ const valType = this.#simple(schema.type || "string");
448
+ const { mixins, withMixins } = this.#mixinise(className, context);
449
+ const content = `
450
+ class _EnumValue implements ${pascalcase(name)} {
451
+ final ${valType} value;
452
+ const _EnumValue(this.value);
453
+ @override
454
+ toJson() {return this.value;}
455
+ }
456
+ abstract ${mixins.length ? "" : "mixin"} class ${pascalcase(name)} ${withMixins} {
457
+ ${values.map((it) => `static const _EnumValue ${formatName(it)} = _EnumValue(${typeof it === "number" ? it : `'${it}'`});`).join("\n")}
458
+ dynamic toJson();
459
+
460
+ static _EnumValue fromJson(${valType} value) {
461
+ switch (value) {
462
+ ${values.map(
463
+ (it) => `case ${typeof it === "number" ? it : `'${it}'`}: return ${formatName(it)};`
464
+ ).join("\n")}
465
+ default:
466
+ throw ArgumentError.value(value, "value", "No enum value with that name");
467
+ }
468
+ }
469
+
470
+ static bool matches(${valType} value) {
471
+ try {
472
+ fromJson(value);
473
+ return true;
474
+ } catch (error) {
475
+ return false;
476
+ }
477
+ }
478
+
479
+ }`;
480
+ if (context.noEmit !== true) {
481
+ this.#emit(name, content);
482
+ }
483
+ return {
484
+ type: Array.isArray(schema.type) ? this.#simple(schema.type[0]) : schema.type ? this.#simple(schema.type) : void 0,
485
+ content,
486
+ use: pascalcase(name),
487
+ toJson: `${context.required ? `this.${camelcase(context.name)}.toJson()` : `this.${camelcase(context.name)} != null ? this.${camelcase(context.name)}!.toJson() : null`}`,
488
+ fromJson: `${pascalcase(name)}.fromJson(json['${context.name}'])`,
489
+ matches: `${pascalcase(name)}.matches(json['${context.name}'])`
490
+ };
491
+ }
492
+ /**
493
+ * Handle string type with formats
494
+ */
495
+ #string(schema, context) {
496
+ switch (schema.format) {
497
+ case "date-time":
498
+ case "datetime":
499
+ case "date":
500
+ return {
501
+ content: "",
502
+ use: "DateTime",
503
+ simple: true,
504
+ toJson: `this.${camelcase(context.name)}.toIso8601String()`,
505
+ fromJson: `DateTime.parse(json['${context.name}'])`,
506
+ matches: `json['${context.name}'] is String`
507
+ };
508
+ case "binary":
509
+ case "byte":
510
+ return {
511
+ content: "",
512
+ use: "Uint8List",
513
+ toJson: `this.${camelcase(context.name)}`,
514
+ simple: true,
515
+ fromJson: `json['${context.name}']`,
516
+ matches: `json['${context.name}'] is Uint8List`
517
+ };
518
+ default:
519
+ return {
520
+ use: "String",
521
+ content: "",
522
+ simple: true,
523
+ toJson: `this.${camelcase(context.name)}`,
524
+ fromJson: `json['${context.name}'] as String`,
525
+ matches: `json['${context.name}'] is String`
526
+ };
527
+ }
528
+ }
529
+ /**
530
+ * Handle number/integer types with formats
531
+ */
532
+ number(schema, context) {
533
+ const type = schema.type === "integer" ? "int" : "double";
534
+ if (schema.format === "int64") {
535
+ return {
536
+ content: "",
537
+ use: "int",
538
+ simple: true,
539
+ toJson: `this.${camelcase(context.name)}`,
540
+ fromJson: `json['${context.name}']`,
541
+ matches: `json['${context.name}'] is int`
542
+ };
543
+ }
544
+ return {
545
+ content: "",
546
+ simple: true,
547
+ use: type,
548
+ toJson: `this.${camelcase(context.name)}`,
549
+ fromJson: `json['${context.name}']`,
550
+ matches: `json['${context.name}'] is int`
551
+ };
552
+ }
553
+ handle(className, schema, required = true, context = {}) {
554
+ if (isRef(schema)) {
555
+ return this.#ref(schema.$ref, required, context);
556
+ }
557
+ if (schema.allOf && Array.isArray(schema.allOf)) {
558
+ return this.#allOf(className, schema.allOf, context);
559
+ }
560
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
561
+ return this.anyOf(className, schema.anyOf, context);
562
+ }
563
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
564
+ return this.#oneOf(className, schema.oneOf, context);
565
+ }
566
+ if (schema.enum && Array.isArray(schema.enum)) {
567
+ return this.#enum(className, schema, context);
568
+ }
569
+ const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
570
+ let nullable = false;
571
+ if ("nullable" in schema && schema.nullable) {
572
+ nullable = true;
573
+ } else if (schema.default === null) {
574
+ nullable = true;
575
+ } else if (types.includes("null")) {
576
+ nullable = true;
577
+ }
578
+ if (!types.length) {
579
+ if ("properties" in schema) {
580
+ return this.#object(className, schema, context);
581
+ }
582
+ if ("items" in schema) {
583
+ return this.#array(className, schema, true, context);
584
+ }
585
+ return {
586
+ content: "",
587
+ use: "dynamic",
588
+ toJson: `${camelcase(context.name)}`,
589
+ fromJson: `json['${context.name}']`
590
+ };
591
+ }
592
+ return this.primitive(
593
+ className,
594
+ types[0],
595
+ schema,
596
+ { ...context, nullable },
597
+ required
598
+ );
599
+ }
600
+ };
7
601
 
8
602
  // packages/dart/src/lib/interceptors.txt
9
603
  var interceptors_default = "abstract class Interceptor {\n RequestConfig before(RequestConfig config);\n void after();\n}\n\nclass BaseUrlInterceptor extends Interceptor {\n final String Function() getBaseUrl;\n BaseUrlInterceptor(this.getBaseUrl);\n\n @override\n RequestConfig before(RequestConfig config) {\n final baseUrl = getBaseUrl();\n if (config.url.scheme.isEmpty) {\n config.url = Uri.parse(baseUrl + config.url.toString());\n }\n return config;\n }\n\n @override\n void after() {\n //\n }\n}\n\nclass RequestConfig {\n final String method;\n Uri url;\n final Map<String, String> headers;\n RequestConfig({required this.method, required this.url, required this.headers});\n}\n";
10
604
 
11
605
  // packages/dart/src/lib/generate.ts
606
+ function tuneSpec(spec, schemas, refs) {
607
+ for (const [name, schema] of Object.entries(schemas)) {
608
+ if (isRef2(schema))
609
+ continue;
610
+ if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length) {
611
+ const schemas2 = schema.allOf;
612
+ const refs2 = schemas2.filter(isRef2);
613
+ const nonRefs = schemas2.filter(notRef2);
614
+ if (nonRefs.some((it) => it.type && it.type !== "object")) {
615
+ assert2(false, `allOf ${name} must be an object`);
616
+ }
617
+ const objectSchema = merge2(
618
+ {},
619
+ ...nonRefs,
620
+ ...refs2.map((ref) => followRef2(spec, ref.$ref))
621
+ );
622
+ delete objectSchema.allOf;
623
+ delete schema.allOf;
624
+ Object.assign(schema, objectSchema);
625
+ }
626
+ if (schema.type === "object") {
627
+ if (!isEmpty2(schema.oneOf)) {
628
+ for (const oneOfIdx in schema.oneOf) {
629
+ const oneOf = schema.oneOf[oneOfIdx];
630
+ if (isRef2(oneOf))
631
+ continue;
632
+ if (!isEmpty2(oneOf.required) && schema.properties) {
633
+ schema.oneOf[oneOfIdx] = schema.properties[oneOf.required[0]];
634
+ }
635
+ }
636
+ delete schema.type;
637
+ tuneSpec(spec, schemas, refs);
638
+ continue;
639
+ }
640
+ schema.properties ??= {};
641
+ for (const [propName, value] of Object.entries(schema.properties)) {
642
+ if (isRef2(value))
643
+ continue;
644
+ const refName = pascalcase2(`${name} ${propName.replace("[]", "")}`);
645
+ refs.push({ name: refName, value });
646
+ schema.properties[propName] = {
647
+ $ref: `#/components/schemas/${refName}`
648
+ };
649
+ const props = Object.fromEntries(
650
+ Object.entries(value.properties ?? {}).map(([key, value2]) => {
651
+ return [pascalcase2(`${refName} ${key}`), value2];
652
+ })
653
+ );
654
+ tuneSpec(spec, props, refs);
655
+ }
656
+ } else if (schema.type === "array") {
657
+ if (isRef2(schema.items))
658
+ continue;
659
+ const refName = name;
660
+ refs.push({ name: refName, value: schema.items ?? {} });
661
+ schema.items = {
662
+ $ref: `#/components/schemas/${refName}`
663
+ };
664
+ }
665
+ }
666
+ }
12
667
  async function generate(spec, settings) {
13
668
  const output = settings.mode === "full" ? join(settings.output, "src") : settings.output;
14
669
  const groups = {};
670
+ spec.components ??= {};
671
+ spec.components.schemas ??= {};
15
672
  forEachOperation({ spec }, (entry, operation) => {
16
- const [groupName] = operation.tags ?? [];
17
- const group = groups[groupName] ?? (groups[groupName] = {
673
+ console.log(`Processing ${entry.method} ${entry.path}`);
674
+ const group = groups[entry.groupName] ?? (groups[entry.groupName] = {
18
675
  methods: [],
19
- use: `final ${groupName} = new ${pascalcase(groupName)}();`
676
+ use: `final ${entry.groupName} = new ${pascalcase2(entry.groupName)}();`
20
677
  });
21
678
  group.methods.push(`
22
- Future<http.Response> ${camelcase(operation.operationId)}() async {
679
+ Future<http.Response> ${camelcase2(operation.operationId)}() async {
23
680
  final stream = await this.dispatcher.dispatch(RequestConfig(
24
681
  method: '${entry.method}',
25
682
  url: Uri.parse('${entry.path}'),
@@ -30,19 +687,36 @@ async function generate(spec, settings) {
30
687
  }
31
688
  `);
32
689
  });
690
+ const newRefs = [];
691
+ tuneSpec(spec, spec.components.schemas, newRefs);
692
+ for (const ref of newRefs) {
693
+ spec.components.schemas[ref.name] = ref.value;
694
+ }
695
+ await writeFile(
696
+ join(process.cwd(), "openai.json"),
697
+ JSON.stringify(spec, null, 2)
698
+ );
699
+ const models = Object.entries(spec.components.schemas).reduce((acc, [name, schema]) => {
700
+ const serializer = new DartSerializer(spec, (name2, content) => {
701
+ acc[`models/${snakecase2(name2)}.dart`] = `import 'dart:typed_data'; import './index.dart';
702
+
703
+ ${content}`;
704
+ });
705
+ serializer.handle(pascalcase2(name), schema);
706
+ return acc;
707
+ }, {});
33
708
  const clazzez = Object.entries(groups).reduce(
34
709
  (acc, [name, { methods }]) => {
35
710
  return {
36
711
  ...acc,
37
- [`api/${spinalcase(name)}.dart`]: `
38
- import 'dart:convert';
712
+ [`api/${snakecase2(name)}.dart`]: `
39
713
  import 'package:http/http.dart' as http;
40
714
  import '../interceptors.dart';
41
715
  import '../http.dart';
42
716
 
43
- class ${pascalcase(name)} {
717
+ class ${pascalcase2(name)} {
44
718
  final Dispatcher dispatcher;
45
- ${pascalcase(name)}(this.dispatcher);
719
+ ${pascalcase2(name)}(this.dispatcher);
46
720
  ${methods.join("\n")}
47
721
  }
48
722
  `
@@ -50,21 +724,20 @@ import '../http.dart';
50
724
  },
51
725
  {}
52
726
  );
53
- console.dir({ groups }, { depth: null });
54
727
  const client = `
728
+ ${Object.keys(groups).map((name) => `import './api/${snakecase2(name)}.dart';`).join("\n")}
55
729
  import './interceptors.dart';
56
730
  import './http.dart';
57
- ${Object.keys(groups).map((name) => `import './api/${spinalcase(name)}.dart';`).join("\n")}
58
731
 
59
732
  class Client {
60
733
  final Options options;
61
- ${Object.keys(groups).map((name) => `late final ${pascalcase(name)} ${camelcase(name)};`).join("\n")}
734
+ ${Object.keys(groups).map((name) => `late final ${pascalcase2(name)} ${camelcase2(name)};`).join("\n")}
62
735
 
63
736
  Client(this.options) {
64
737
  final interceptors = [new BaseUrlInterceptor(() => this.options.baseUrl)];
65
-
738
+ final dispatcher = new Dispatcher(interceptors);
66
739
  ${Object.keys(groups).map(
67
- (name) => `this.${camelcase(name)} = new ${pascalcase(name)}(new Dispatcher(interceptors));`
740
+ (name) => `this.${camelcase2(name)} = new ${pascalcase2(name)}(dispatcher);`
68
741
  ).join("\n")}
69
742
 
70
743
  }
@@ -84,10 +757,17 @@ class Options {
84
757
 
85
758
  `;
86
759
  await writeFiles(output, {
760
+ ...models
761
+ });
762
+ await writeFiles(output, {
763
+ "models/index.dart": await getFolderExportsV2(join(output, "models"), {
764
+ exportSyntax: "export",
765
+ extensions: ["dart"]
766
+ }),
87
767
  "index.dart": client,
88
768
  "interceptors.dart": interceptors_default,
89
769
  "http.dart": `
90
- import 'interceptors.dart';
770
+ import 'interceptors.dart';
91
771
  import 'package:http/http.dart' as http;
92
772
 
93
773
  class Dispatcher {
@@ -108,7 +788,9 @@ class Dispatcher {
108
788
  ...clazzez
109
789
  // 'index.dart': await getFolderExports(output, settings.useTsExtension),
110
790
  });
111
- execSync("dart format .", { cwd: output });
791
+ await settings.formatCode?.({
792
+ output
793
+ });
112
794
  }
113
795
  export {
114
796
  generate
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/lib/generate.ts", "../src/lib/interceptors.txt"],
4
- "sourcesContent": ["import { execSync } from 'node:child_process';\nimport { join } from 'node:path';\nimport { npmRunPathEnv } from 'npm-run-path';\nimport type { OpenAPIObject } from 'openapi3-ts/oas31';\nimport { camelcase, pascalcase, spinalcase } from 'stringcase';\n\n\n\nimport { forEachOperation, writeFiles } from '@sdk-it/core';\n\n\n\nimport interceptors from './interceptors.txt';\n\n\n\n\n\nexport async function generate(\n spec: OpenAPIObject,\n settings: {\n output: string;\n name?: string;\n /**\n * full: generate a full project including package.json and tsconfig.json. useful for monorepo/workspaces\n * minimal: generate only the client sdk\n */\n mode?: 'full' | 'minimal';\n formatCode?: (options: {\n output: string;\n env: ReturnType<typeof npmRunPathEnv>;\n }) => void | Promise<void>;\n },\n) {\n const output =\n settings.mode === 'full' ? join(settings.output, 'src') : settings.output;\n const groups: Record<\n string,\n {\n use: string;\n methods: string[];\n }\n > = {};\n forEachOperation({ spec }, (entry, operation) => {\n const [groupName] = operation.tags ?? [];\n const group =\n groups[groupName] ??\n (groups[groupName] = {\n methods: [],\n use: `final ${groupName} = new ${pascalcase(groupName)}();`,\n });\n group.methods.push(`\n Future<http.Response> ${camelcase(operation.operationId)}() async {\n final stream = await this.dispatcher.dispatch(RequestConfig(\n method: '${entry.method}',\n url: Uri.parse('${entry.path}'),\n headers: {},\n ));\n final response = await http.Response.fromStream(stream);\n return response;\n }\n `);\n });\n\n const clazzez = Object.entries(groups).reduce<Record<string, string>>(\n (acc, [name, { methods }]) => {\n return {\n ...acc,\n [`api/${spinalcase(name)}.dart`]: `\n import 'dart:convert';\nimport 'package:http/http.dart' as http;\nimport '../interceptors.dart';\nimport '../http.dart';\n\n class ${pascalcase(name)} {\n final Dispatcher dispatcher;\n ${pascalcase(name)}(this.dispatcher);\n ${methods.join('\\n')}\n }\n `,\n };\n },\n {},\n );\n\n console.dir({ groups }, { depth: null });\n\n const client = `\nimport './interceptors.dart';\nimport './http.dart';\n${Object.keys(groups)\n .map((name) => `import './api/${spinalcase(name)}.dart';`)\n .join('\\n')}\n\n class Client {\n final Options options;\n${Object.keys(groups)\n .map((name) => `late final ${pascalcase(name)} ${camelcase(name)};`)\n .join('\\n')}\n\n Client(this.options) {\n final interceptors = [new BaseUrlInterceptor(() => this.options.baseUrl)];\n\n ${Object.keys(groups)\n .map(\n (name) =>\n `this.${camelcase(name)} = new ${pascalcase(name)}(new Dispatcher(interceptors));`,\n )\n .join('\\n')}\n\n }\n\n void setOptions({String? baseUrl}) {\n if (baseUrl != null) {\n options.baseUrl = baseUrl;\n }\n }\n }\n\n\nclass Options {\n String baseUrl;\n Options({required this.baseUrl});\n}\n\n `;\n await writeFiles(output, {\n 'index.dart': client,\n 'interceptors.dart': interceptors,\n 'http.dart': `\n import 'interceptors.dart';\nimport 'package:http/http.dart' as http;\n\nclass Dispatcher {\n final List<Interceptor> interceptors;\n\n Dispatcher(this.interceptors);\n\n Future<http.StreamedResponse> dispatch(RequestConfig config) {\n final modifedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n final request = http.Request(modifedConfig.method, modifedConfig.url);\n return request.send();\n }\n}\n`,\n ...clazzez,\n // 'index.dart': await getFolderExports(output, settings.useTsExtension),\n });\n\n execSync('dart format .', { cwd: output });\n}", "abstract class Interceptor {\n RequestConfig before(RequestConfig config);\n void after();\n}\n\nclass BaseUrlInterceptor extends Interceptor {\n final String Function() getBaseUrl;\n BaseUrlInterceptor(this.getBaseUrl);\n\n @override\n RequestConfig before(RequestConfig config) {\n final baseUrl = getBaseUrl();\n if (config.url.scheme.isEmpty) {\n config.url = Uri.parse(baseUrl + config.url.toString());\n }\n return config;\n }\n\n @override\n void after() {\n //\n }\n}\n\nclass RequestConfig {\n final String method;\n Uri url;\n final Map<String, String> headers;\n RequestConfig({required this.method, required this.url, required this.headers});\n}\n"],
5
- "mappings": ";AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,OAA8B;AAE9B,SAAS,WAAW,YAAY,kBAAkB;AAIlD,SAAS,kBAAkB,kBAAkB;;;ACR7C;;;ADkBA,eAAsB,SACpB,MACA,UAaA;AACA,QAAM,SACJ,SAAS,SAAS,SAAS,KAAK,SAAS,QAAQ,KAAK,IAAI,SAAS;AACrE,QAAM,SAMF,CAAC;AACL,mBAAiB,EAAE,KAAK,GAAG,CAAC,OAAO,cAAc;AAC/C,UAAM,CAAC,SAAS,IAAI,UAAU,QAAQ,CAAC;AACvC,UAAM,QACJ,OAAO,SAAS,MACf,OAAO,SAAS,IAAI;AAAA,MACnB,SAAS,CAAC;AAAA,MACV,KAAK,SAAS,SAAS,UAAU,WAAW,SAAS,CAAC;AAAA,IACxD;AACF,UAAM,QAAQ,KAAK;AAAA,gCACS,UAAU,UAAU,WAAW,CAAC;AAAA;AAAA,uBAEzC,MAAM,MAAM;AAAA,8BACL,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAMnC;AAAA,EACH,CAAC;AAED,QAAM,UAAU,OAAO,QAAQ,MAAM,EAAE;AAAA,IACrC,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM;AAC5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,CAAC,OAAO,WAAW,IAAI,CAAC,OAAO,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAM9B,WAAW,IAAI,CAAC;AAAA;AAAA,QAEpB,WAAW,IAAI,CAAC;AAAA,QAChB,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,MAGpB;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,UAAQ,IAAI,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK,CAAC;AAEvC,QAAM,SAAS;AAAA;AAAA;AAAA,EAGf,OAAO,KAAK,MAAM,EACjB,IAAI,CAAC,SAAS,iBAAiB,WAAW,IAAI,CAAC,SAAS,EACxD,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,EAIX,OAAO,KAAK,MAAM,EACjB,IAAI,CAAC,SAAS,cAAc,WAAW,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,GAAG,EAClE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAKP,OAAO,KAAK,MAAM,EACjB;AAAA,IACC,CAAC,SACC,QAAQ,UAAU,IAAI,CAAC,UAAU,WAAW,IAAI,CAAC;AAAA,EACrD,EACC,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBf,QAAM,WAAW,QAAQ;AAAA,IACvB,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmBb,GAAG;AAAA;AAAA,EAEL,CAAC;AAED,WAAS,iBAAiB,EAAE,KAAK,OAAO,CAAC;AAC3C;",
6
- "names": []
3
+ "sources": ["../src/lib/generate.ts", "../src/lib/dart-emitter.ts", "../src/lib/interceptors.txt"],
4
+ "sourcesContent": ["import { merge } from 'lodash-es';\nimport assert from 'node:assert';\nimport { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type {\n OpenAPIObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase } from 'stringcase';\n\nimport {\n followRef,\n forEachOperation,\n getFolderExportsV2,\n isEmpty,\n isRef,\n notRef,\n pascalcase,\n snakecase,\n writeFiles,\n} from '@sdk-it/core';\n\nimport { DartSerializer } from './dart-emitter.ts';\nimport interceptors from './interceptors.txt';\n\nfunction tuneSpec(\n spec: OpenAPIObject,\n schemas: Record<string, SchemaObject | ReferenceObject>,\n refs: { name: string; value: SchemaObject }[],\n) {\n for (const [name, schema] of Object.entries(schemas)) {\n if (isRef(schema)) continue;\n\n if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length) {\n const schemas = schema.allOf;\n const refs = schemas.filter(isRef);\n const nonRefs = schemas.filter(notRef);\n if (nonRefs.some((it) => it.type && it.type !== 'object')) {\n assert(false, `allOf ${name} must be an object`);\n }\n const objectSchema = merge(\n {},\n ...nonRefs,\n ...refs.map((ref) => followRef(spec, ref.$ref)),\n );\n delete objectSchema.allOf;\n delete schema.allOf;\n Object.assign(schema, objectSchema);\n }\n\n if (schema.type === 'object') {\n if (!isEmpty(schema.oneOf)) {\n for (const oneOfIdx in schema.oneOf) {\n const oneOf = schema.oneOf[oneOfIdx];\n if (isRef(oneOf)) continue;\n if (!isEmpty(oneOf.required) && schema.properties) {\n schema.oneOf[oneOfIdx] = schema.properties[oneOf.required[0]];\n }\n }\n\n delete schema.type;\n tuneSpec(spec, schemas, refs);\n continue;\n }\n\n schema.properties ??= {};\n\n for (const [propName, value] of Object.entries(schema.properties)) {\n if (isRef(value)) continue;\n const refName = pascalcase(`${name} ${propName.replace('[]', '')}`);\n refs.push({ name: refName, value });\n schema.properties[propName] = {\n $ref: `#/components/schemas/${refName}`,\n };\n const props = Object.fromEntries(\n Object.entries(value.properties ?? {}).map(([key, value]) => {\n return [pascalcase(`${refName} ${key}`), value];\n }),\n );\n tuneSpec(spec, props, refs);\n // if (value.oneOf && Array.isArray(value.oneOf) && value.oneOf.length) {\n // for (const oneOfIdx in value.oneOf) {\n // const oneOf = value.oneOf[oneOfIdx];\n // if (isRef(oneOf)) continue;\n // if (oneOf.type === 'string') {\n // console.log(refName);\n // // const refName= pascalcase(`${name} ${key} ${oneOfIdx}`);\n // // schema.oneOf[oneOfIdx] = {\n // // $ref: `#/components/schemas/${refName}`,\n // // };\n // }\n // }\n // }\n }\n } else if (schema.type === 'array') {\n if (isRef(schema.items)) continue;\n const refName = name;\n refs.push({ name: refName, value: schema.items ?? {} });\n schema.items = {\n $ref: `#/components/schemas/${refName}`,\n };\n }\n }\n}\nexport async function generate(\n spec: OpenAPIObject,\n settings: {\n output: string;\n name?: string;\n /**\n * full: generate a full project including package.json and tsconfig.json. useful for monorepo/workspaces\n * minimal: generate only the client sdk\n */\n mode?: 'full' | 'minimal';\n formatCode?: (options: { output: string }) => void | Promise<void>;\n },\n) {\n const output =\n settings.mode === 'full' ? join(settings.output, 'src') : settings.output;\n const groups: Record<\n string,\n {\n use: string;\n methods: string[];\n }\n > = {};\n spec.components ??= {};\n spec.components.schemas ??= {};\n\n forEachOperation({ spec }, (entry, operation) => {\n console.log(`Processing ${entry.method} ${entry.path}`);\n const group =\n groups[entry.groupName] ??\n (groups[entry.groupName] = {\n methods: [],\n use: `final ${entry.groupName} = new ${pascalcase(entry.groupName)}();`,\n });\n group.methods.push(`\n Future<http.Response> ${camelcase(operation.operationId)}() async {\n final stream = await this.dispatcher.dispatch(RequestConfig(\n method: '${entry.method}',\n url: Uri.parse('${entry.path}'),\n headers: {},\n ));\n final response = await http.Response.fromStream(stream);\n return response;\n }\n `);\n });\n\n const newRefs: { name: string; value: SchemaObject }[] = [];\n tuneSpec(spec, spec.components.schemas, newRefs);\n for (const ref of newRefs) {\n spec.components.schemas[ref.name] = ref.value;\n }\n await writeFile(\n join(process.cwd(), 'openai.json'),\n JSON.stringify(spec, null, 2),\n );\n\n const models = Object.entries(spec.components.schemas).reduce<\n Record<string, string>\n >((acc, [name, schema]) => {\n const serializer = new DartSerializer(spec, (name, content) => {\n acc[`models/${snakecase(name)}.dart`] =\n `import 'dart:typed_data'; import './index.dart';\\n\\n${content}`;\n });\n serializer.handle(pascalcase(name), schema);\n return acc;\n }, {});\n\n const clazzez = Object.entries(groups).reduce<Record<string, string>>(\n (acc, [name, { methods }]) => {\n return {\n ...acc,\n [`api/${snakecase(name)}.dart`]: `\nimport 'package:http/http.dart' as http;\nimport '../interceptors.dart';\nimport '../http.dart';\n\n class ${pascalcase(name)} {\n final Dispatcher dispatcher;\n ${pascalcase(name)}(this.dispatcher);\n ${methods.join('\\n')}\n }\n `,\n };\n },\n {},\n );\n\n const client = `\n ${Object.keys(groups)\n .map((name) => `import './api/${snakecase(name)}.dart';`)\n .join('\\n')}\nimport './interceptors.dart';\nimport './http.dart';\n\n class Client {\n final Options options;\n${Object.keys(groups)\n .map((name) => `late final ${pascalcase(name)} ${camelcase(name)};`)\n .join('\\n')}\n\n Client(this.options) {\n final interceptors = [new BaseUrlInterceptor(() => this.options.baseUrl)];\n final dispatcher = new Dispatcher(interceptors);\n ${Object.keys(groups)\n .map(\n (name) =>\n `this.${camelcase(name)} = new ${pascalcase(name)}(dispatcher);`,\n )\n .join('\\n')}\n\n }\n\n void setOptions({String? baseUrl}) {\n if (baseUrl != null) {\n options.baseUrl = baseUrl;\n }\n }\n }\n\n\nclass Options {\n String baseUrl;\n Options({required this.baseUrl});\n}\n\n `;\n await writeFiles(output, {\n ...models,\n });\n\n await writeFiles(output, {\n 'models/index.dart': await getFolderExportsV2(join(output, 'models'), {\n exportSyntax: 'export',\n extensions: ['dart'],\n }),\n 'index.dart': client,\n 'interceptors.dart': interceptors,\n 'http.dart': `\nimport 'interceptors.dart';\nimport 'package:http/http.dart' as http;\n\nclass Dispatcher {\n final List<Interceptor> interceptors;\n\n Dispatcher(this.interceptors);\n\n Future<http.StreamedResponse> dispatch(RequestConfig config) {\n final modifedConfig = interceptors.fold(\n config,\n (acc, interceptor) => interceptor.before(acc),\n );\n final request = http.Request(modifedConfig.method, modifedConfig.url);\n return request.send();\n }\n}\n`,\n ...clazzez,\n // 'index.dart': await getFolderExports(output, settings.useTsExtension),\n });\n\n await settings.formatCode?.({\n output: output,\n });\n}\n", "import { merge } from 'lodash-es';\nimport assert from 'node:assert';\nimport type {\n OpenAPIObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase, snakecase } from 'stringcase';\n\nimport {\n cleanRef,\n followRef,\n isEmpty,\n isRef,\n notRef,\n parseRef,\n pascalcase,\n} from '@sdk-it/core';\n\nconst formatName = (it: any): string => {\n const startsWithDigitPattern = /^\\d/;\n // 1. Handle numbers\n if (typeof it === 'number') {\n return `$${it}`;\n }\n\n // 2. Handle the specific string 'default'\n if (it === 'default') {\n return '$default';\n }\n\n // 3. Handle other strings\n if (typeof it === 'string') {\n // 3a. Check if the string starts with a digit FIRST\n if (startsWithDigitPattern.test(it)) {\n return `$${it}`; // Prefix with $ and return immediately\n }\n\n // 3b. If not starting with a digit, handle brackets and snake_case\n let nameToFormat = it;\n\n // Remove a single leading '[' if present\n if (nameToFormat.startsWith('[')) {\n nameToFormat = nameToFormat.slice(1);\n }\n\n // Remove a single trailing ']' if present\n if (nameToFormat.endsWith(']')) {\n nameToFormat = nameToFormat.slice(0, -1);\n }\n\n // Apply snakecase to the (potentially modified) string\n return snakecase(nameToFormat);\n }\n\n // 4. Fallback for any other types (e.g., null, undefined, objects)\n // Convert to string first, then apply snakecase\n return snakecase(String(it));\n};\n\ntype Context = Record<string, any>;\ntype Serialized = {\n use: string;\n toJson: string;\n matches?: string;\n fromJson: string;\n type?: string;\n content: string;\n simple?: boolean;\n};\ntype Emit = (name: string, content: string) => void;\n/**\n * Convert an OpenAPI (JSON Schema style) object into Dart classes\n */\nexport class DartSerializer {\n #spec: OpenAPIObject;\n #emit: Emit;\n\n constructor(spec: OpenAPIObject, emit: Emit) {\n this.#spec = spec;\n this.#emit = emit;\n }\n\n #getRefUsage(schemaName: string, list: string[] = []): string[] {\n this.#spec.components ??= {};\n this.#spec.components.schemas ??= {};\n this.#spec.components.responses ??= {};\n\n const checkSchema = (schema: SchemaObject | ReferenceObject): boolean => {\n if (isRef(schema)) {\n const { model } = parseRef(schema.$ref);\n return model === schemaName;\n }\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n return (schema.oneOf as Array<SchemaObject | ReferenceObject>).some(\n (subSchema) => checkSchema(subSchema),\n );\n }\n if (\n schema.type === 'array' &&\n schema.items &&\n notRef(schema.items) &&\n schema.items.oneOf\n ) {\n return checkSchema(schema.items);\n }\n return false;\n };\n\n for (const [key, value] of Object.entries(this.#spec.components.schemas)) {\n if (checkSchema(value)) {\n list.push(key);\n }\n }\n\n return list;\n }\n\n #object(\n className: string,\n schema: SchemaObject,\n context: Context,\n ): Serialized {\n if (schema.additionalProperties) {\n return {\n content: '',\n use: 'Map<String, dynamic>',\n toJson: `this.${camelcase(context.name)}`,\n fromJson: `json['${camelcase(context.name)}']`,\n matches: `json['${camelcase(context.name)}'] is Map<String, dynamic>`,\n };\n }\n if (isEmpty(schema.properties)) {\n if (context.noEmit !== true) {\n this.#emit(\n className,\n `class ${className} {\n const ${className}(); // Add const constructor\n\n factory ${className}.fromJson(Map<String, dynamic> json) {\n return const ${className}();\n }\n\n Map<String, dynamic> toJson() => {};\n\n /// Determines if a given map can be parsed into an instance of this class.\n /// Returns true for any map since this class has no properties.\n static bool matches(Map<String, dynamic> json) {\n return true; // Any map is fine for an empty object\n }\n}`,\n );\n }\n return {\n content: '',\n use: className,\n toJson: `${this.#safe(context.name as string, context.required)}`,\n fromJson: `${className}.fromJson(json['${context.name}'])`,\n matches: `${className}.matches(json['${context.name}'])`,\n };\n }\n\n const props: string[] = [];\n const toJsonProperties: string[] = [];\n const constructorParams: string[] = [];\n const fromJsonParams: string[] = [];\n const matches: string[] = [];\n\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n const propName = key.replace('[]', '');\n const required = (schema.required ?? []).includes(key);\n const typeStr = this.handle(className, propSchema, required, {\n name: propName,\n required,\n propName: [className, propName].filter(Boolean).join('_'),\n });\n const nullable = !required;\n const nullableSuffix = nullable ? '?' : '';\n props.push(\n `final ${typeStr.use}${nullableSuffix} ${camelcase(propName)};`,\n );\n fromJsonParams.push(`${camelcase(propName)}: ${typeStr.fromJson}`);\n toJsonProperties.push(`'${propName}': ${typeStr.toJson}`);\n constructorParams.push(\n `${required ? 'required ' : ''}this.${camelcase(propName)},`,\n );\n if (required) {\n matches.push(`(\n json.containsKey('${camelcase(propName)}')\n ? ${nullable ? `json['${propName}'] == null` : `json['${propName}'] != null`} && ${typeStr.matches}\n : false)`);\n } else {\n matches.push(`(\n json.containsKey('${camelcase(propName)}')\n ? ${nullable ? `json['${propName}'] == null` : `json['${propName}'] != null`} || ${typeStr.matches}\n : true)`);\n }\n }\n\n const { mixins, withMixins } = this.#mixinise(className, context);\n const content = `class ${className} ${withMixins} {\n ${props.join('\\n')}\n ${!mixins.length ? 'const' : ''} ${className}({\n ${constructorParams.join('\\n')}})${mixins.length > 1 ? '' : `:super()`};\n factory ${className}.fromJson(Map<String, dynamic> json) {\nreturn ${className}(\\n${fromJsonParams.join(',\\n')});\n }\n Map<String, dynamic> toJson() => {\n${toJsonProperties.join(',\\n')}\n };\n static bool matches(Map<String, dynamic> json) {\nreturn ${matches.join(' && ')};\n }\n }`;\n if (context.noEmit !== true) {\n this.#emit(className, content);\n }\n const nullable = !context.required || context.nullable === true;\n return {\n use: className,\n content,\n toJson: `${this.#safe(context.name, context.required)}`,\n fromJson: `${className}.fromJson(json['${context.name}'])`,\n matches: `${className}.matches(json['${context.name}'])`,\n };\n }\n\n #safe(accces: string, required: boolean) {\n return required\n ? `this.${camelcase(accces)}.toJson()`\n : `this.${camelcase(accces)} != null ? this.${camelcase(accces)}!.toJson() : null`;\n }\n\n #array(\n className: string,\n schema: SchemaObject,\n required = false,\n context: Context,\n ): Serialized {\n const { items } = schema;\n if (!items) {\n return {\n content: '',\n use: 'List<dynamic>',\n toJson: '',\n fromJson: '',\n matches: '',\n };\n }\n\n const itemsType = this.handle(className, items, true, context);\n return {\n content: '',\n use: `List<${itemsType.use}>`,\n fromJson: required\n ? `(json['${context.name}'] as List<${itemsType.simple ? itemsType.use : 'dynamic'}>).map((it) => ${itemsType.simple ? 'it' : `${itemsType.use}.fromJson(it)`}).toList()`\n : `json['${context.name}'] != null ? (json['${context.name}'] as List).map((it) => ${itemsType.fromJson}).toList() : null`,\n toJson: `${context.required ? `this.${camelcase(context.name)}${itemsType.simple ? '' : '.map((it) => it.toJson()).toList()'}` : `this.${camelcase(context.name)}!= null? this.${camelcase(context.name)}${itemsType.simple ? '' : '!.map((it) => it.toJson()).toList()'} : null`}`,\n matches: `json['${camelcase(context.name)}'].every((it) => ${itemsType.matches})`,\n };\n }\n\n /**\n * Convert a basic type to Dart\n */\n primitive(\n className: string,\n type: string,\n schema: SchemaObject,\n context: Record<string, unknown>,\n required = false,\n ): Serialized {\n switch (type) {\n case 'string':\n return this.#string(schema, context);\n case 'number':\n case 'integer':\n return this.number(schema, context);\n case 'boolean':\n return {\n content: '',\n use: 'bool',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n matches: `json['${context.name}'] is bool`,\n };\n case 'object':\n return this.#object(className, schema, context);\n case 'array':\n return this.#array(className, schema, required, context);\n case 'null':\n return {\n content: '',\n use: 'Null',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n };\n default:\n // Unknown type -> fallback\n return {\n content: '',\n use: 'dynamic',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n };\n }\n }\n\n #ref($ref: string, required: boolean, context: Context): Serialized {\n const schemaName = cleanRef($ref).split('/').pop()!;\n const result = this.handle(\n context.alias || schemaName,\n followRef(this.#spec, $ref),\n required,\n {\n ...context,\n propName: schemaName,\n noEmit: !context.forceEmit,\n },\n );\n return result;\n }\n\n // fixme: this method should no longer be needed because the logic in it is being preprocessed before emitting begins\n #allOf(\n className: string,\n schemas: (SchemaObject | ReferenceObject)[],\n context: Context,\n ): Serialized {\n const name = pascalcase(context.propName || className); // className in case is top level\n\n const refs = schemas.filter(isRef);\n const nonRefs = schemas.filter(notRef);\n if (nonRefs.some((it) => it.type && it.type !== 'object')) {\n assert(false, `allOf ${name} must be an object`);\n }\n const objectSchema = merge(\n {},\n ...nonRefs,\n ...refs.map((ref) => followRef(this.#spec, ref.$ref)),\n );\n delete objectSchema.allOf;\n return this.handle(name, objectSchema, true, context);\n }\n\n anyOf(\n className: string,\n schemas: (SchemaObject | ReferenceObject)[],\n context: Record<string, unknown>,\n ): Serialized {\n // fixme: handle\n if (schemas.length === 0) {\n return {\n content: '',\n use: 'dynamic',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n };\n }\n\n return this.handle(className, schemas[0], true, context);\n }\n\n #mixinise(name: string, context: Context) {\n const mixins = this.#getRefUsage(name);\n if (context.mixin) {\n mixins.unshift(context.mixin);\n }\n const withMixins =\n mixins.length > 1\n ? ` with ${mixins.join(', ')}`\n : mixins.length === 1\n ? `extends ${mixins[0]}`\n : '';\n return {\n withMixins,\n mixins,\n };\n }\n\n #oneOf(\n className: string,\n schemas: (SchemaObject | ReferenceObject)[],\n context: Context,\n ): Serialized {\n const name = pascalcase(context.propName || className); // className in case is top level\n\n if (schemas.length === 0) {\n return {\n content: '',\n use: 'dynamic',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n };\n }\n const content: string[] = [];\n const patterns: { pattern: string; name: string }[] = [];\n // FIXME: if there is just one type then no need to add the discriminator\n const objects = schemas.filter(notRef).filter((it) => it.type === 'object');\n for (const schema of schemas) {\n if (isRef(schema)) {\n const refType = this.#ref(schema.$ref, true, context);\n patterns.push({\n pattern: `case ${refType.type || 'Map<String, dynamic>'} map when ${refType.use}.matches(map): return ${refType.use}.fromJson(map);`,\n name: refType.use,\n });\n } else if (schema.type === 'string') {\n // todo: make this into a schema with ref (preproccesing)\n content.push(`class ${name}Text with ${name} {\n final String value;\n ${name}Text(this.value);\n @override\n dynamic toJson() => value;\n static bool matches(dynamic value) {\n return value is String;\n }}\n `);\n patterns.push({\n pattern: `case String(): return ${name}Text(json);`,\n name: `${name}Text`,\n });\n } else if (schema.type === 'array') {\n // todo: make this into a schema with ref (preproccesing) with all varients types (integer, string)\n // todo: this can be abstracted so the varients somehow dynamic without having to replicate the same classes all the time\n const itemsType = this.handle(name, schema.items!, true, {\n ...context,\n noEmit: true,\n });\n content.push(`class ${name}List with ${name} {\n final List<${itemsType.use}> value;\n ${name}List(this.value);\n @override\n dynamic toJson() => value;\n static bool matches(dynamic value) {\n return value is List;\n }}`);\n patterns.push({\n pattern: `case List(): return ${name}List(List<${itemsType.use}>.from(json));`,\n name: `${name}List`,\n });\n }\n }\n if (objects.length) {\n // todo: take a look at CompoundFilterFilters at the end\n const candidates: Record<string, Set<string>> = {};\n for (const schema of objects) {\n if (schema.additionalProperties === true) {\n continue;\n }\n assert(\n schema.properties,\n `Schema ${name} has no properties which are required in oneOf in order to determine the discriminator.`,\n );\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n if (\n notRef(propSchema) &&\n propSchema.enum &&\n // fixme: the enum can have more than one value as long as it is not duplicated else where on the other schemas\n propSchema.enum.length === 1\n ) {\n candidates[propName] ??= new Set();\n candidates[propName].add(String(propSchema.enum[0]));\n }\n }\n }\n\n let discriminatorProp: string | undefined;\n\n for (const [name, values] of Object.entries(candidates)) {\n if (\n // make sure we pick the prop that exists on all objects\n values.size === objects.filter((it) => it.properties?.[name]).length\n ) {\n discriminatorProp = name;\n break;\n }\n }\n\n // if (objects.filter((it) => it.additionalProperties !== true).length) {\n // }\n // assert(discriminatorProp, `No discriminator property found in ${name}`);\n\n if (discriminatorProp) {\n for (const schema of objects) {\n const discriminatorValue: string = (\n (schema as SchemaObject).properties![\n discriminatorProp!\n ] as SchemaObject\n ).enum?.[0];\n\n const varientName = `${name}${pascalcase(discriminatorValue)}`;\n patterns.push({\n pattern: `case Map<String, dynamic> map when ${varientName}.matches(json): return ${varientName}.fromJson(map);`,\n name: varientName,\n });\n\n const objResult = this.#object(varientName, schema, {\n ...context,\n noEmit: true,\n mixin: name,\n });\n content.push(objResult.content);\n }\n }\n }\n\n const { mixins, withMixins } = this.#mixinise(name, context);\n content.unshift(`abstract ${mixins.length ? '' : 'mixin'} class ${name} ${withMixins} {\n dynamic toJson();\n ${\n patterns.length\n ? `static ${name} fromJson(dynamic json) {\n switch (json){\n ${patterns.map((it) => it.pattern).join('\\n')}\n default:\n throw ArgumentError(\"Invalid type for query property: \\${json}\");\n }\n }\n\n\n ${\n patterns.length\n ? ` static bool matches(dynamic value) {\n return ${patterns.map((it) => `value is ${it.name}`).join(' || ')};\n }`\n : ''\n }\n\n `\n : ''\n }\n }`);\n this.#emit(name, content.join('\\n'));\n\n return {\n content: content.join('\\n'),\n use: name,\n toJson: `${this.#safe(context.name as string, context.required)}`,\n fromJson: `${name}.fromJson(json['${context.name}'])`,\n matches: `${name}.matches(json['${context.name}'])`,\n };\n }\n\n #simple(type: string) {\n switch (type) {\n case 'string':\n return 'String';\n case 'number':\n return 'double';\n case 'integer':\n return 'int';\n case 'boolean':\n return 'bool';\n default:\n return 'dynamic';\n }\n }\n\n #enum(className: string, schema: SchemaObject, context: Context): Serialized {\n const name = context.propName || className; // className in case enum is top level\n const values = schema.enum as string[];\n const valType = this.#simple((schema.type as string) || 'string');\n // fixme: if enum have one value and cannot be null then use it as default value\n\n const { mixins, withMixins } = this.#mixinise(className, context);\n\n const content = `\n class _EnumValue implements ${pascalcase(name)} {\n final ${valType} value;\n const _EnumValue(this.value);\n @override\n toJson() {return this.value;}\n}\n abstract ${mixins.length ? '' : 'mixin'} class ${pascalcase(name)} ${withMixins} {\n ${values.map((it) => `static const _EnumValue ${formatName(it)} = _EnumValue(${typeof it === 'number' ? it : `'${it}'`});`).join('\\n')}\n dynamic toJson();\n\n static _EnumValue fromJson(${valType} value) {\n switch (value) {\n${values\n .map(\n (it) =>\n `case ${typeof it === 'number' ? it : `'${it}'`}: return ${formatName(it)};`,\n )\n .join('\\n')}\ndefault:\n throw ArgumentError.value(value, \"value\", \"No enum value with that name\");\n }\n }\n\n static bool matches(${valType} value) {\n try {\nfromJson(value);\nreturn true;\n } catch (error) {\nreturn false;\n }\n }\n\n }`;\n if (context.noEmit !== true) {\n this.#emit(name, content);\n }\n return {\n type: Array.isArray(schema.type)\n ? this.#simple(schema.type[0])\n : schema.type\n ? this.#simple(schema.type)\n : undefined,\n content: content,\n use: pascalcase(name),\n toJson: `${context.required ? `this.${camelcase(context.name)}.toJson()` : `this.${camelcase(context.name)} != null ? this.${camelcase(context.name)}!.toJson() : null`}`,\n fromJson: `${pascalcase(name)}.fromJson(json['${context.name}'])`,\n matches: `${pascalcase(name)}.matches(json['${context.name}'])`,\n };\n }\n\n /**\n * Handle string type with formats\n */\n #string(schema: SchemaObject, context: Context): Serialized {\n switch (schema.format) {\n case 'date-time':\n case 'datetime':\n case 'date':\n return {\n content: '',\n use: 'DateTime',\n simple: true,\n toJson: `this.${camelcase(context.name)}.toIso8601String()`,\n fromJson: `DateTime.parse(json['${context.name}'])`,\n matches: `json['${context.name}'] is String`,\n };\n case 'binary':\n case 'byte':\n return {\n content: '',\n use: 'Uint8List',\n toJson: `this.${camelcase(context.name)}`,\n simple: true,\n fromJson: `json['${context.name}']`,\n matches: `json['${context.name}'] is Uint8List`,\n };\n default:\n return {\n use: 'String',\n content: '',\n simple: true,\n toJson: `this.${camelcase(context.name)}`,\n fromJson: `json['${context.name}'] as String`,\n matches: `json['${context.name}'] is String`,\n };\n }\n }\n\n /**\n * Handle number/integer types with formats\n */\n number(schema: SchemaObject, context: Context): Serialized {\n const type = schema.type === 'integer' ? 'int' : 'double';\n\n if (schema.format === 'int64') {\n return {\n content: '',\n use: 'int',\n simple: true,\n toJson: `this.${camelcase(context.name)}`,\n fromJson: `json['${context.name}']`,\n matches: `json['${context.name}'] is int`,\n };\n }\n\n return {\n content: '',\n simple: true,\n use: type,\n toJson: `this.${camelcase(context.name)}`,\n fromJson: `json['${context.name}']`,\n matches: `json['${context.name}'] is int`,\n };\n }\n\n handle(\n className: string,\n schema: SchemaObject | ReferenceObject,\n required = true,\n context: Context = {},\n ): Serialized {\n if (isRef(schema)) {\n return this.#ref(schema.$ref, required, context);\n }\n\n if (schema.allOf && Array.isArray(schema.allOf)) {\n return this.#allOf(className, schema.allOf, context);\n }\n\n if (schema.anyOf && Array.isArray(schema.anyOf)) {\n return this.anyOf(className, schema.anyOf, context);\n }\n\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n return this.#oneOf(className, schema.oneOf, context);\n }\n\n if (schema.enum && Array.isArray(schema.enum)) {\n return this.#enum(className, schema, context);\n }\n\n // Handle types\n const types = Array.isArray(schema.type)\n ? schema.type\n : schema.type\n ? [schema.type]\n : [];\n\n let nullable = false;\n if ('nullable' in schema && schema.nullable) {\n nullable = true;\n } else if (schema.default === null) {\n nullable = true;\n } else if (types.includes('null')) {\n nullable = true;\n }\n\n // If no explicit \"type\", fallback to dynamic\n if (!types.length) {\n // unless properties are defined then assume object\n if ('properties' in schema) {\n return this.#object(className, schema, context);\n }\n if ('items' in schema) {\n return this.#array(className, schema, true, context);\n }\n return {\n content: '',\n use: 'dynamic',\n toJson: `${camelcase(context.name as string)}`,\n fromJson: `json['${context.name}']`,\n };\n }\n\n return this.primitive(\n className,\n types[0],\n schema,\n { ...context, nullable },\n required,\n );\n }\n}\n", "abstract class Interceptor {\n RequestConfig before(RequestConfig config);\n void after();\n}\n\nclass BaseUrlInterceptor extends Interceptor {\n final String Function() getBaseUrl;\n BaseUrlInterceptor(this.getBaseUrl);\n\n @override\n RequestConfig before(RequestConfig config) {\n final baseUrl = getBaseUrl();\n if (config.url.scheme.isEmpty) {\n config.url = Uri.parse(baseUrl + config.url.toString());\n }\n return config;\n }\n\n @override\n void after() {\n //\n }\n}\n\nclass RequestConfig {\n final String method;\n Uri url;\n final Map<String, String> headers;\n RequestConfig({required this.method, required this.url, required this.headers});\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["merge", "assert", "camelcase", "followRef", "isEmpty", "isRef", "notRef", "pascalcase", "snakecase", "nullable", "name", "isRef", "schemas", "refs", "notRef", "assert", "merge", "followRef", "isEmpty", "pascalcase", "value", "camelcase", "name", "snakecase"]
7
7
  }
@@ -0,0 +1,31 @@
1
+ import type { OpenAPIObject, ReferenceObject, SchemaObject } from 'openapi3-ts/oas31';
2
+ type Context = Record<string, any>;
3
+ type Serialized = {
4
+ use: string;
5
+ toJson: string;
6
+ matches?: string;
7
+ fromJson: string;
8
+ type?: string;
9
+ content: string;
10
+ simple?: boolean;
11
+ };
12
+ type Emit = (name: string, content: string) => void;
13
+ /**
14
+ * Convert an OpenAPI (JSON Schema style) object into Dart classes
15
+ */
16
+ export declare class DartSerializer {
17
+ #private;
18
+ constructor(spec: OpenAPIObject, emit: Emit);
19
+ /**
20
+ * Convert a basic type to Dart
21
+ */
22
+ primitive(className: string, type: string, schema: SchemaObject, context: Record<string, unknown>, required?: boolean): Serialized;
23
+ anyOf(className: string, schemas: (SchemaObject | ReferenceObject)[], context: Record<string, unknown>): Serialized;
24
+ /**
25
+ * Handle number/integer types with formats
26
+ */
27
+ number(schema: SchemaObject, context: Context): Serialized;
28
+ handle(className: string, schema: SchemaObject | ReferenceObject, required?: boolean, context?: Context): Serialized;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=dart-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dart-emitter.d.ts","sourceRoot":"","sources":["../../src/lib/dart-emitter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACb,MAAM,mBAAmB,CAAC;AAsD3B,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACnC,KAAK,UAAU,GAAG;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AACF,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AACpD;;GAEG;AACH,qBAAa,cAAc;;gBAIb,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI;IAwL3C;;OAEG;IACH,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,UAAQ,GACf,UAAU;IA0Eb,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,YAAY,GAAG,eAAe,CAAC,EAAE,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,UAAU;IAoTb;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU;IAwB1D,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,eAAe,EACtC,QAAQ,UAAO,EACf,OAAO,GAAE,OAAY,GACpB,UAAU;CA8Dd"}
@@ -1,4 +1,3 @@
1
- import { npmRunPathEnv } from 'npm-run-path';
2
1
  import type { OpenAPIObject } from 'openapi3-ts/oas31';
3
2
  export declare function generate(spec: OpenAPIObject, settings: {
4
3
  output: string;
@@ -10,7 +9,6 @@ export declare function generate(spec: OpenAPIObject, settings: {
10
9
  mode?: 'full' | 'minimal';
11
10
  formatCode?: (options: {
12
11
  output: string;
13
- env: ReturnType<typeof npmRunPathEnv>;
14
12
  }) => void | Promise<void>;
15
13
  }): Promise<void>;
16
14
  //# sourceMappingURL=generate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/lib/generate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAevD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;KACvC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,iBAyHF"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/lib/generate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EAGd,MAAM,mBAAmB,CAAC;AAiG3B,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE,iBAwJF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdk-it/dart",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,6 +23,6 @@
23
23
  "dependencies": {
24
24
  "npm-run-path": "6.0.0",
25
25
  "openapi3-ts": "4.4.0",
26
- "@sdk-it/core": "0.15.0"
26
+ "@sdk-it/core": "0.16.0"
27
27
  }
28
28
  }