@arrirpc/codegen-dart 0.45.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.mjs ADDED
@@ -0,0 +1,1020 @@
1
+ import { execSync } from 'child_process';
2
+ import { writeFileSync } from 'fs';
3
+ import { defineClientGeneratorPlugin, unflattenProcedures, isRpcDefinition, isServiceDefinition, pascalCase, isSchemaFormProperties, isSchemaFormDiscriminator, isSchemaFormValues, isSchemaFormType, isSchemaFormElements, isSchemaFormEnum, isSchemaFormRef, camelCase } from '@arrirpc/codegen-utils';
4
+ import { a } from '@arrirpc/schema';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __publicField = (obj, key, value) => {
9
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10
+ return value;
11
+ };
12
+ function camelCaseWrapper(input) {
13
+ if (input.toUpperCase() === input) {
14
+ return camelCase(input, { normalize: true });
15
+ }
16
+ return camelCase(input);
17
+ }
18
+ const dartClientGenerator = defineClientGeneratorPlugin(
19
+ (options) => {
20
+ return {
21
+ generator: async (def) => {
22
+ if (!options.clientName) {
23
+ throw new Error(
24
+ 'Missing "clientName" cannot generate dart client'
25
+ );
26
+ }
27
+ if (!options.outputFile) {
28
+ throw new Error(
29
+ 'Missing "outputFile" cannot generate dart client'
30
+ );
31
+ }
32
+ const numProcedures = Object.keys(def.procedures).length;
33
+ if (numProcedures <= 0) {
34
+ console.warn(
35
+ "No procedures found in definition file. Dart client will not be generated"
36
+ );
37
+ }
38
+ const result = createDartClient(def, options);
39
+ writeFileSync(options.outputFile, result);
40
+ try {
41
+ execSync(`dart format ${options.outputFile}`);
42
+ } catch (err) {
43
+ console.error("Error formatting dart client", err);
44
+ }
45
+ },
46
+ options
47
+ };
48
+ }
49
+ );
50
+ class DartClientGenerator {
51
+ constructor() {
52
+ __publicField(this, "generatedModels", []);
53
+ }
54
+ }
55
+ function getAnnotations(metadata) {
56
+ const commentParts = [];
57
+ if (metadata?.description?.length) {
58
+ const parts = metadata.description.split("\n");
59
+ for (const part of parts) {
60
+ commentParts.push(`/// ${part}`);
61
+ }
62
+ }
63
+ if (metadata?.isDeprecated) {
64
+ commentParts.push("@deprecated");
65
+ }
66
+ if (commentParts.length === 0) {
67
+ return "";
68
+ }
69
+ return `${commentParts.join("\n")}
70
+ `;
71
+ }
72
+ function createDartClient(def, opts) {
73
+ const existingClassNames = [];
74
+ const clientVersion = def.info?.version ?? "";
75
+ const services = unflattenProcedures(def.procedures);
76
+ const rpcParts = [];
77
+ const serviceGetterParts = [];
78
+ const serviceParts = [];
79
+ const modelParts = [];
80
+ for (const key of Object.keys(services)) {
81
+ const item = services[key];
82
+ if (isRpcDefinition(item)) {
83
+ const rpc = dartRpcFromDefinition(key, item);
84
+ if (rpc) {
85
+ rpcParts.push(rpc);
86
+ }
87
+ continue;
88
+ }
89
+ if (isServiceDefinition(item)) {
90
+ const serviceName = pascalCase(`${opts.clientName}_${key}`);
91
+ const service = dartServiceFromDefinition(serviceName, item, {
92
+ versionNumber: clientVersion,
93
+ ...opts
94
+ });
95
+ serviceParts.push(service);
96
+ serviceGetterParts.push(`${serviceName}Service get ${key} {
97
+ return ${serviceName}Service(
98
+ httpClient: _httpClient,
99
+ baseUrl: _baseUrl,
100
+ headers: _headers,
101
+ );
102
+ }`);
103
+ }
104
+ }
105
+ for (const key of Object.keys(def.definitions)) {
106
+ const item = def.definitions[key];
107
+ if (isSchemaFormProperties(item) || isSchemaFormDiscriminator(item) || isSchemaFormValues(item)) {
108
+ const result = dartTypeFromJtdSchema(key, item, {
109
+ isOptional: false,
110
+ existingClassNames
111
+ });
112
+ modelParts.push(result.content);
113
+ }
114
+ }
115
+ if (rpcParts.length === 0 && serviceGetterParts.length === 0) {
116
+ return `// this file was autogenerated by arri
117
+ // ignore_for_file: type=lint
118
+ import "package:arri_client/arri_client.dart";
119
+
120
+ ${modelParts.join("\n")}`;
121
+ }
122
+ return `// this file was autogenerated by arri
123
+ // ignore_for_file: type=lint, unused_field
124
+ import "dart:convert";
125
+ import "package:arri_client/arri_client.dart";
126
+ import "package:http/http.dart" as http;
127
+
128
+ class ${opts.clientName} {
129
+ final http.Client? _httpClient;
130
+ final String _baseUrl;
131
+ final String _clientVersion = "${def.info?.version ?? ""}";
132
+ late final Map<String, String> Function()? _headers;
133
+ ${opts.clientName}({
134
+ http.Client? httpClient,
135
+ String baseUrl = "",
136
+ Map<String, String> Function()? headers,
137
+ }) : _httpClient = httpClient,
138
+ _baseUrl = baseUrl,
139
+ _headers = headers;
140
+ ${rpcParts.join("\n ")}
141
+ ${serviceGetterParts.join("\n ")}
142
+ }
143
+
144
+ ${serviceParts.join("\n")}
145
+
146
+ ${modelParts.join("\n")}
147
+ `;
148
+ }
149
+ function dartServiceFromDefinition(name, def, opts) {
150
+ const rpcParts = [];
151
+ const subServiceParts = [];
152
+ const serviceName = `${name}`;
153
+ Object.keys(def).forEach((key) => {
154
+ const item = def[key];
155
+ if (isRpcDefinition(item)) {
156
+ const rpc = dartRpcFromDefinition(key, item);
157
+ if (rpc) {
158
+ rpcParts.push(rpc);
159
+ }
160
+ return;
161
+ }
162
+ if (isServiceDefinition(item)) {
163
+ const subServiceName = pascalCase(`${serviceName}_${key}`);
164
+ const subService = dartServiceFromDefinition(
165
+ subServiceName,
166
+ item,
167
+ opts
168
+ );
169
+ subServiceParts.push({
170
+ name: subServiceName,
171
+ key,
172
+ content: subService
173
+ });
174
+ }
175
+ });
176
+ return `class ${serviceName}Service {
177
+ final http.Client? _httpClient;
178
+ final String _baseUrl;
179
+ final String _clientVersion = "${opts.versionNumber}";
180
+ late final Map<String, String> Function()? _headers;
181
+ ${serviceName}Service({
182
+ http.Client? httpClient,
183
+ String baseUrl = "",
184
+ Map<String, String> Function()? headers,
185
+ }) : _httpClient = httpClient,
186
+ _baseUrl = baseUrl,
187
+ _headers = headers;
188
+ ${subServiceParts.map(
189
+ (sub) => `${sub.name}Service get ${sub.key} {
190
+ return ${sub.name}Service(
191
+ httpClient: _httpClient,
192
+ baseUrl: _baseUrl,
193
+ headers: _headers,
194
+ );
195
+ }`
196
+ ).join("\n")}
197
+ ${rpcParts.join("\n ")}
198
+ }
199
+ ${subServiceParts.map((sub) => sub.content).join("\n")}
200
+ `;
201
+ }
202
+ function dartRpcFromDefinition(key, def, opts) {
203
+ if (def.transport === "http") {
204
+ return dartHttpRpcFromSchema(key, def);
205
+ }
206
+ if (def.transport === "ws") {
207
+ return dartWsRpcFromSchema(key, def);
208
+ }
209
+ console.warn(
210
+ `[codegen-dart] WARNING: unsupported transport "${def.transport}". Skipping "${def.path}".`
211
+ );
212
+ return "";
213
+ }
214
+ function dartHttpRpcFromSchema(key, def, opts) {
215
+ let returnType = `Future<String>`;
216
+ let returnTypeName = "String";
217
+ if (def.response) {
218
+ returnTypeName = pascalCase(def.response);
219
+ if (def.isEventStream) {
220
+ returnType = `EventSource<${returnTypeName}>`;
221
+ } else {
222
+ returnType = `Future<${returnTypeName}>`;
223
+ }
224
+ } else {
225
+ returnType = "Future<void>";
226
+ }
227
+ let paramsInput = "";
228
+ if (def.params) {
229
+ paramsInput = `${pascalCase(def.params)} params`;
230
+ }
231
+ let responseParser = "(body) => body;";
232
+ switch (returnType) {
233
+ case "Future<String>":
234
+ break;
235
+ case "Future<int>":
236
+ responseParser = `(body) => Int.parse(body)`;
237
+ break;
238
+ case "Future<double>":
239
+ responseParser = `(body) => Double.parse(body)`;
240
+ break;
241
+ case "Future<void>":
242
+ responseParser = `(body) {}`;
243
+ break;
244
+ case "Future<bool>":
245
+ responseParser = `(body) {
246
+ switch(body) {
247
+ case "true":
248
+ case "1":
249
+ return true;
250
+ case "false":
251
+ case "0":
252
+ default:
253
+ return false;
254
+ }
255
+ }`;
256
+ break;
257
+ default:
258
+ responseParser = `(body) => ${returnTypeName}.fromJson(
259
+ json.decode(body),
260
+ )`;
261
+ break;
262
+ }
263
+ if (def.isEventStream) {
264
+ const hookParts = [
265
+ `SseHookOnData<${returnTypeName}>? onData`,
266
+ `SseHookOnError<${returnTypeName}>? onError`,
267
+ `SseHookOnConnectionError<${returnTypeName}>? onConnectionError`,
268
+ `SseHookOnOpen<${returnTypeName}>? onOpen`,
269
+ `SseHookOnClose<${returnTypeName}>? onClose`,
270
+ `String? lastEventId`
271
+ ];
272
+ return `${getAnnotations({ description: def.description, isDeprecated: def.isDeprecated })}${returnType} ${key}(${paramsInput.length ? `${paramsInput}, ` : ""}{${hookParts.join(", ")},}) {
273
+ return parsedArriSseRequest<${returnTypeName}>(
274
+ "$_baseUrl${def.path}",
275
+ httpClient: _httpClient,
276
+ method: HttpMethod.${def.method},
277
+ headers: _headers,
278
+ params: ${paramsInput.length ? `params.toJson()` : "null"},
279
+ parser: ${responseParser},
280
+ onData: onData,
281
+ onError: onError,
282
+ onConnectionError: onConnectionError,
283
+ onOpen: onOpen,
284
+ onClose: onClose,
285
+ lastEventId: lastEventId,
286
+ clientVersion: _clientVersion,
287
+ );
288
+ }`;
289
+ }
290
+ return `${getAnnotations({ description: def.description, isDeprecated: def.isDeprecated })}${returnType} ${key}(${paramsInput}) {
291
+ return parsedArriRequest(
292
+ "$_baseUrl${def.path}",
293
+ httpClient: _httpClient,
294
+ method: HttpMethod.${def.method},
295
+ headers: _headers,
296
+ params: ${paramsInput.length ? `params.toJson()` : "null"},
297
+ parser: ${responseParser},
298
+ clientVersion: _clientVersion,
299
+ );
300
+ }`;
301
+ }
302
+ function dartWsRpcFromSchema(key, def, opts) {
303
+ const serverMsg = def.response ? pascalCase(def.response, { normalize: true }) : "Null";
304
+ const clientMsg = def.params ? pascalCase(def.params, { normalize: true }) : "Null";
305
+ const returnType = `Future<ArriWebsocketController<${serverMsg}, ${clientMsg}>>`;
306
+ const parser = def.response ? `(body) => ${serverMsg}.fromJson(json.decode(body))` : `(_) => null`;
307
+ const serializer = def.params ? `(body) => json.encode(body.toJson())` : `(_) => ""`;
308
+ return `${getAnnotations({ description: def.description, isDeprecated: def.isDeprecated })}${returnType} ${key}() {
309
+ return arriWebsocketRequest<${serverMsg}, ${clientMsg}>(
310
+ "$_baseUrl${def.path}",
311
+ headers: _headers,
312
+ parser: ${parser},
313
+ serializer: ${serializer},
314
+ clientVersion: _clientVersion,
315
+ );
316
+ }`;
317
+ }
318
+ function dartTypeFromJtdSchema(nodePath, def, additionalOptions) {
319
+ if (isSchemaFormType(def)) {
320
+ return dartScalarFromJtdScalar(nodePath, def, additionalOptions);
321
+ }
322
+ if (isSchemaFormProperties(def)) {
323
+ return dartClassFromJtdSchema(nodePath, def, additionalOptions);
324
+ }
325
+ if (isSchemaFormElements(def)) {
326
+ return dartArrayFromJtdSchema(nodePath, def, additionalOptions);
327
+ }
328
+ if (isSchemaFormEnum(def)) {
329
+ return dartEnumFromJtdSchema(nodePath, def, additionalOptions);
330
+ }
331
+ if (isSchemaFormValues(def)) {
332
+ return dartMapFromJtdSchema(nodePath, def, additionalOptions);
333
+ }
334
+ if (isSchemaFormDiscriminator(def)) {
335
+ return dartSealedClassFromJtdSchema(nodePath, def, additionalOptions);
336
+ }
337
+ if (isSchemaFormRef(def)) {
338
+ return dartRefFromJtdSchema(nodePath, def, additionalOptions);
339
+ }
340
+ return dartDynamicFromAny(nodePath, a.any(), additionalOptions);
341
+ }
342
+ function dartClassFromJtdSchema(nodePath, def, additionalOptions) {
343
+ const isException = additionalOptions?.isException ?? false;
344
+ const discOptions = additionalOptions?.discriminatorOptions;
345
+ const isDiscriminatorChild = (discOptions?.discriminatorKey.length ?? 0) > 0;
346
+ const jsonKey = nodePath.split(".").pop() ?? "";
347
+ const key = camelCaseWrapper(jsonKey);
348
+ let className = def.metadata?.id ? pascalCase(def.metadata.id) : void 0;
349
+ if (!className) {
350
+ const relativePath = nodePath.split(".").pop();
351
+ if (additionalOptions.parentId && relativePath) {
352
+ className = pascalCase(
353
+ `${additionalOptions.parentId}_${relativePath}`
354
+ );
355
+ } else {
356
+ className = pascalCase(nodePath.split(".").join("_"));
357
+ }
358
+ }
359
+ const properties = [];
360
+ const optionalProperties = [];
361
+ const subContentParts = [];
362
+ if (!def.properties) {
363
+ return {
364
+ typeName: "",
365
+ fieldTemplate: "",
366
+ constructorTemplate: "",
367
+ fromJsonTemplate: () => "",
368
+ toJsonTemplate: () => "",
369
+ content: ""
370
+ };
371
+ }
372
+ for (const key2 of Object.keys(def.properties ?? {})) {
373
+ const keyPath = `${nodePath}.${key2}`;
374
+ const prop = def.properties[key2];
375
+ const mappedProp = dartTypeFromJtdSchema(keyPath, prop, {
376
+ parentId: className,
377
+ isOptional: false,
378
+ existingClassNames: additionalOptions.existingClassNames
379
+ });
380
+ properties.push({
381
+ key: key2,
382
+ templates: mappedProp
383
+ });
384
+ if (mappedProp?.content) {
385
+ subContentParts.push(mappedProp.content);
386
+ }
387
+ }
388
+ if (def.optionalProperties) {
389
+ for (const key2 of Object.keys(def.optionalProperties ?? {})) {
390
+ const keyPath = `${nodePath}.${key2}`;
391
+ const prop = def.optionalProperties[key2];
392
+ const mappedProp = dartTypeFromJtdSchema(keyPath, prop, {
393
+ parentId: className,
394
+ isOptional: true,
395
+ existingClassNames: additionalOptions.existingClassNames
396
+ });
397
+ optionalProperties.push({ key: key2, templates: mappedProp });
398
+ if (mappedProp?.content) {
399
+ subContentParts.push(mappedProp.content);
400
+ }
401
+ }
402
+ }
403
+ const fieldParts = [];
404
+ const constructorParts = [];
405
+ const fromJsonParts = [];
406
+ const copyWithParamParts = [];
407
+ const copyWithInitParts = [];
408
+ if (discOptions) {
409
+ fieldParts.push(`@override
410
+ final String ${camelCaseWrapper(discOptions.discriminatorKey)} = "${discOptions.discriminatorValue}"`);
411
+ }
412
+ for (const prop of properties) {
413
+ fieldParts.push(prop.templates.fieldTemplate);
414
+ constructorParts.push(prop.templates.constructorTemplate);
415
+ const subJsonKey = prop.key;
416
+ const subKey = camelCaseWrapper(prop.key);
417
+ fromJsonParts.push(
418
+ `${subKey}: ${prop.templates.fromJsonTemplate(
419
+ `json["${subJsonKey}"]`
420
+ )}`
421
+ );
422
+ if (prop.templates.typeName === "dynamic") {
423
+ copyWithParamParts.push(`dynamic ${subKey}`);
424
+ copyWithInitParts.push(`${subKey}: ${subKey} ?? this.${subKey}`);
425
+ } else {
426
+ if (prop.templates.typeName.endsWith("?")) {
427
+ copyWithParamParts.push(
428
+ `ArriBox<${prop.templates.typeName}>? ${subKey}`
429
+ );
430
+ copyWithInitParts.push(
431
+ `${subKey}: ${subKey} != null ? ${subKey}.value : this.${subKey}`
432
+ );
433
+ } else {
434
+ copyWithParamParts.push(
435
+ `${prop.templates.typeName}? ${subKey}`
436
+ );
437
+ copyWithInitParts.push(
438
+ `${subKey}: ${subKey} ?? this.${subKey}`
439
+ );
440
+ }
441
+ }
442
+ }
443
+ for (const prop of optionalProperties) {
444
+ fieldParts.push(prop.templates.fieldTemplate);
445
+ constructorParts.push(prop.templates.constructorTemplate);
446
+ const subKey = camelCaseWrapper(prop.key);
447
+ const subJsonKey = prop.key;
448
+ fromJsonParts.push(
449
+ `${subKey}: ${prop.templates.fromJsonTemplate(
450
+ `json["${subJsonKey}"]`
451
+ )}`
452
+ );
453
+ if (prop.templates.typeName === "dynamic") {
454
+ copyWithParamParts.push(`dynamic ${subKey}`);
455
+ copyWithInitParts.push(`${subKey}: ${subKey} ?? this.${subKey}`);
456
+ } else {
457
+ if (prop.templates.typeName.endsWith("?")) {
458
+ copyWithParamParts.push(
459
+ `ArriBox<${prop.templates.typeName}>? ${subKey}`
460
+ );
461
+ copyWithInitParts.push(
462
+ `${subKey}: ${subKey} != null ? ${subKey}.value : this.${subKey}`
463
+ );
464
+ } else {
465
+ copyWithParamParts.push(
466
+ `${prop.templates.typeName}? ${subKey}`
467
+ );
468
+ copyWithInitParts.push(
469
+ `${subKey}: ${subKey} ?? this.${subKey}`
470
+ );
471
+ }
472
+ }
473
+ }
474
+ let classNamePart = `class ${className}`;
475
+ if (isDiscriminatorChild) {
476
+ classNamePart += ` implements ${discOptions?.discriminatorParentClassName}`;
477
+ } else if (isException) {
478
+ classNamePart += ` implements Exception`;
479
+ }
480
+ let content = `${getAnnotations(def.metadata)}${classNamePart} {
481
+ ${fieldParts.join(";\n ")};
482
+ const ${className}({
483
+ ${constructorParts.join(",\n ")},
484
+ });
485
+ factory ${className}.fromJson(Map<String, dynamic> json) {
486
+ return ${className}(
487
+ ${fromJsonParts.join(",\n ")},
488
+ );
489
+ }
490
+ ${isDiscriminatorChild ? `@override` : ""}
491
+ Map<String, dynamic> toJson() {
492
+ final __result = <String, dynamic>{${isDiscriminatorChild ? `
493
+ "${discOptions?.discriminatorKey}": ${camelCaseWrapper(
494
+ discOptions?.discriminatorKey ?? ""
495
+ )},` : ""}
496
+ ${properties.map(
497
+ (prop) => `"${prop.key}": ${prop.templates.toJsonTemplate(
498
+ camelCaseWrapper(prop.key)
499
+ )}`
500
+ ).join(",\n ")}${properties.length ? "," : ""}
501
+ };
502
+ ${optionalProperties.map(
503
+ (prop) => `if (${camelCaseWrapper(prop.key)} != null) {
504
+ __result["${prop.key}"] = ${prop.templates.toJsonTemplate(
505
+ camelCaseWrapper(prop.key)
506
+ )};
507
+ }`
508
+ ).join("\n")}
509
+ return __result;
510
+ }
511
+ ${className} copyWith({
512
+ ${copyWithParamParts.join(",\n ")},
513
+ }) {
514
+ return ${className}(
515
+ ${copyWithInitParts.join(",\n ")},
516
+ );
517
+ }
518
+ }
519
+ ${subContentParts.join("\n")}
520
+
521
+ `;
522
+ if (additionalOptions.existingClassNames.includes(className)) {
523
+ content = "";
524
+ } else {
525
+ additionalOptions.existingClassNames.push(className);
526
+ }
527
+ const isNullable = def.nullable ?? additionalOptions?.isOptional;
528
+ const typeName = isNullable ? `${className}?` : className;
529
+ return {
530
+ typeName,
531
+ fieldTemplate: fieldTemplateString(
532
+ typeName,
533
+ key,
534
+ def.metadata?.description,
535
+ def.metadata?.isDeprecated
536
+ ),
537
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
538
+ fromJsonTemplate: (input) => isNullable ? `${input} is Map<String, dynamic> ? ${className}.fromJson(${input}) : null` : `${className}.fromJson(${input})`,
539
+ toJsonTemplate: (input) => `${input}${isNullable ? "?" : ""}.toJson()`,
540
+ content
541
+ };
542
+ }
543
+ function dartDynamicFromAny(nodePath, def, additionalOptions) {
544
+ const jsonKey = nodePath.split(".").pop() ?? "";
545
+ const key = camelCaseWrapper(jsonKey);
546
+ return {
547
+ typeName: "dynamic",
548
+ fieldTemplate: fieldTemplateString(
549
+ "dynamic",
550
+ key,
551
+ def.metadata?.description,
552
+ def.metadata?.isDeprecated
553
+ ),
554
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
555
+ fromJsonTemplate: (input) => `${input}`,
556
+ toJsonTemplate: (input) => input,
557
+ content: ""
558
+ };
559
+ }
560
+ function fieldTemplateString(typeName, key, description, deprecated) {
561
+ let result = "";
562
+ if (deprecated) {
563
+ result += `@deprecated
564
+ `;
565
+ }
566
+ if (description) {
567
+ const parts = description.split("\n");
568
+ for (const part of parts) {
569
+ result += `/// ${part}
570
+ `;
571
+ }
572
+ }
573
+ result += `final ${typeName} ${key}`;
574
+ return result;
575
+ }
576
+ function dartArrayFromJtdSchema(nodePath, def, additionalOptions) {
577
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
578
+ const jsonKey = nodePath.split(".").pop() ?? "";
579
+ const key = camelCaseWrapper(jsonKey);
580
+ const subtype = dartTypeFromJtdSchema(`${nodePath}.Item`, def.elements, {
581
+ existingClassNames: additionalOptions.existingClassNames,
582
+ isOptional: false
583
+ });
584
+ const typeName = isNullable ? `List<${subtype.typeName}>?` : `List<${subtype.typeName}>`;
585
+ return {
586
+ typeName,
587
+ fieldTemplate: fieldTemplateString(
588
+ typeName,
589
+ key,
590
+ def.metadata?.description,
591
+ def.metadata?.isDeprecated
592
+ ),
593
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
594
+ fromJsonTemplate: (input) => {
595
+ if (isNullable) {
596
+ return `${input} is List ?
597
+ // ignore: unnecessary_cast
598
+ (${input} as List).map((item) => ${subtype.fromJsonTemplate(
599
+ "item"
600
+ )}).toList() as ${typeName} : null`;
601
+ }
602
+ return `${input} is List ?
603
+ // ignore: unnecessary_cast
604
+ (${input} as List).map((item) => ${subtype.fromJsonTemplate(
605
+ "item"
606
+ )}).toList() as ${typeName} : <${subtype.typeName}>[]`;
607
+ },
608
+ toJsonTemplate: (input) => {
609
+ return `${input}${isNullable ? "?" : ""}.map((item) => ${subtype.toJsonTemplate("item")}).toList()`;
610
+ },
611
+ content: subtype.content
612
+ };
613
+ }
614
+ function dartScalarFromJtdScalar(nodePath, def, additionalOptions) {
615
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
616
+ const jsonKey = nodePath.split(".").pop() ?? "";
617
+ const key = camelCaseWrapper(jsonKey);
618
+ const defaultInitializationTemplate = additionalOptions.isOptional ? `this.${key}` : `required this.${key}`;
619
+ const { description } = def.metadata ?? {};
620
+ const defaultToJsonTemplate = (input) => input;
621
+ switch (def.type) {
622
+ case "boolean":
623
+ if (isNullable) {
624
+ return {
625
+ typeName: "bool?",
626
+ fieldTemplate: fieldTemplateString(
627
+ "bool?",
628
+ key,
629
+ description,
630
+ def.metadata?.isDeprecated
631
+ ),
632
+ constructorTemplate: defaultInitializationTemplate,
633
+ fromJsonTemplate: (input) => `nullableTypeFromDynamic<bool>(${input})`,
634
+ toJsonTemplate: defaultToJsonTemplate,
635
+ content: ""
636
+ };
637
+ }
638
+ return {
639
+ typeName: "bool",
640
+ fieldTemplate: fieldTemplateString(
641
+ "bool",
642
+ key,
643
+ description,
644
+ def.metadata?.isDeprecated
645
+ ),
646
+ constructorTemplate: defaultInitializationTemplate,
647
+ fromJsonTemplate: (input) => `typeFromDynamic<bool>(${input}, false)`,
648
+ toJsonTemplate: defaultToJsonTemplate,
649
+ content: ""
650
+ };
651
+ case "float32":
652
+ case "float64":
653
+ if (isNullable) {
654
+ return {
655
+ typeName: "double?",
656
+ fieldTemplate: fieldTemplateString(
657
+ "double?",
658
+ key,
659
+ description,
660
+ def.metadata?.isDeprecated
661
+ ),
662
+ constructorTemplate: defaultInitializationTemplate,
663
+ fromJsonTemplate: (input) => `nullableDoubleFromDynamic(${input})`,
664
+ toJsonTemplate: defaultToJsonTemplate,
665
+ content: ""
666
+ };
667
+ }
668
+ return {
669
+ typeName: "double",
670
+ fieldTemplate: fieldTemplateString(
671
+ "double",
672
+ key,
673
+ description,
674
+ def.metadata?.isDeprecated
675
+ ),
676
+ constructorTemplate: defaultInitializationTemplate,
677
+ fromJsonTemplate: (input) => `doubleFromDynamic(${input}, 0)`,
678
+ toJsonTemplate: defaultToJsonTemplate,
679
+ content: ""
680
+ };
681
+ case "int16":
682
+ case "int32":
683
+ case "int8":
684
+ case "uint16":
685
+ case "uint32":
686
+ case "uint8":
687
+ if (isNullable) {
688
+ return {
689
+ typeName: "int?",
690
+ fieldTemplate: fieldTemplateString(
691
+ "int?",
692
+ key,
693
+ description,
694
+ def.metadata?.isDeprecated
695
+ ),
696
+ constructorTemplate: defaultInitializationTemplate,
697
+ fromJsonTemplate: (input) => `nullableIntFromDynamic(${input})`,
698
+ toJsonTemplate: defaultToJsonTemplate,
699
+ content: ""
700
+ };
701
+ }
702
+ return {
703
+ typeName: "int",
704
+ fieldTemplate: fieldTemplateString(
705
+ `int`,
706
+ key,
707
+ description,
708
+ def.metadata?.isDeprecated
709
+ ),
710
+ constructorTemplate: defaultInitializationTemplate,
711
+ fromJsonTemplate: (input) => `intFromDynamic(${input}, 0)`,
712
+ toJsonTemplate: defaultToJsonTemplate,
713
+ content: ""
714
+ };
715
+ case "int64":
716
+ case "uint64":
717
+ if (isNullable) {
718
+ return {
719
+ typeName: "BigInt?",
720
+ fieldTemplate: fieldTemplateString(
721
+ `BigInt?`,
722
+ key,
723
+ description,
724
+ def.metadata?.isDeprecated
725
+ ),
726
+ constructorTemplate: defaultInitializationTemplate,
727
+ fromJsonTemplate: (input) => `nullableBigIntFromDynamic(${input})`,
728
+ toJsonTemplate: (input) => `${input}?.toString()`,
729
+ content: ""
730
+ };
731
+ }
732
+ return {
733
+ typeName: "BigInt",
734
+ fieldTemplate: fieldTemplateString(
735
+ `BigInt`,
736
+ key,
737
+ description,
738
+ def.metadata?.isDeprecated
739
+ ),
740
+ constructorTemplate: defaultInitializationTemplate,
741
+ fromJsonTemplate: (input) => `bigIntFromDynamic(${input}, BigInt.zero)`,
742
+ toJsonTemplate: (input) => `${input}.toString()`,
743
+ content: ""
744
+ };
745
+ case "timestamp":
746
+ if (isNullable) {
747
+ return {
748
+ typeName: "DateTime?",
749
+ fieldTemplate: fieldTemplateString(
750
+ "DateTime?",
751
+ key,
752
+ description,
753
+ def.metadata?.isDeprecated
754
+ ),
755
+ constructorTemplate: defaultInitializationTemplate,
756
+ fromJsonTemplate: (input) => `nullableDateTimeFromDynamic(${input})`,
757
+ toJsonTemplate: (input) => `${input}?.toUtc().toIso8601String()`,
758
+ content: ""
759
+ };
760
+ }
761
+ return {
762
+ typeName: "DateTime",
763
+ fieldTemplate: fieldTemplateString(
764
+ "DateTime",
765
+ key,
766
+ description,
767
+ def.metadata?.isDeprecated
768
+ ),
769
+ constructorTemplate: defaultInitializationTemplate,
770
+ fromJsonTemplate: (input) => `dateTimeFromDynamic(
771
+ ${input},
772
+ DateTime.fromMillisecondsSinceEpoch(0),
773
+ )`,
774
+ toJsonTemplate: (input) => `${input}.toUtc().toIso8601String()`,
775
+ content: ""
776
+ };
777
+ case "string":
778
+ if (isNullable) {
779
+ return {
780
+ typeName: "String?",
781
+ fieldTemplate: fieldTemplateString(
782
+ "String?",
783
+ key,
784
+ description,
785
+ def.metadata?.isDeprecated
786
+ ),
787
+ constructorTemplate: defaultInitializationTemplate,
788
+ fromJsonTemplate: (input) => `nullableTypeFromDynamic<String>(${input})`,
789
+ toJsonTemplate: defaultToJsonTemplate,
790
+ content: ""
791
+ };
792
+ }
793
+ return {
794
+ typeName: "String",
795
+ fieldTemplate: fieldTemplateString(
796
+ "String",
797
+ key,
798
+ description,
799
+ def.metadata?.isDeprecated
800
+ ),
801
+ constructorTemplate: defaultInitializationTemplate,
802
+ fromJsonTemplate: (input) => `typeFromDynamic<String>(${input}, "")`,
803
+ toJsonTemplate: defaultToJsonTemplate,
804
+ content: ""
805
+ };
806
+ default:
807
+ return {
808
+ typeName: "dynamic",
809
+ fieldTemplate: fieldTemplateString(
810
+ "dynamic",
811
+ key,
812
+ description,
813
+ def.metadata?.isDeprecated
814
+ ),
815
+ constructorTemplate: defaultInitializationTemplate,
816
+ fromJsonTemplate: (input) => input,
817
+ toJsonTemplate: defaultToJsonTemplate,
818
+ content: ""
819
+ };
820
+ }
821
+ }
822
+ function dartEnumFromJtdSchema(nodePath, def, additionalOptions) {
823
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
824
+ const jsonKey = nodePath.split(".").pop() ?? "";
825
+ const key = camelCaseWrapper(jsonKey);
826
+ let className = def.metadata?.id ? pascalCase(def.metadata.id) : void 0;
827
+ if (!className) {
828
+ className = pascalCase(nodePath.split(".").join("_"));
829
+ }
830
+ const valNames = [];
831
+ const fieldParts = [];
832
+ for (const val of def.enum) {
833
+ valNames.push(`${camelCaseWrapper(val)}`);
834
+ fieldParts.push(`${camelCaseWrapper(val)}("${val}")`);
835
+ }
836
+ let content = `${getAnnotations(def.metadata)}enum ${className} implements Comparable<${className}> {
837
+ ${fieldParts.join(",\n ")};
838
+ const ${className}(this.value);
839
+ final String value;
840
+
841
+ factory ${className}.fromJson(dynamic json) {
842
+ for(final v in values) {
843
+ if(v.value == json) {
844
+ return v;
845
+ }
846
+ }
847
+ return ${valNames[0]};
848
+ }
849
+
850
+ @override
851
+ compareTo(${className} other) => name.compareTo(other.name);
852
+ }`;
853
+ if (additionalOptions.existingClassNames.includes(className)) {
854
+ content = "";
855
+ } else {
856
+ additionalOptions.existingClassNames.push(className);
857
+ }
858
+ return {
859
+ typeName: className,
860
+ fieldTemplate: fieldTemplateString(
861
+ isNullable ? `${className}?` : className,
862
+ key,
863
+ def.metadata?.description,
864
+ def.metadata?.isDeprecated
865
+ ),
866
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
867
+ fromJsonTemplate: (input) => {
868
+ if (isNullable) {
869
+ return `${input} is String ? ${className}.fromJson(${input}) : null`;
870
+ }
871
+ return `${className}.fromJson(${input})`;
872
+ },
873
+ toJsonTemplate: (input) => `${input}${isNullable ? "?" : ""}.value`,
874
+ content
875
+ };
876
+ }
877
+ function dartMapFromJtdSchema(nodePath, def, additionalOptions) {
878
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
879
+ const jsonKey = nodePath.split(".").pop() ?? "";
880
+ const key = camelCaseWrapper(jsonKey);
881
+ const innerType = dartTypeFromJtdSchema(`${nodePath}.Value`, def.values, {
882
+ existingClassNames: additionalOptions.existingClassNames,
883
+ isOptional: false
884
+ });
885
+ const typeName = `Map<String, ${innerType.typeName}>${isNullable ? "?" : ""}`;
886
+ return {
887
+ typeName: isNullable ? `Map<String, ${innerType.typeName}>?` : `Map<String, ${innerType.typeName}>`,
888
+ fieldTemplate: fieldTemplateString(
889
+ typeName,
890
+ key,
891
+ def.metadata?.description,
892
+ def.metadata?.isDeprecated
893
+ ),
894
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
895
+ fromJsonTemplate: (input) => `${input} is Map<String, dynamic>
896
+ ? (${input} as Map<String, dynamic>).map(
897
+ (key, value) => MapEntry(key, ${innerType.fromJsonTemplate(
898
+ "value"
899
+ )}))
900
+ : <String, ${innerType.typeName}>{}`,
901
+ toJsonTemplate: (input) => `${input}${isNullable ? "?" : ""}.map((key, value) => MapEntry(key, ${innerType.toJsonTemplate(
902
+ "value"
903
+ )}))`,
904
+ content: innerType.content
905
+ };
906
+ }
907
+ function dartSealedClassFromJtdSchema(nodePath, def, additionalOptions) {
908
+ const className = def.metadata?.id ? pascalCase(def.metadata?.id) : pascalCase(nodePath.split(".").join("_"));
909
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
910
+ const jsonKey = nodePath.split(".").pop() ?? "";
911
+ const key = camelCaseWrapper(jsonKey);
912
+ const discriminatorJsonKey = def.discriminator;
913
+ const discriminatorKey = camelCaseWrapper(def.discriminator);
914
+ const fromJsonCaseParts = [];
915
+ const childContentParts = [];
916
+ Object.keys(def.mapping).forEach((discKeyValue) => {
917
+ const childDef = def.mapping[discKeyValue];
918
+ if (!isSchemaFormProperties(childDef)) {
919
+ return;
920
+ }
921
+ const child = dartClassFromJtdSchema(
922
+ `${nodePath}.${camelCaseWrapper(discKeyValue.toLowerCase())}`,
923
+ childDef,
924
+ {
925
+ parentId: className,
926
+ isOptional: false,
927
+ existingClassNames: additionalOptions.existingClassNames,
928
+ discriminatorOptions: {
929
+ discriminatorKey,
930
+ discriminatorValue: discKeyValue,
931
+ discriminatorParentClassName: className
932
+ }
933
+ }
934
+ );
935
+ fromJsonCaseParts.push(`case "${discKeyValue}":
936
+ return ${child.typeName}.fromJson(json);`);
937
+ childContentParts.push(child.content);
938
+ });
939
+ let content = "";
940
+ if (!additionalOptions.existingClassNames.includes(className)) {
941
+ content = `${getAnnotations(def.metadata)}sealed class ${className} {
942
+ final String ${discriminatorKey};
943
+ const ${className}({
944
+ required this.${discriminatorKey},
945
+ });
946
+ factory ${className}.fromJson(Map<String, dynamic> json) {
947
+ if(json["${discriminatorJsonKey}"] is! String) {
948
+ throw Exception(
949
+ "Unable to decode ${className}. Expected String from \\"${discriminatorJsonKey}\\". Received \${json["${discriminatorJsonKey}"]}}",
950
+ );
951
+ }
952
+ switch (json["${discriminatorJsonKey}"]) {
953
+ ${fromJsonCaseParts.join("\n ")}
954
+ }
955
+ throw Exception(
956
+ "Unable to decode ${className}. \\"\${json["${discriminatorJsonKey}"]}\\" doesn't match any of the accepted discriminator values.",
957
+ );
958
+ }
959
+ Map<String, dynamic> toJson();
960
+ }
961
+ ${childContentParts.join("\n")}`;
962
+ additionalOptions.existingClassNames.push(className);
963
+ }
964
+ const typeName = `${className}${isNullable ? "?" : ""}`;
965
+ return {
966
+ typeName,
967
+ fieldTemplate: fieldTemplateString(
968
+ typeName,
969
+ key,
970
+ def.metadata?.description,
971
+ def.metadata?.isDeprecated
972
+ ),
973
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
974
+ fromJsonTemplate: (input) => {
975
+ if (isNullable) {
976
+ return `${input} is Map<String, dynamic> ? ${className}.fromJson(${input}) : null`;
977
+ }
978
+ return `${className}.fromJson(${input})`;
979
+ },
980
+ toJsonTemplate: (input) => {
981
+ if (isNullable) {
982
+ return `${input}?.toJson()`;
983
+ }
984
+ return `${input}.toJson()`;
985
+ },
986
+ content
987
+ };
988
+ }
989
+ function dartRefFromJtdSchema(nodePath, def, additionalOptions) {
990
+ const jsonKey = nodePath.split(".").pop() ?? "";
991
+ const key = camelCaseWrapper(jsonKey);
992
+ const className = pascalCase(def.ref, { normalize: true });
993
+ const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
994
+ const typeName = `${className}${isNullable ? "?" : ""}`;
995
+ return {
996
+ typeName,
997
+ fieldTemplate: fieldTemplateString(
998
+ typeName,
999
+ key,
1000
+ def.metadata?.description,
1001
+ def.metadata?.isDeprecated
1002
+ ),
1003
+ constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
1004
+ fromJsonTemplate(input) {
1005
+ if (isNullable) {
1006
+ return `${input} is Map<String, dynamic> ? ${className}.fromJson(${input}) : null`;
1007
+ }
1008
+ return `${className}.fromJson(${input})`;
1009
+ },
1010
+ toJsonTemplate(input) {
1011
+ if (isNullable) {
1012
+ return `${input}?.toJson()`;
1013
+ }
1014
+ return `${input}.toJson()`;
1015
+ },
1016
+ content: ""
1017
+ };
1018
+ }
1019
+
1020
+ export { DartClientGenerator, createDartClient, dartClassFromJtdSchema, dartClientGenerator, dartHttpRpcFromSchema, dartRpcFromDefinition, dartServiceFromDefinition, dartTypeFromJtdSchema, dartWsRpcFromSchema, getAnnotations };