@arrirpc/codegen-dart 0.49.1 → 0.50.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.cjs +1114 -914
- package/dist/index.d.cts +26 -38
- package/dist/index.d.mts +26 -38
- package/dist/index.d.ts +26 -38
- package/dist/index.mjs +1121 -919
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
@@ -1,1021 +1,1223 @@
|
|
1
|
-
import {
|
2
|
-
import
|
3
|
-
import {
|
4
|
-
import
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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 });
|
1
|
+
import { execSync } from 'node:child_process';
|
2
|
+
import fs from 'node:fs/promises';
|
3
|
+
import { camelCase, pascalCase, removeDisallowedChars, isServiceDefinition, isRpcDefinition, defineClientGeneratorPlugin, unflattenProcedures, isSchemaFormType, isSchemaFormEnum, isSchemaFormProperties, isSchemaFormElements, isSchemaFormValues, isSchemaFormDiscriminator, isSchemaFormRef } from '@arrirpc/codegen-utils';
|
4
|
+
import path from 'pathe';
|
5
|
+
|
6
|
+
function outputIsNullable(schema, context) {
|
7
|
+
if (schema.nullable) {
|
8
|
+
return true;
|
15
9
|
}
|
16
|
-
|
10
|
+
if (context.isOptional) {
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
return false;
|
17
14
|
}
|
18
|
-
const
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
15
|
+
const reservedIdentifierKeywords = {
|
16
|
+
abstract: 2,
|
17
|
+
as: 2,
|
18
|
+
assert: 0,
|
19
|
+
async: 3,
|
20
|
+
await: 1,
|
21
|
+
base: 3,
|
22
|
+
break: 0,
|
23
|
+
case: 0,
|
24
|
+
catch: 0,
|
25
|
+
class: 0,
|
26
|
+
const: 0,
|
27
|
+
continue: 0,
|
28
|
+
covariant: 2,
|
29
|
+
default: 0,
|
30
|
+
deferred: 2,
|
31
|
+
do: 0,
|
32
|
+
dynamic: 2,
|
33
|
+
else: 0,
|
34
|
+
enum: 0,
|
35
|
+
export: 2,
|
36
|
+
extends: 0,
|
37
|
+
extension: 2,
|
38
|
+
external: 2,
|
39
|
+
factory: 2,
|
40
|
+
false: 0,
|
41
|
+
final: 0,
|
42
|
+
finally: 0,
|
43
|
+
for: 0,
|
44
|
+
Function: 2,
|
45
|
+
get: 2,
|
46
|
+
hide: 3,
|
47
|
+
if: 0,
|
48
|
+
implements: 2,
|
49
|
+
import: 2,
|
50
|
+
in: 0,
|
51
|
+
interface: 2,
|
52
|
+
is: 0,
|
53
|
+
late: 2,
|
54
|
+
library: 2,
|
55
|
+
mixin: 2,
|
56
|
+
new: 0,
|
57
|
+
null: 0,
|
58
|
+
of: 3,
|
59
|
+
on: 3,
|
60
|
+
operator: 2,
|
61
|
+
part: 2,
|
62
|
+
required: 2,
|
63
|
+
rethrow: 0,
|
64
|
+
return: 0,
|
65
|
+
sealed: 3,
|
66
|
+
set: 2,
|
67
|
+
show: 3,
|
68
|
+
static: 2,
|
69
|
+
super: 0,
|
70
|
+
switch: 0,
|
71
|
+
sync: 3,
|
72
|
+
this: 0,
|
73
|
+
throw: 0,
|
74
|
+
true: 0,
|
75
|
+
try: 0,
|
76
|
+
type: 2,
|
77
|
+
typedef: 2,
|
78
|
+
var: 0,
|
79
|
+
void: 0,
|
80
|
+
when: 3,
|
81
|
+
with: 0,
|
82
|
+
while: 0,
|
83
|
+
yield: 1
|
84
|
+
};
|
85
|
+
function canUseIdentifier(input) {
|
86
|
+
const reservedId = reservedIdentifierKeywords[input];
|
87
|
+
if (typeof reservedId === "undefined") {
|
88
|
+
return true;
|
48
89
|
}
|
49
|
-
)
|
50
|
-
|
51
|
-
|
52
|
-
|
90
|
+
switch (reservedId) {
|
91
|
+
case 0:
|
92
|
+
return false;
|
93
|
+
case 1:
|
94
|
+
return true;
|
95
|
+
case 2:
|
96
|
+
return true;
|
97
|
+
case 3:
|
98
|
+
return true;
|
99
|
+
default:
|
100
|
+
throw new Error("Unhandled case");
|
53
101
|
}
|
54
102
|
}
|
55
|
-
function
|
56
|
-
const
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
103
|
+
function sanitizeIdentifier(input) {
|
104
|
+
const bannedCharacters = "!@#$%^&*()-=+[{}]\\|/?.><,;`~";
|
105
|
+
const result = removeDisallowedChars(input, bannedCharacters);
|
106
|
+
const numbers = "0123456789";
|
107
|
+
if (numbers.includes(result.charAt(0))) {
|
108
|
+
return `k_${result}`;
|
62
109
|
}
|
63
|
-
|
64
|
-
|
110
|
+
return result;
|
111
|
+
}
|
112
|
+
function canUseClassName(input) {
|
113
|
+
const reservedId = reservedIdentifierKeywords[input];
|
114
|
+
if (typeof reservedId === "undefined") {
|
115
|
+
return true;
|
65
116
|
}
|
66
|
-
|
67
|
-
|
117
|
+
switch (reservedId) {
|
118
|
+
case 0:
|
119
|
+
return false;
|
120
|
+
case 1:
|
121
|
+
return false;
|
122
|
+
case 2:
|
123
|
+
return false;
|
124
|
+
case 3:
|
125
|
+
return true;
|
126
|
+
default:
|
127
|
+
throw new Error("Unhandled case");
|
68
128
|
}
|
69
|
-
return `${commentParts.join("\n")}
|
70
|
-
`;
|
71
129
|
}
|
72
|
-
function
|
73
|
-
const
|
74
|
-
|
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,
|
130
|
+
function validDartIdentifier(input) {
|
131
|
+
const finalIdentifier = sanitizeIdentifier(
|
132
|
+
camelCase(input, { normalize: true })
|
101
133
|
);
|
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
|
-
}
|
134
|
+
if (!canUseIdentifier(finalIdentifier)) {
|
135
|
+
return `k_${finalIdentifier}`;
|
114
136
|
}
|
115
|
-
|
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:async";
|
125
|
-
import "dart:convert";
|
126
|
-
import "package:arri_client/arri_client.dart";
|
127
|
-
import "package:http/http.dart" as http;
|
128
|
-
|
129
|
-
class ${opts.clientName} {
|
130
|
-
final http.Client? _httpClient;
|
131
|
-
final String _baseUrl;
|
132
|
-
final String _clientVersion = "${def.info?.version ?? ""}";
|
133
|
-
late final FutureOr<Map<String, String>> Function()? _headers;
|
134
|
-
${opts.clientName}({
|
135
|
-
http.Client? httpClient,
|
136
|
-
String baseUrl = "",
|
137
|
-
FutureOr<Map<String, String>> Function()? headers,
|
138
|
-
}) : _httpClient = httpClient,
|
139
|
-
_baseUrl = baseUrl,
|
140
|
-
_headers = headers;
|
141
|
-
${rpcParts.join("\n ")}
|
142
|
-
${serviceGetterParts.join("\n ")}
|
143
|
-
}
|
144
|
-
|
145
|
-
${serviceParts.join("\n")}
|
146
|
-
|
147
|
-
${modelParts.join("\n")}
|
148
|
-
`;
|
149
|
-
}
|
150
|
-
function dartServiceFromDefinition(name, def, opts) {
|
151
|
-
const rpcParts = [];
|
152
|
-
const subServiceParts = [];
|
153
|
-
const serviceName = `${name}`;
|
154
|
-
Object.keys(def).forEach((key) => {
|
155
|
-
const item = def[key];
|
156
|
-
if (isRpcDefinition(item)) {
|
157
|
-
const rpc = dartRpcFromDefinition(key, item);
|
158
|
-
if (rpc) {
|
159
|
-
rpcParts.push(rpc);
|
160
|
-
}
|
161
|
-
return;
|
162
|
-
}
|
163
|
-
if (isServiceDefinition(item)) {
|
164
|
-
const subServiceName = pascalCase(`${serviceName}_${key}`);
|
165
|
-
const subService = dartServiceFromDefinition(
|
166
|
-
subServiceName,
|
167
|
-
item,
|
168
|
-
opts
|
169
|
-
);
|
170
|
-
subServiceParts.push({
|
171
|
-
name: subServiceName,
|
172
|
-
key,
|
173
|
-
content: subService
|
174
|
-
});
|
175
|
-
}
|
176
|
-
});
|
177
|
-
return `class ${serviceName}Service {
|
178
|
-
final http.Client? _httpClient;
|
179
|
-
final String _baseUrl;
|
180
|
-
final String _clientVersion = "${opts.versionNumber}";
|
181
|
-
late final FutureOr<Map<String, String>> Function()? _headers;
|
182
|
-
${serviceName}Service({
|
183
|
-
http.Client? httpClient,
|
184
|
-
String baseUrl = "",
|
185
|
-
FutureOr<Map<String, String>> Function()? headers,
|
186
|
-
}) : _httpClient = httpClient,
|
187
|
-
_baseUrl = baseUrl,
|
188
|
-
_headers = headers;
|
189
|
-
${subServiceParts.map(
|
190
|
-
(sub) => `${sub.name}Service get ${sub.key} {
|
191
|
-
return ${sub.name}Service(
|
192
|
-
httpClient: _httpClient,
|
193
|
-
baseUrl: _baseUrl,
|
194
|
-
headers: _headers,
|
195
|
-
);
|
196
|
-
}`
|
197
|
-
).join("\n")}
|
198
|
-
${rpcParts.join("\n ")}
|
199
|
-
}
|
200
|
-
${subServiceParts.map((sub) => sub.content).join("\n")}
|
201
|
-
`;
|
137
|
+
return finalIdentifier;
|
202
138
|
}
|
203
|
-
function
|
204
|
-
|
205
|
-
|
206
|
-
}
|
207
|
-
if (def.transport === "ws") {
|
208
|
-
return dartWsRpcFromSchema(key, def);
|
209
|
-
}
|
210
|
-
console.warn(
|
211
|
-
`[codegen-dart] WARNING: unsupported transport "${def.transport}". Skipping "${def.path}".`
|
139
|
+
function validDartClassName(input, modelPrefix) {
|
140
|
+
const className = sanitizeIdentifier(
|
141
|
+
pascalCase(input, { normalize: true })
|
212
142
|
);
|
213
|
-
|
214
|
-
|
215
|
-
function dartHttpRpcFromSchema(key, def, _opts) {
|
216
|
-
let returnType = `Future<String>`;
|
217
|
-
let returnTypeName = "String";
|
218
|
-
if (def.response) {
|
219
|
-
returnTypeName = pascalCase(def.response);
|
220
|
-
if (def.isEventStream) {
|
221
|
-
returnType = `EventSource<${returnTypeName}>`;
|
222
|
-
} else {
|
223
|
-
returnType = `Future<${returnTypeName}>`;
|
224
|
-
}
|
225
|
-
} else {
|
226
|
-
returnType = "Future<void>";
|
227
|
-
}
|
228
|
-
let paramsInput = "";
|
229
|
-
if (def.params) {
|
230
|
-
paramsInput = `${pascalCase(def.params)} params`;
|
231
|
-
}
|
232
|
-
let responseParser = "(body) => body;";
|
233
|
-
switch (returnType) {
|
234
|
-
case "Future<String>":
|
235
|
-
break;
|
236
|
-
case "Future<int>":
|
237
|
-
responseParser = `(body) => Int.parse(body)`;
|
238
|
-
break;
|
239
|
-
case "Future<double>":
|
240
|
-
responseParser = `(body) => Double.parse(body)`;
|
241
|
-
break;
|
242
|
-
case "Future<void>":
|
243
|
-
responseParser = `(body) {}`;
|
244
|
-
break;
|
245
|
-
case "Future<bool>":
|
246
|
-
responseParser = `(body) {
|
247
|
-
switch(body) {
|
248
|
-
case "true":
|
249
|
-
case "1":
|
250
|
-
return true;
|
251
|
-
case "false":
|
252
|
-
case "0":
|
253
|
-
default:
|
254
|
-
return false;
|
255
|
-
}
|
256
|
-
}`;
|
257
|
-
break;
|
258
|
-
default:
|
259
|
-
responseParser = `(body) => ${returnTypeName}.fromJson(
|
260
|
-
json.decode(body),
|
261
|
-
)`;
|
262
|
-
break;
|
263
|
-
}
|
264
|
-
if (def.isEventStream) {
|
265
|
-
const hookParts = [
|
266
|
-
`SseHookOnData<${returnTypeName}>? onData`,
|
267
|
-
`SseHookOnError<${returnTypeName}>? onError`,
|
268
|
-
`SseHookOnConnectionError<${returnTypeName}>? onConnectionError`,
|
269
|
-
`SseHookOnOpen<${returnTypeName}>? onOpen`,
|
270
|
-
`SseHookOnClose<${returnTypeName}>? onClose`,
|
271
|
-
`String? lastEventId`
|
272
|
-
];
|
273
|
-
return `${getAnnotations({ description: def.description, isDeprecated: def.isDeprecated })}${returnType} ${key}(${paramsInput.length ? `${paramsInput}, ` : ""}{${hookParts.join(", ")},}) {
|
274
|
-
return parsedArriSseRequest<${returnTypeName}>(
|
275
|
-
"$_baseUrl${def.path}",
|
276
|
-
httpClient: _httpClient,
|
277
|
-
method: HttpMethod.${def.method},
|
278
|
-
headers: _headers,
|
279
|
-
params: ${paramsInput.length ? `params.toJson()` : "null"},
|
280
|
-
parser: ${responseParser},
|
281
|
-
onData: onData,
|
282
|
-
onError: onError,
|
283
|
-
onConnectionError: onConnectionError,
|
284
|
-
onOpen: onOpen,
|
285
|
-
onClose: onClose,
|
286
|
-
lastEventId: lastEventId,
|
287
|
-
clientVersion: _clientVersion,
|
288
|
-
);
|
289
|
-
}`;
|
143
|
+
if (canUseClassName(className) || modelPrefix.length) {
|
144
|
+
return className;
|
290
145
|
}
|
291
|
-
return
|
292
|
-
return parsedArriRequest(
|
293
|
-
"$_baseUrl${def.path}",
|
294
|
-
httpClient: _httpClient,
|
295
|
-
method: HttpMethod.${def.method},
|
296
|
-
headers: _headers,
|
297
|
-
params: ${paramsInput.length ? `params.toJson()` : "null"},
|
298
|
-
parser: ${responseParser},
|
299
|
-
clientVersion: _clientVersion,
|
300
|
-
);
|
301
|
-
}`;
|
302
|
-
}
|
303
|
-
function dartWsRpcFromSchema(key, def, _opts) {
|
304
|
-
const serverMsg = def.response ? pascalCase(def.response, { normalize: true }) : "Null";
|
305
|
-
const clientMsg = def.params ? pascalCase(def.params, { normalize: true }) : "Null";
|
306
|
-
const returnType = `Future<ArriWebsocketController<${serverMsg}, ${clientMsg}>>`;
|
307
|
-
const parser = def.response ? `(body) => ${serverMsg}.fromJson(json.decode(body))` : `(_) => null`;
|
308
|
-
const serializer = def.params ? `(body) => json.encode(body.toJson())` : `(_) => ""`;
|
309
|
-
return `${getAnnotations({ description: def.description, isDeprecated: def.isDeprecated })}${returnType} ${key}() {
|
310
|
-
return arriWebsocketRequest<${serverMsg}, ${clientMsg}>(
|
311
|
-
"$_baseUrl${def.path}",
|
312
|
-
headers: _headers,
|
313
|
-
parser: ${parser},
|
314
|
-
serializer: ${serializer},
|
315
|
-
clientVersion: _clientVersion,
|
316
|
-
);
|
317
|
-
}`;
|
146
|
+
return `Class${className}`;
|
318
147
|
}
|
319
|
-
function
|
320
|
-
if (
|
321
|
-
return
|
322
|
-
}
|
323
|
-
if (isSchemaFormProperties(def)) {
|
324
|
-
return dartClassFromJtdSchema(nodePath, def, additionalOptions);
|
325
|
-
}
|
326
|
-
if (isSchemaFormElements(def)) {
|
327
|
-
return dartArrayFromJtdSchema(nodePath, def, additionalOptions);
|
328
|
-
}
|
329
|
-
if (isSchemaFormEnum(def)) {
|
330
|
-
return dartEnumFromJtdSchema(nodePath, def, additionalOptions);
|
331
|
-
}
|
332
|
-
if (isSchemaFormValues(def)) {
|
333
|
-
return dartMapFromJtdSchema(nodePath, def, additionalOptions);
|
334
|
-
}
|
335
|
-
if (isSchemaFormDiscriminator(def)) {
|
336
|
-
return dartSealedClassFromJtdSchema(nodePath, def, additionalOptions);
|
148
|
+
function getDartClassName(schema, context) {
|
149
|
+
if (schema.metadata?.id) {
|
150
|
+
return validDartClassName(schema.metadata.id, context.modelPrefix);
|
337
151
|
}
|
338
|
-
if (
|
339
|
-
return
|
152
|
+
if (context.discriminatorParentId) {
|
153
|
+
return validDartClassName(
|
154
|
+
`${context.discriminatorParentId}_${context.discriminatorValue}`,
|
155
|
+
context.modelPrefix
|
156
|
+
);
|
340
157
|
}
|
341
|
-
return
|
158
|
+
return validDartClassName(
|
159
|
+
context.instancePath.split("/").join("_"),
|
160
|
+
context.modelPrefix
|
161
|
+
);
|
342
162
|
}
|
343
|
-
|
344
|
-
|
345
|
-
const
|
346
|
-
const
|
347
|
-
const
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
}
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
}
|
388
|
-
}
|
389
|
-
if (def.optionalProperties) {
|
390
|
-
for (const key2 of Object.keys(def.optionalProperties ?? {})) {
|
391
|
-
const keyPath = `${nodePath}.${key2}`;
|
392
|
-
const prop = def.optionalProperties[key2];
|
393
|
-
const mappedProp = dartTypeFromJtdSchema(keyPath, prop, {
|
394
|
-
parentId: className,
|
395
|
-
isOptional: true,
|
396
|
-
existingClassNames: additionalOptions.existingClassNames
|
397
|
-
});
|
398
|
-
optionalProperties.push({ key: key2, templates: mappedProp });
|
399
|
-
if (mappedProp?.content) {
|
400
|
-
subContentParts.push(mappedProp.content);
|
163
|
+
|
164
|
+
function dartAnyFromSchema(schema, context) {
|
165
|
+
const typeName = `dynamic`;
|
166
|
+
const isNullable = outputIsNullable(schema, context);
|
167
|
+
const defaultValue = `null`;
|
168
|
+
return {
|
169
|
+
typeName,
|
170
|
+
isNullable,
|
171
|
+
defaultValue,
|
172
|
+
fromJson(input) {
|
173
|
+
return `${input}`;
|
174
|
+
},
|
175
|
+
toJson(input) {
|
176
|
+
return input;
|
177
|
+
},
|
178
|
+
toQueryString() {
|
179
|
+
return `print("[WARNING] any's cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
180
|
+
},
|
181
|
+
content: ""
|
182
|
+
};
|
183
|
+
}
|
184
|
+
|
185
|
+
function dartListFromSchema(schema, context) {
|
186
|
+
const isNullable = outputIsNullable(schema, context);
|
187
|
+
const innerType = dartTypeFromSchema(schema.elements, {
|
188
|
+
clientName: context.clientName,
|
189
|
+
modelPrefix: context.modelPrefix,
|
190
|
+
generatedTypes: context.generatedTypes,
|
191
|
+
instancePath: `${context.instancePath}/[Element]`,
|
192
|
+
schemaPath: `${context.schemaPath}/elements`
|
193
|
+
});
|
194
|
+
const typeName = isNullable ? `List<${innerType.typeName}>?` : `List<${innerType.typeName}>`;
|
195
|
+
const defaultValue = isNullable ? "null" : "[]";
|
196
|
+
return {
|
197
|
+
typeName,
|
198
|
+
isNullable,
|
199
|
+
defaultValue,
|
200
|
+
fromJson(input) {
|
201
|
+
if (isNullable) {
|
202
|
+
return `${input} is List
|
203
|
+
? (${input} as List)
|
204
|
+
.map((_el_) => ${innerType.fromJson(`_el_`)})
|
205
|
+
.toList()
|
206
|
+
: null`;
|
401
207
|
}
|
402
|
-
|
208
|
+
return `${input} is List
|
209
|
+
? (${input} as List)
|
210
|
+
.map((_el_) => ${innerType.fromJson(`_el_`)})
|
211
|
+
.toList()
|
212
|
+
: <${innerType.typeName}>[]`;
|
213
|
+
},
|
214
|
+
toJson(input) {
|
215
|
+
if (context.isOptional) {
|
216
|
+
return `${input}!.map((_el_) => ${innerType.toJson("_el_", "", "")}).toList()`;
|
217
|
+
}
|
218
|
+
if (schema.nullable) {
|
219
|
+
return `${input}?.map((_el_) => ${innerType.toJson("_el_", "", "")}).toList()`;
|
220
|
+
}
|
221
|
+
return `${input}.map((_el_) => ${innerType.toJson("_el_", "", "")}).toList()`;
|
222
|
+
},
|
223
|
+
toQueryString() {
|
224
|
+
return `print(
|
225
|
+
"[WARNING] arrays cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
226
|
+
},
|
227
|
+
content: innerType.content
|
228
|
+
};
|
229
|
+
}
|
230
|
+
|
231
|
+
function dartClassFromSchema(schema, context) {
|
232
|
+
const isNullable = outputIsNullable(schema, context);
|
233
|
+
const className = getDartClassName(schema, context);
|
234
|
+
const finalClassName = `${context.modelPrefix}${className}`;
|
235
|
+
const typeName = isNullable ? `${finalClassName}?` : finalClassName;
|
236
|
+
const defaultValue = isNullable ? "null" : `${finalClassName}.empty()`;
|
237
|
+
const result = {
|
238
|
+
typeName,
|
239
|
+
isNullable,
|
240
|
+
defaultValue,
|
241
|
+
fromJson(input) {
|
242
|
+
if (isNullable) {
|
243
|
+
return `${input} is Map<String, dynamic>
|
244
|
+
? ${finalClassName}.fromJson(${input})
|
245
|
+
: null`;
|
246
|
+
}
|
247
|
+
return `${input} is Map<String, dynamic>
|
248
|
+
? ${finalClassName}.fromJson(${input})
|
249
|
+
: ${finalClassName}.empty()`;
|
250
|
+
},
|
251
|
+
toJson(input) {
|
252
|
+
if (context.isOptional) {
|
253
|
+
return `${input}!.toJson()`;
|
254
|
+
}
|
255
|
+
if (schema.nullable) {
|
256
|
+
return `${input}?.toJson()`;
|
257
|
+
}
|
258
|
+
return `${input}.toJson()`;
|
259
|
+
},
|
260
|
+
toQueryString() {
|
261
|
+
return `print(
|
262
|
+
"[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
263
|
+
},
|
264
|
+
content: ""
|
265
|
+
};
|
266
|
+
if (context.generatedTypes.includes(className)) {
|
267
|
+
return result;
|
403
268
|
}
|
269
|
+
const propNames = [];
|
404
270
|
const fieldParts = [];
|
405
271
|
const constructorParts = [];
|
272
|
+
const defaultParts = [];
|
406
273
|
const fromJsonParts = [];
|
274
|
+
const toJsonRequiredParts = [];
|
275
|
+
if (context.discriminatorKey && context.discriminatorValue) {
|
276
|
+
toJsonRequiredParts.push(
|
277
|
+
` "${context.discriminatorKey}": ${validDartIdentifier(context.discriminatorKey)},`
|
278
|
+
);
|
279
|
+
}
|
280
|
+
const toJsonOptionalParts = [];
|
281
|
+
const toUrlQueryParts = [];
|
282
|
+
if (context.discriminatorKey && context.discriminatorValue) {
|
283
|
+
toUrlQueryParts.push(
|
284
|
+
`_queryParts_.add("${context.discriminatorKey}=$${validDartIdentifier(context.discriminatorKey)}");`
|
285
|
+
);
|
286
|
+
}
|
407
287
|
const copyWithParamParts = [];
|
408
|
-
const
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
288
|
+
const copyWithReturnParts = [];
|
289
|
+
const subContentParts = [];
|
290
|
+
for (const key of Object.keys(schema.properties)) {
|
291
|
+
const innerSchema = schema.properties[key];
|
292
|
+
const typeResult = dartTypeFromSchema(innerSchema, {
|
293
|
+
clientName: context.clientName,
|
294
|
+
modelPrefix: context.modelPrefix,
|
295
|
+
generatedTypes: context.generatedTypes,
|
296
|
+
instancePath: `/${className}/${key}`,
|
297
|
+
schemaPath: `${context.schemaPath}/properties/${key}`
|
298
|
+
});
|
299
|
+
const propName = validDartIdentifier(key);
|
300
|
+
propNames.push(propName);
|
301
|
+
fieldParts.push(` final ${typeResult.typeName} ${propName};`);
|
302
|
+
constructorParts.push(` required this.${propName},`);
|
303
|
+
defaultParts.push(` ${propName}: ${typeResult.defaultValue},`);
|
418
304
|
fromJsonParts.push(
|
419
|
-
|
420
|
-
`json["${subJsonKey}"]`
|
421
|
-
)}`
|
305
|
+
` final ${propName} = ${typeResult.fromJson(`_input_["${key}"]`, key)};`
|
422
306
|
);
|
423
|
-
|
424
|
-
|
425
|
-
|
307
|
+
toJsonRequiredParts.push(
|
308
|
+
` "${key}": ${typeResult.toJson(propName, "", key)},`
|
309
|
+
);
|
310
|
+
toUrlQueryParts.push(
|
311
|
+
` ${typeResult.toQueryString(propName, "_queryParts_", key)};`
|
312
|
+
);
|
313
|
+
if (typeResult.isNullable) {
|
314
|
+
copyWithParamParts.push(
|
315
|
+
` ${typeResult.typeName} Function()? ${propName},`
|
316
|
+
);
|
317
|
+
copyWithReturnParts.push(
|
318
|
+
` ${propName}: ${propName} != null ? ${propName}() : this.${propName},`
|
319
|
+
);
|
426
320
|
} else {
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
`${prop.templates.typeName}? ${subKey}`
|
437
|
-
);
|
438
|
-
copyWithInitParts.push(
|
439
|
-
`${subKey}: ${subKey} ?? this.${subKey}`
|
440
|
-
);
|
441
|
-
}
|
321
|
+
copyWithParamParts.push(
|
322
|
+
` ${typeResult.typeName}${typeResult.typeName !== "dynamic" ? "?" : ""} ${propName},`
|
323
|
+
);
|
324
|
+
copyWithReturnParts.push(
|
325
|
+
` ${propName}: ${propName} ?? this.${propName},`
|
326
|
+
);
|
327
|
+
}
|
328
|
+
if (typeResult.content) {
|
329
|
+
subContentParts.push(typeResult.content);
|
442
330
|
}
|
443
331
|
}
|
444
|
-
for (const
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
332
|
+
for (const key of Object.keys(schema.optionalProperties ?? {})) {
|
333
|
+
const innerSchema = schema.optionalProperties[key];
|
334
|
+
const typeResult = dartTypeFromSchema(innerSchema, {
|
335
|
+
clientName: context.clientName,
|
336
|
+
modelPrefix: context.modelPrefix,
|
337
|
+
generatedTypes: context.generatedTypes,
|
338
|
+
instancePath: `/${className}/${key}`,
|
339
|
+
schemaPath: `${context.schemaPath}/optionalProperties/${key}`,
|
340
|
+
isOptional: true
|
341
|
+
});
|
342
|
+
const propName = validDartIdentifier(key);
|
343
|
+
propNames.push(propName);
|
344
|
+
fieldParts.push(` final ${typeResult.typeName} ${propName};`);
|
345
|
+
constructorParts.push(` this.${propName},`);
|
449
346
|
fromJsonParts.push(
|
450
|
-
|
451
|
-
`json["${subJsonKey}"]`
|
452
|
-
)}`
|
347
|
+
` final ${propName} = ${typeResult.fromJson(`_input_["${key}"]`, key)};`
|
453
348
|
);
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
);
|
469
|
-
copyWithInitParts.push(
|
470
|
-
`${subKey}: ${subKey} ?? this.${subKey}`
|
471
|
-
);
|
472
|
-
}
|
349
|
+
toJsonOptionalParts.push(
|
350
|
+
` if (${propName} != null) _output_["${key}"] = ${typeResult.toJson(propName, "_output_", key)};`
|
351
|
+
);
|
352
|
+
toUrlQueryParts.push(
|
353
|
+
` ${typeResult.toQueryString(propName, "_queryParts_", key)};`
|
354
|
+
);
|
355
|
+
copyWithParamParts.push(
|
356
|
+
` ${typeResult.typeName} Function()? ${propName},`
|
357
|
+
);
|
358
|
+
copyWithReturnParts.push(
|
359
|
+
` ${propName}: ${propName} != null ? ${propName}() : this.${propName},`
|
360
|
+
);
|
361
|
+
if (typeResult.content) {
|
362
|
+
subContentParts.push(typeResult.content);
|
473
363
|
}
|
474
364
|
}
|
475
|
-
let
|
476
|
-
if (
|
477
|
-
|
478
|
-
|
479
|
-
|
365
|
+
let discriminatorPart = "";
|
366
|
+
if (context.discriminatorKey && context.discriminatorValue) {
|
367
|
+
discriminatorPart = `
|
368
|
+
@override
|
369
|
+
String get ${validDartIdentifier(context.discriminatorKey)} => "${context.discriminatorValue}";
|
370
|
+
`;
|
480
371
|
}
|
481
|
-
|
482
|
-
|
483
|
-
const ${
|
484
|
-
|
372
|
+
result.content = `class ${finalClassName} implements ${context.discriminatorParentId ?? "ArriModel"} {
|
373
|
+
${fieldParts.join("\n")}
|
374
|
+
const ${finalClassName}({
|
375
|
+
${constructorParts.join("\n")}
|
485
376
|
});
|
486
|
-
|
487
|
-
|
488
|
-
|
377
|
+
${discriminatorPart}
|
378
|
+
factory ${finalClassName}.empty() {
|
379
|
+
return ${finalClassName}(
|
380
|
+
${defaultParts.join("\n")}
|
489
381
|
);
|
490
382
|
}
|
491
|
-
|
383
|
+
|
384
|
+
factory ${finalClassName}.fromJson(Map<String, dynamic> _input_) {
|
385
|
+
${fromJsonParts.join("\n")}
|
386
|
+
return ${finalClassName}(
|
387
|
+
${propNames.map((prop) => ` ${prop}: ${prop},`).join("\n")}
|
388
|
+
);
|
389
|
+
}
|
390
|
+
|
391
|
+
factory ${finalClassName}.fromJsonString(String input) {
|
392
|
+
return ${finalClassName}.fromJson(json.decode(input));
|
393
|
+
}
|
394
|
+
|
395
|
+
@override
|
492
396
|
Map<String, dynamic> toJson() {
|
493
|
-
final
|
494
|
-
|
495
|
-
discOptions?.discriminatorKey ?? ""
|
496
|
-
)},` : ""}
|
497
|
-
${properties.map(
|
498
|
-
(prop) => `"${prop.key}": ${prop.templates.toJsonTemplate(
|
499
|
-
camelCaseWrapper(prop.key)
|
500
|
-
)}`
|
501
|
-
).join(",\n ")}${properties.length ? "," : ""}
|
397
|
+
final _output_ = <String, dynamic>{
|
398
|
+
${toJsonRequiredParts.join("\n")}
|
502
399
|
};
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
return __result;
|
400
|
+
${toJsonOptionalParts.join("\n")}
|
401
|
+
return _output_;
|
402
|
+
}
|
403
|
+
|
404
|
+
@override
|
405
|
+
String toJsonString() {
|
406
|
+
return json.encode(toJson());
|
511
407
|
}
|
512
|
-
|
513
|
-
|
408
|
+
|
409
|
+
@override
|
410
|
+
String toUrlQueryParams() {
|
411
|
+
final _queryParts_ = <String>[];
|
412
|
+
${toUrlQueryParts.join("\n")}
|
413
|
+
return _queryParts_.join("&");
|
414
|
+
}
|
415
|
+
|
416
|
+
@override
|
417
|
+
${finalClassName} copyWith({
|
418
|
+
${copyWithParamParts.join("\n")}
|
514
419
|
}) {
|
515
|
-
return ${
|
516
|
-
|
420
|
+
return ${finalClassName}(
|
421
|
+
${copyWithReturnParts.join("\n")}
|
517
422
|
);
|
518
423
|
}
|
424
|
+
|
425
|
+
@override
|
426
|
+
List<Object?> get props => [
|
427
|
+
${propNames.map((prop) => ` ${prop},`).join("\n")}
|
428
|
+
];
|
429
|
+
|
430
|
+
@override
|
431
|
+
bool operator ==(Object other) {
|
432
|
+
return other is ${finalClassName} &&
|
433
|
+
listsAreEqual(props, other.props);
|
434
|
+
}
|
435
|
+
|
436
|
+
@override
|
437
|
+
int get hashCode => listToHashCode(props);
|
438
|
+
|
439
|
+
@override
|
440
|
+
String toString() {
|
441
|
+
return "${finalClassName} \${toJsonString()}";
|
442
|
+
}
|
443
|
+
}
|
444
|
+
|
445
|
+
${subContentParts.join("\n\n")}`;
|
446
|
+
context.generatedTypes.push(className);
|
447
|
+
return result;
|
519
448
|
}
|
520
|
-
${subContentParts.join("\n")}
|
521
449
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
450
|
+
function dartSealedClassFromSchema(schema, context) {
|
451
|
+
const isNullable = outputIsNullable(schema, context);
|
452
|
+
const className = getDartClassName(schema, context);
|
453
|
+
const finalClassName = `${context.modelPrefix}${className}`;
|
454
|
+
const typeName = isNullable ? `${finalClassName}?` : finalClassName;
|
455
|
+
const defaultValue = isNullable ? `null` : `${finalClassName}.empty()`;
|
456
|
+
const discriminatorKey = schema.discriminator;
|
457
|
+
const subTypeParts = [];
|
458
|
+
const subContentParts = [];
|
459
|
+
for (const key of Object.keys(schema.mapping)) {
|
460
|
+
const subSchema = schema.mapping[key];
|
461
|
+
const discriminatorValue = key;
|
462
|
+
const subTypeResult = dartClassFromSchema(subSchema, {
|
463
|
+
clientName: context.clientName,
|
464
|
+
modelPrefix: context.modelPrefix,
|
465
|
+
generatedTypes: context.generatedTypes,
|
466
|
+
instancePath: context.instancePath,
|
467
|
+
schemaPath: `${context.schemaPath}/mapping/${key}`,
|
468
|
+
discriminatorKey,
|
469
|
+
discriminatorValue,
|
470
|
+
discriminatorParentId: className
|
471
|
+
});
|
472
|
+
subTypeParts.push({
|
473
|
+
name: subTypeResult.typeName,
|
474
|
+
value: discriminatorValue
|
475
|
+
});
|
476
|
+
if (subTypeResult.content) {
|
477
|
+
subContentParts.push(subTypeResult.content);
|
478
|
+
}
|
527
479
|
}
|
528
|
-
const
|
529
|
-
const typeName = isNullable ? `${className}?` : className;
|
530
|
-
return {
|
480
|
+
const result = {
|
531
481
|
typeName,
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
}
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
toJsonTemplate: (input) => input,
|
482
|
+
isNullable,
|
483
|
+
defaultValue,
|
484
|
+
fromJson(input) {
|
485
|
+
if (isNullable) {
|
486
|
+
return `${input} is Map<String, dynamic>
|
487
|
+
? ${finalClassName}.fromJson(${input})
|
488
|
+
: null`;
|
489
|
+
}
|
490
|
+
return `${input} is Map<String, dynamic>
|
491
|
+
? ${finalClassName}.fromJson(${input})
|
492
|
+
: ${finalClassName}.empty()`;
|
493
|
+
},
|
494
|
+
toJson(input) {
|
495
|
+
if (context.isOptional) {
|
496
|
+
return `${input}!.toJson()`;
|
497
|
+
}
|
498
|
+
if (schema.nullable) {
|
499
|
+
return `${input}?.toJson()`;
|
500
|
+
}
|
501
|
+
return `${input}.toJson()`;
|
502
|
+
},
|
503
|
+
toQueryString() {
|
504
|
+
return `print(
|
505
|
+
"[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
506
|
+
},
|
558
507
|
content: ""
|
559
508
|
};
|
560
|
-
|
561
|
-
|
562
|
-
let result = "";
|
563
|
-
if (deprecated) {
|
564
|
-
result += `@deprecated
|
565
|
-
`;
|
509
|
+
if (context.generatedTypes.includes(className)) {
|
510
|
+
return result;
|
566
511
|
}
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
512
|
+
const discriminatorProp = validDartIdentifier(schema.discriminator);
|
513
|
+
result.content = `sealed class ${finalClassName} implements ArriModel {
|
514
|
+
String get ${discriminatorProp};
|
515
|
+
const ${finalClassName}();
|
516
|
+
|
517
|
+
factory ${finalClassName}.empty() {
|
518
|
+
return ${subTypeParts[0]?.name}.empty();
|
572
519
|
}
|
573
|
-
|
574
|
-
|
520
|
+
|
521
|
+
factory ${finalClassName}.fromJson(Map<String, dynamic> _input_) {
|
522
|
+
final ${discriminatorProp} = typeFromDynamic<String>(_input_["${schema.discriminator}"], "");
|
523
|
+
switch (${discriminatorProp}) {
|
524
|
+
${subTypeParts.map(
|
525
|
+
(type) => ` case "${type.value}":
|
526
|
+
return ${type.name}.fromJson(_input_);`
|
527
|
+
).join("\n")}
|
528
|
+
default:
|
529
|
+
return ${finalClassName}.empty();
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
factory ${finalClassName}.fromJsonString(String input) {
|
534
|
+
return ${finalClassName}.fromJson(json.decode(input));
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
${subContentParts.join("\n\n")}`;
|
539
|
+
context.generatedTypes.push(className);
|
575
540
|
return result;
|
576
541
|
}
|
577
|
-
|
578
|
-
|
579
|
-
const
|
580
|
-
const
|
581
|
-
const
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
542
|
+
|
543
|
+
function dartEnumFromSchema(schema, context) {
|
544
|
+
const isNullable = outputIsNullable(schema, context);
|
545
|
+
const enumName = getDartClassName(schema, context);
|
546
|
+
const typeName = isNullable ? `${enumName}?` : enumName;
|
547
|
+
const enumValues = schema.enum.map((val) => ({
|
548
|
+
name: camelCase(val, { normalize: true }),
|
549
|
+
serialValue: val
|
550
|
+
}));
|
551
|
+
if (!enumValues.length) {
|
552
|
+
throw new Error(
|
553
|
+
`Enum schemas must have at least one enum value. At ${context.instancePath}.`
|
554
|
+
);
|
555
|
+
}
|
556
|
+
const defaultValue = isNullable ? "null" : `${context.modelPrefix}${enumName}.${enumValues[0]?.name}`;
|
557
|
+
const output = {
|
587
558
|
typeName,
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
def.metadata?.description,
|
592
|
-
def.metadata?.isDeprecated
|
593
|
-
),
|
594
|
-
constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
|
595
|
-
fromJsonTemplate: (input) => {
|
559
|
+
isNullable,
|
560
|
+
defaultValue,
|
561
|
+
fromJson(input, _key) {
|
596
562
|
if (isNullable) {
|
597
|
-
return `${input} is
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
563
|
+
return `${input} is String ? ${context.modelPrefix}${enumName}.fromString(${input}) : null`;
|
564
|
+
}
|
565
|
+
return `${context.modelPrefix}${enumName}.fromString(typeFromDynamic<String>(${input}, ""))`;
|
566
|
+
},
|
567
|
+
toJson(input) {
|
568
|
+
if (context.isOptional) {
|
569
|
+
return `${input}!.serialValue`;
|
570
|
+
}
|
571
|
+
if (schema.nullable) {
|
572
|
+
return `${input}?.serialValue`;
|
573
|
+
}
|
574
|
+
return `${input}.serialValue`;
|
575
|
+
},
|
576
|
+
toQueryString(input, target, key) {
|
577
|
+
if (context.isOptional) {
|
578
|
+
return `if (${input} != null) ${target}.add("${key}=\${${input}!.serialValue}")`;
|
579
|
+
}
|
580
|
+
if (schema.nullable) {
|
581
|
+
return `${target}.add("${key}=\${${input}?.serialValue}")`;
|
582
|
+
}
|
583
|
+
return `${target}.add("${key}=\${${input}.serialValue}")`;
|
584
|
+
},
|
585
|
+
content: ""
|
613
586
|
};
|
614
|
-
|
615
|
-
|
616
|
-
const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
|
617
|
-
const jsonKey = nodePath.split(".").pop() ?? "";
|
618
|
-
const key = camelCaseWrapper(jsonKey);
|
619
|
-
const defaultInitializationTemplate = additionalOptions.isOptional ? `this.${key}` : `required this.${key}`;
|
620
|
-
const { description } = def.metadata ?? {};
|
621
|
-
const defaultToJsonTemplate = (input) => input;
|
622
|
-
switch (def.type) {
|
623
|
-
case "boolean":
|
624
|
-
if (isNullable) {
|
625
|
-
return {
|
626
|
-
typeName: "bool?",
|
627
|
-
fieldTemplate: fieldTemplateString(
|
628
|
-
"bool?",
|
629
|
-
key,
|
630
|
-
description,
|
631
|
-
def.metadata?.isDeprecated
|
632
|
-
),
|
633
|
-
constructorTemplate: defaultInitializationTemplate,
|
634
|
-
fromJsonTemplate: (input) => `nullableTypeFromDynamic<bool>(${input})`,
|
635
|
-
toJsonTemplate: defaultToJsonTemplate,
|
636
|
-
content: ""
|
637
|
-
};
|
638
|
-
}
|
639
|
-
return {
|
640
|
-
typeName: "bool",
|
641
|
-
fieldTemplate: fieldTemplateString(
|
642
|
-
"bool",
|
643
|
-
key,
|
644
|
-
description,
|
645
|
-
def.metadata?.isDeprecated
|
646
|
-
),
|
647
|
-
constructorTemplate: defaultInitializationTemplate,
|
648
|
-
fromJsonTemplate: (input) => `typeFromDynamic<bool>(${input}, false)`,
|
649
|
-
toJsonTemplate: defaultToJsonTemplate,
|
650
|
-
content: ""
|
651
|
-
};
|
652
|
-
case "float32":
|
653
|
-
case "float64":
|
654
|
-
if (isNullable) {
|
655
|
-
return {
|
656
|
-
typeName: "double?",
|
657
|
-
fieldTemplate: fieldTemplateString(
|
658
|
-
"double?",
|
659
|
-
key,
|
660
|
-
description,
|
661
|
-
def.metadata?.isDeprecated
|
662
|
-
),
|
663
|
-
constructorTemplate: defaultInitializationTemplate,
|
664
|
-
fromJsonTemplate: (input) => `nullableDoubleFromDynamic(${input})`,
|
665
|
-
toJsonTemplate: defaultToJsonTemplate,
|
666
|
-
content: ""
|
667
|
-
};
|
668
|
-
}
|
669
|
-
return {
|
670
|
-
typeName: "double",
|
671
|
-
fieldTemplate: fieldTemplateString(
|
672
|
-
"double",
|
673
|
-
key,
|
674
|
-
description,
|
675
|
-
def.metadata?.isDeprecated
|
676
|
-
),
|
677
|
-
constructorTemplate: defaultInitializationTemplate,
|
678
|
-
fromJsonTemplate: (input) => `doubleFromDynamic(${input}, 0)`,
|
679
|
-
toJsonTemplate: defaultToJsonTemplate,
|
680
|
-
content: ""
|
681
|
-
};
|
682
|
-
case "int16":
|
683
|
-
case "int32":
|
684
|
-
case "int8":
|
685
|
-
case "uint16":
|
686
|
-
case "uint32":
|
687
|
-
case "uint8":
|
688
|
-
if (isNullable) {
|
689
|
-
return {
|
690
|
-
typeName: "int?",
|
691
|
-
fieldTemplate: fieldTemplateString(
|
692
|
-
"int?",
|
693
|
-
key,
|
694
|
-
description,
|
695
|
-
def.metadata?.isDeprecated
|
696
|
-
),
|
697
|
-
constructorTemplate: defaultInitializationTemplate,
|
698
|
-
fromJsonTemplate: (input) => `nullableIntFromDynamic(${input})`,
|
699
|
-
toJsonTemplate: defaultToJsonTemplate,
|
700
|
-
content: ""
|
701
|
-
};
|
702
|
-
}
|
703
|
-
return {
|
704
|
-
typeName: "int",
|
705
|
-
fieldTemplate: fieldTemplateString(
|
706
|
-
`int`,
|
707
|
-
key,
|
708
|
-
description,
|
709
|
-
def.metadata?.isDeprecated
|
710
|
-
),
|
711
|
-
constructorTemplate: defaultInitializationTemplate,
|
712
|
-
fromJsonTemplate: (input) => `intFromDynamic(${input}, 0)`,
|
713
|
-
toJsonTemplate: defaultToJsonTemplate,
|
714
|
-
content: ""
|
715
|
-
};
|
716
|
-
case "int64":
|
717
|
-
case "uint64":
|
718
|
-
if (isNullable) {
|
719
|
-
return {
|
720
|
-
typeName: "BigInt?",
|
721
|
-
fieldTemplate: fieldTemplateString(
|
722
|
-
`BigInt?`,
|
723
|
-
key,
|
724
|
-
description,
|
725
|
-
def.metadata?.isDeprecated
|
726
|
-
),
|
727
|
-
constructorTemplate: defaultInitializationTemplate,
|
728
|
-
fromJsonTemplate: (input) => `nullableBigIntFromDynamic(${input})`,
|
729
|
-
toJsonTemplate: (input) => `${input}?.toString()`,
|
730
|
-
content: ""
|
731
|
-
};
|
732
|
-
}
|
733
|
-
return {
|
734
|
-
typeName: "BigInt",
|
735
|
-
fieldTemplate: fieldTemplateString(
|
736
|
-
`BigInt`,
|
737
|
-
key,
|
738
|
-
description,
|
739
|
-
def.metadata?.isDeprecated
|
740
|
-
),
|
741
|
-
constructorTemplate: defaultInitializationTemplate,
|
742
|
-
fromJsonTemplate: (input) => `bigIntFromDynamic(${input}, BigInt.zero)`,
|
743
|
-
toJsonTemplate: (input) => `${input}.toString()`,
|
744
|
-
content: ""
|
745
|
-
};
|
746
|
-
case "timestamp":
|
747
|
-
if (isNullable) {
|
748
|
-
return {
|
749
|
-
typeName: "DateTime?",
|
750
|
-
fieldTemplate: fieldTemplateString(
|
751
|
-
"DateTime?",
|
752
|
-
key,
|
753
|
-
description,
|
754
|
-
def.metadata?.isDeprecated
|
755
|
-
),
|
756
|
-
constructorTemplate: defaultInitializationTemplate,
|
757
|
-
fromJsonTemplate: (input) => `nullableDateTimeFromDynamic(${input})`,
|
758
|
-
toJsonTemplate: (input) => `${input}?.toUtc().toIso8601String()`,
|
759
|
-
content: ""
|
760
|
-
};
|
761
|
-
}
|
762
|
-
return {
|
763
|
-
typeName: "DateTime",
|
764
|
-
fieldTemplate: fieldTemplateString(
|
765
|
-
"DateTime",
|
766
|
-
key,
|
767
|
-
description,
|
768
|
-
def.metadata?.isDeprecated
|
769
|
-
),
|
770
|
-
constructorTemplate: defaultInitializationTemplate,
|
771
|
-
fromJsonTemplate: (input) => `dateTimeFromDynamic(
|
772
|
-
${input},
|
773
|
-
DateTime.fromMillisecondsSinceEpoch(0),
|
774
|
-
)`,
|
775
|
-
toJsonTemplate: (input) => `${input}.toUtc().toIso8601String()`,
|
776
|
-
content: ""
|
777
|
-
};
|
778
|
-
case "string":
|
779
|
-
if (isNullable) {
|
780
|
-
return {
|
781
|
-
typeName: "String?",
|
782
|
-
fieldTemplate: fieldTemplateString(
|
783
|
-
"String?",
|
784
|
-
key,
|
785
|
-
description,
|
786
|
-
def.metadata?.isDeprecated
|
787
|
-
),
|
788
|
-
constructorTemplate: defaultInitializationTemplate,
|
789
|
-
fromJsonTemplate: (input) => `nullableTypeFromDynamic<String>(${input})`,
|
790
|
-
toJsonTemplate: defaultToJsonTemplate,
|
791
|
-
content: ""
|
792
|
-
};
|
793
|
-
}
|
794
|
-
return {
|
795
|
-
typeName: "String",
|
796
|
-
fieldTemplate: fieldTemplateString(
|
797
|
-
"String",
|
798
|
-
key,
|
799
|
-
description,
|
800
|
-
def.metadata?.isDeprecated
|
801
|
-
),
|
802
|
-
constructorTemplate: defaultInitializationTemplate,
|
803
|
-
fromJsonTemplate: (input) => `typeFromDynamic<String>(${input}, "")`,
|
804
|
-
toJsonTemplate: defaultToJsonTemplate,
|
805
|
-
content: ""
|
806
|
-
};
|
807
|
-
default:
|
808
|
-
return {
|
809
|
-
typeName: "dynamic",
|
810
|
-
fieldTemplate: fieldTemplateString(
|
811
|
-
"dynamic",
|
812
|
-
key,
|
813
|
-
description,
|
814
|
-
def.metadata?.isDeprecated
|
815
|
-
),
|
816
|
-
constructorTemplate: defaultInitializationTemplate,
|
817
|
-
fromJsonTemplate: (input) => input,
|
818
|
-
toJsonTemplate: defaultToJsonTemplate,
|
819
|
-
content: ""
|
820
|
-
};
|
821
|
-
}
|
822
|
-
}
|
823
|
-
function dartEnumFromJtdSchema(nodePath, def, additionalOptions) {
|
824
|
-
const isNullable = additionalOptions.isOptional || (def.nullable ?? false);
|
825
|
-
const jsonKey = nodePath.split(".").pop() ?? "";
|
826
|
-
const key = camelCaseWrapper(jsonKey);
|
827
|
-
let className = def.metadata?.id ? pascalCase(def.metadata.id) : void 0;
|
828
|
-
if (!className) {
|
829
|
-
className = pascalCase(nodePath.split(".").join("_"));
|
830
|
-
}
|
831
|
-
const valNames = [];
|
832
|
-
const fieldParts = [];
|
833
|
-
for (const val of def.enum) {
|
834
|
-
valNames.push(`${camelCaseWrapper(val)}`);
|
835
|
-
fieldParts.push(`${camelCaseWrapper(val)}("${val}")`);
|
587
|
+
if (context.generatedTypes.includes(enumName)) {
|
588
|
+
return output;
|
836
589
|
}
|
837
|
-
|
838
|
-
${
|
839
|
-
|
840
|
-
|
590
|
+
output.content = `enum ${context.modelPrefix}${enumName} implements Comparable<${context.modelPrefix}${enumName}> {
|
591
|
+
${enumValues.map((val) => ` ${val.name}("${val.serialValue}")`).join(",\n")};
|
592
|
+
|
593
|
+
const ${context.modelPrefix}${enumName}(this.serialValue);
|
594
|
+
final String serialValue;
|
841
595
|
|
842
|
-
factory ${
|
843
|
-
for(final
|
844
|
-
if(
|
845
|
-
return
|
596
|
+
factory ${context.modelPrefix}${enumName}.fromString(String input) {
|
597
|
+
for (final val in values) {
|
598
|
+
if (val.serialValue == input) {
|
599
|
+
return val;
|
846
600
|
}
|
847
601
|
}
|
848
|
-
return ${
|
602
|
+
return ${enumValues[0].name};
|
849
603
|
}
|
850
604
|
|
851
605
|
@override
|
852
|
-
compareTo(${
|
606
|
+
int compareTo(${enumName} other) => name.compareTo(other.name);
|
853
607
|
}`;
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
608
|
+
context.generatedTypes.push(enumName);
|
609
|
+
return output;
|
610
|
+
}
|
611
|
+
|
612
|
+
function dartStringFromSchema(schema, context) {
|
613
|
+
const isNullable = outputIsNullable(schema, context);
|
614
|
+
const typeName = isNullable ? `String?` : "String";
|
615
|
+
const defaultValue = isNullable ? "null" : '""';
|
859
616
|
return {
|
860
|
-
typeName
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
def.metadata?.description,
|
865
|
-
def.metadata?.isDeprecated
|
866
|
-
),
|
867
|
-
constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
|
868
|
-
fromJsonTemplate: (input) => {
|
617
|
+
typeName,
|
618
|
+
isNullable,
|
619
|
+
defaultValue,
|
620
|
+
fromJson(input, _key) {
|
869
621
|
if (isNullable) {
|
870
|
-
return
|
622
|
+
return `nullableTypeFromDynamic<String>(${input})`;
|
871
623
|
}
|
872
|
-
return
|
624
|
+
return `typeFromDynamic<String>(${input}, "")`;
|
625
|
+
},
|
626
|
+
toJson(input, _target, _key) {
|
627
|
+
return input;
|
873
628
|
},
|
874
|
-
|
875
|
-
|
629
|
+
toQueryString(input, target, key) {
|
630
|
+
if (context.isOptional) {
|
631
|
+
return `if (${input} != null) ${target}.add("${key}=$${input}")`;
|
632
|
+
}
|
633
|
+
return `${target}.add("${key}=$${input}")`;
|
634
|
+
},
|
635
|
+
content: ""
|
876
636
|
};
|
877
637
|
}
|
878
|
-
function
|
879
|
-
const isNullable =
|
880
|
-
const
|
881
|
-
const
|
882
|
-
const innerType = dartTypeFromJtdSchema(`${nodePath}.Value`, def.values, {
|
883
|
-
existingClassNames: additionalOptions.existingClassNames,
|
884
|
-
isOptional: false
|
885
|
-
});
|
886
|
-
const typeName = `Map<String, ${innerType.typeName}>${isNullable ? "?" : ""}`;
|
638
|
+
function dartBoolFromSchema(schema, context) {
|
639
|
+
const isNullable = outputIsNullable(schema, context);
|
640
|
+
const typeName = isNullable ? "bool?" : "bool";
|
641
|
+
const defaultValue = isNullable ? "null" : "false";
|
887
642
|
return {
|
888
|
-
typeName
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
)
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
643
|
+
typeName,
|
644
|
+
isNullable,
|
645
|
+
defaultValue,
|
646
|
+
fromJson(input, _key) {
|
647
|
+
if (isNullable) {
|
648
|
+
return `nullableTypeFromDynamic<bool>(${input})`;
|
649
|
+
}
|
650
|
+
return `typeFromDynamic<bool>(${input}, false)`;
|
651
|
+
},
|
652
|
+
toJson(input, _target, _key) {
|
653
|
+
return input;
|
654
|
+
},
|
655
|
+
toQueryString(input, target, key) {
|
656
|
+
if (context.isOptional) {
|
657
|
+
return `if (${input} != null) ${target}.add("${key}=$${input}")`;
|
658
|
+
}
|
659
|
+
return `${target}.add("${key}=$${input}")`;
|
660
|
+
},
|
661
|
+
content: ""
|
906
662
|
};
|
907
663
|
}
|
908
|
-
function
|
909
|
-
const
|
910
|
-
const
|
911
|
-
const
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
if (!isSchemaFormProperties(childDef)) {
|
920
|
-
return;
|
921
|
-
}
|
922
|
-
const child = dartClassFromJtdSchema(
|
923
|
-
`${nodePath}.${camelCaseWrapper(discKeyValue.toLowerCase())}`,
|
924
|
-
childDef,
|
925
|
-
{
|
926
|
-
parentId: className,
|
927
|
-
isOptional: false,
|
928
|
-
existingClassNames: additionalOptions.existingClassNames,
|
929
|
-
discriminatorOptions: {
|
930
|
-
discriminatorKey,
|
931
|
-
discriminatorValue: discKeyValue,
|
932
|
-
discriminatorParentClassName: className
|
933
|
-
}
|
664
|
+
function dartDateTimeFromSchema(schema, context) {
|
665
|
+
const isNullable = outputIsNullable(schema, context);
|
666
|
+
const typeName = isNullable ? "DateTime?" : "DateTime";
|
667
|
+
const defaultValue = isNullable ? "null" : "DateTime.now()";
|
668
|
+
return {
|
669
|
+
typeName,
|
670
|
+
isNullable,
|
671
|
+
defaultValue,
|
672
|
+
fromJson(input, _key) {
|
673
|
+
if (isNullable) {
|
674
|
+
return `nullableDateTimeFromDynamic(${input})`;
|
934
675
|
}
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
676
|
+
return `dateTimeFromDynamic(${input}, DateTime.now())`;
|
677
|
+
},
|
678
|
+
toJson(input, _target, _key) {
|
679
|
+
if (context.isOptional) {
|
680
|
+
return `${input}!.toUtc().toIso8601String()`;
|
681
|
+
}
|
682
|
+
if (schema.nullable) {
|
683
|
+
return `${input}?.toUtc().toIso8601String()`;
|
684
|
+
}
|
685
|
+
return `${input}.toUtc().toIso8601String()`;
|
686
|
+
},
|
687
|
+
toQueryString(input, target, key) {
|
688
|
+
if (context.isOptional) {
|
689
|
+
return `if (${input} != null) ${target}.add("${key}=\${${input}!.toUtc().toIso8601String()}")`;
|
690
|
+
}
|
691
|
+
if (schema.nullable) {
|
692
|
+
return `${target}.add("${key}=\${${input}?.toUtc().toIso8601String()}")`;
|
693
|
+
}
|
694
|
+
return `${target}.add("${key}=\${${input}.toUtc().toIso8601String()}")`;
|
695
|
+
},
|
696
|
+
content: ""
|
697
|
+
};
|
698
|
+
}
|
699
|
+
function dartDoubleFromSchema(schema, context) {
|
700
|
+
const isNullable = outputIsNullable(schema, context);
|
701
|
+
const typeName = isNullable ? "double?" : "double";
|
702
|
+
const defaultValue = isNullable ? "null" : "0.0";
|
703
|
+
return {
|
704
|
+
typeName,
|
705
|
+
isNullable,
|
706
|
+
defaultValue,
|
707
|
+
fromJson(input, _key) {
|
708
|
+
if (isNullable) {
|
709
|
+
return `nullableDoubleFromDynamic(${input})`;
|
710
|
+
}
|
711
|
+
return `doubleFromDynamic(${input}, 0.0)`;
|
712
|
+
},
|
713
|
+
toJson(input, _, __) {
|
714
|
+
return input;
|
715
|
+
},
|
716
|
+
toQueryString(input, target, key) {
|
717
|
+
if (context.isOptional) {
|
718
|
+
return `if (${input} != null) ${target}.add("${key}=$${input}")`;
|
719
|
+
}
|
720
|
+
return `${target}.add("${key}=$${input}")`;
|
721
|
+
},
|
722
|
+
content: ""
|
723
|
+
};
|
724
|
+
}
|
725
|
+
function dartIntFromSchema(schema, context) {
|
726
|
+
const isNullable = outputIsNullable(schema, context);
|
727
|
+
const typeName = isNullable ? "int?" : "int";
|
728
|
+
const defaultValue = isNullable ? "null" : "0";
|
729
|
+
return {
|
730
|
+
typeName,
|
731
|
+
isNullable,
|
732
|
+
defaultValue,
|
733
|
+
fromJson(input, _key) {
|
734
|
+
if (isNullable) {
|
735
|
+
return `nullableIntFromDynamic(${input})`;
|
736
|
+
}
|
737
|
+
return `intFromDynamic(${input}, 0)`;
|
738
|
+
},
|
739
|
+
toJson(input) {
|
740
|
+
return input;
|
741
|
+
},
|
742
|
+
toQueryString(input, target, key) {
|
743
|
+
if (context.isOptional) {
|
744
|
+
return `if (${input} != null) ${target}.add("${key}=$${input}")`;
|
745
|
+
}
|
746
|
+
return `${target}.add("${key}=$${input}")`;
|
747
|
+
},
|
748
|
+
content: ""
|
749
|
+
};
|
750
|
+
}
|
751
|
+
function dartBigIntFromSchema(schema, context) {
|
752
|
+
const isNullable = outputIsNullable(schema, context);
|
753
|
+
const typeName = isNullable ? "BigInt?" : "BigInt";
|
754
|
+
const defaultValue = isNullable ? "null" : "BigInt.zero";
|
755
|
+
return {
|
756
|
+
typeName,
|
757
|
+
isNullable,
|
758
|
+
defaultValue,
|
759
|
+
fromJson(input, _key) {
|
760
|
+
if (isNullable) {
|
761
|
+
return `nullableBigIntFromDynamic(${input})`;
|
762
|
+
}
|
763
|
+
return `bigIntFromDynamic(${input}, BigInt.zero)`;
|
764
|
+
},
|
765
|
+
toJson(input, _target, _key) {
|
766
|
+
if (context.isOptional) {
|
767
|
+
return `${input}!.toString()`;
|
768
|
+
}
|
769
|
+
if (schema.nullable) {
|
770
|
+
return `${input}?.toString()`;
|
771
|
+
}
|
772
|
+
return `${input}.toString()`;
|
773
|
+
},
|
774
|
+
toQueryString(input, target, key) {
|
775
|
+
if (context.isOptional) {
|
776
|
+
return `if (${input} != null) ${target}.add("${key}=$${input}")`;
|
777
|
+
}
|
778
|
+
return `${target}.add("${key}=$${input}")`;
|
779
|
+
},
|
780
|
+
content: ""
|
781
|
+
};
|
782
|
+
}
|
783
|
+
|
784
|
+
function dartRpcFromSchema(schema, context) {
|
785
|
+
switch (schema.transport) {
|
786
|
+
case "http":
|
787
|
+
return dartHttpRpcFromSchema(schema, context);
|
788
|
+
case "ws":
|
789
|
+
return dartWsRpcFromSchema(schema, context);
|
790
|
+
default:
|
791
|
+
console.warn(
|
792
|
+
`[WARNING] unsupported transport "${schema.transport}". Skipping ${context.instancePath}.`
|
951
793
|
);
|
794
|
+
return "";
|
795
|
+
}
|
796
|
+
}
|
797
|
+
function dartHttpRpcFromSchema(schema, context) {
|
798
|
+
const functionName = getFunctionName(context.instancePath);
|
799
|
+
let responseType = "void";
|
800
|
+
let paramsType = "";
|
801
|
+
if (schema.response) {
|
802
|
+
responseType = `${context.modelPrefix}${validDartClassName(schema.response, context.modelPrefix)}`;
|
803
|
+
}
|
804
|
+
if (schema.params) {
|
805
|
+
paramsType = `${context.modelPrefix}${validDartClassName(schema.params, context.modelPrefix)}`;
|
806
|
+
}
|
807
|
+
if (schema.isEventStream) {
|
808
|
+
return `EventSource<${responseType}> ${functionName}(
|
809
|
+
${paramsType ? `${paramsType} params, ` : ""} {
|
810
|
+
void Function(${responseType} data, EventSource<${responseType}> connection)? onMessage,
|
811
|
+
void Function(http.StreamedResponse response, EventSource<${responseType}> connection)? onOpen,
|
812
|
+
void Function(EventSource<${responseType}> connection)? onClose,
|
813
|
+
void Function(ArriError error, EventSource<${responseType}> connection)? onError,
|
814
|
+
Duration? retryDelay,
|
815
|
+
int? maxRetryCount,
|
816
|
+
String? lastEventId,
|
817
|
+
}) {
|
818
|
+
return parsedArriSseRequest(
|
819
|
+
"$_baseUrl${schema.path}",
|
820
|
+
method: HttpMethod.${schema.method.toLowerCase()},
|
821
|
+
httpClient: _httpClient,
|
822
|
+
headers: _headers,
|
823
|
+
clientVersion: _clientVersion,
|
824
|
+
retryDelay: retryDelay,
|
825
|
+
maxRetryCount: maxRetryCount,
|
826
|
+
lastEventId: lastEventId,
|
827
|
+
${paramsType ? "params: params.toJson()," : ""}
|
828
|
+
parser: (body) ${schema.response ? `=> ${responseType}.fromJsonString(body)` : `{}`},
|
829
|
+
onMessage: onMessage,
|
830
|
+
onOpen: onOpen,
|
831
|
+
onClose: onClose,
|
832
|
+
onError: onError,
|
833
|
+
);
|
834
|
+
}`;
|
835
|
+
}
|
836
|
+
return `Future<${responseType}> ${functionName}(${paramsType ? `${paramsType} params` : ""}) async {
|
837
|
+
return parsedArriRequest(
|
838
|
+
"$_baseUrl${schema.path}",
|
839
|
+
method: HttpMethod.${schema.method.toLowerCase()},
|
840
|
+
httpClient: _httpClient,
|
841
|
+
headers: _headers,
|
842
|
+
clientVersion: _clientVersion,
|
843
|
+
${paramsType ? "params: params.toJson()," : ""}
|
844
|
+
parser: (body) ${schema.response ? `=> ${responseType}.fromJsonString(body)` : "{}"},
|
845
|
+
);
|
846
|
+
}`;
|
847
|
+
}
|
848
|
+
function getFunctionName(instancePath) {
|
849
|
+
const parts = instancePath.split(".");
|
850
|
+
return parts.pop() ?? "";
|
851
|
+
}
|
852
|
+
function dartWsRpcFromSchema(schema, context) {
|
853
|
+
const functionName = getFunctionName(context.instancePath);
|
854
|
+
let responseType;
|
855
|
+
let paramsType;
|
856
|
+
if (schema.response) {
|
857
|
+
responseType = `${context.modelPrefix}${validDartClassName(schema.response, context.modelPrefix)}`;
|
858
|
+
}
|
859
|
+
if (schema.params) {
|
860
|
+
paramsType = `${context.modelPrefix}${validDartClassName(schema.params, context.modelPrefix)}`;
|
861
|
+
}
|
862
|
+
return `Future<ArriWebsocketController<${responseType ?? "void"}, ${paramsType ?? "void"}>> ${functionName}() {
|
863
|
+
return arriWebsocketRequest(
|
864
|
+
"$_baseUrl${schema.path}",
|
865
|
+
headers: _headers,
|
866
|
+
clientVersion: _clientVersion,
|
867
|
+
parser: (msg) ${responseType ? `=> ${responseType}.fromJsonString(msg)` : "{}"},
|
868
|
+
serializer: (msg) ${paramsType ? "=> msg.toJsonString()" : '=> ""'},
|
869
|
+
);
|
870
|
+
}`;
|
871
|
+
}
|
872
|
+
function dartServiceFromSchema(schema, context) {
|
873
|
+
const rpcParts = [];
|
874
|
+
const subServices = [];
|
875
|
+
const subServiceParts = [];
|
876
|
+
const serviceName = getServiceName(
|
877
|
+
context.instancePath,
|
878
|
+
context.clientName
|
879
|
+
);
|
880
|
+
for (const key of Object.keys(schema)) {
|
881
|
+
const subSchema = schema[key];
|
882
|
+
if (isServiceDefinition(subSchema)) {
|
883
|
+
const subSchemaResult = dartServiceFromSchema(subSchema, {
|
884
|
+
clientName: context.clientName,
|
885
|
+
modelPrefix: context.modelPrefix,
|
886
|
+
generatedTypes: context.generatedTypes,
|
887
|
+
instancePath: `${context.instancePath}.${key}`,
|
888
|
+
schemaPath: `${context.schemaPath}.${key}`
|
889
|
+
});
|
890
|
+
if (subSchemaResult) {
|
891
|
+
subServiceParts.push(subSchemaResult);
|
892
|
+
subServices.push({
|
893
|
+
key: validDartIdentifier(key),
|
894
|
+
name: getServiceName(
|
895
|
+
`${context.instancePath}.${key}`,
|
896
|
+
context.clientName
|
897
|
+
)
|
898
|
+
});
|
899
|
+
}
|
900
|
+
continue;
|
952
901
|
}
|
953
|
-
|
954
|
-
|
902
|
+
if (isRpcDefinition(subSchema)) {
|
903
|
+
const subSchemaResult = dartRpcFromSchema(subSchema, {
|
904
|
+
clientName: context.clientName,
|
905
|
+
modelPrefix: context.modelPrefix,
|
906
|
+
generatedTypes: context.generatedTypes,
|
907
|
+
instancePath: `${context.instancePath}.${key}`,
|
908
|
+
schemaPath: `${context.schemaPath}.${key}`
|
909
|
+
});
|
910
|
+
if (subSchemaResult) {
|
911
|
+
rpcParts.push(subSchemaResult);
|
912
|
+
}
|
913
|
+
continue;
|
955
914
|
}
|
956
|
-
|
957
|
-
|
915
|
+
console.warn(
|
916
|
+
`Unknown schema in procedures at "${context.instancePath}".`
|
958
917
|
);
|
959
918
|
}
|
960
|
-
|
919
|
+
return `class ${serviceName}{
|
920
|
+
final http.Client? _httpClient;
|
921
|
+
final String _baseUrl;
|
922
|
+
final String _clientVersion = "${context.clientVersion ?? ""}";
|
923
|
+
late final FutureOr<Map<String, String>> Function()? _headers;
|
924
|
+
${serviceName}({
|
925
|
+
http.Client? httpClient,
|
926
|
+
required String baseUrl,
|
927
|
+
FutureOr<Map<String, String>> Function()? headers,
|
928
|
+
}) : _httpClient = httpClient,
|
929
|
+
_baseUrl = baseUrl,
|
930
|
+
_headers = headers;
|
931
|
+
|
932
|
+
${rpcParts.join("\n\n")}
|
933
|
+
|
934
|
+
${subServices.map(
|
935
|
+
(service) => ` ${service.name} get ${service.key} => ${service.name}(
|
936
|
+
baseUrl: _baseUrl,
|
937
|
+
headers: _headers,
|
938
|
+
httpClient: _httpClient,
|
939
|
+
);`
|
940
|
+
).join("\n\n")}
|
961
941
|
}
|
962
|
-
${
|
963
|
-
|
964
|
-
|
965
|
-
|
942
|
+
${subServiceParts.join("\n\n")}`;
|
943
|
+
}
|
944
|
+
function getServiceName(instancePath, clientName) {
|
945
|
+
return validDartClassName(
|
946
|
+
`${clientName}_${instancePath.split(".").join("_")}_Service`,
|
947
|
+
""
|
948
|
+
);
|
949
|
+
}
|
950
|
+
|
951
|
+
function dartMapFromSchema(schema, context) {
|
952
|
+
const isNullable = outputIsNullable(schema, context);
|
953
|
+
const innerType = dartTypeFromSchema(schema.values, {
|
954
|
+
clientName: context.clientName,
|
955
|
+
modelPrefix: context.modelPrefix,
|
956
|
+
generatedTypes: context.generatedTypes,
|
957
|
+
instancePath: `${context.instancePath}/[entry]`,
|
958
|
+
schemaPath: `${context.schemaPath}/values`
|
959
|
+
});
|
960
|
+
const typeName = isNullable ? `Map<String, ${innerType.typeName}>?` : `Map<String, ${innerType.typeName}>`;
|
961
|
+
const defaultValue = isNullable ? "null" : "{}";
|
966
962
|
return {
|
967
963
|
typeName,
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
def.metadata?.description,
|
972
|
-
def.metadata?.isDeprecated
|
973
|
-
),
|
974
|
-
constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
|
975
|
-
fromJsonTemplate: (input) => {
|
964
|
+
isNullable,
|
965
|
+
defaultValue,
|
966
|
+
fromJson(input) {
|
976
967
|
if (isNullable) {
|
977
|
-
return `${input} is Map<String, dynamic>
|
968
|
+
return `${input} is Map<String, dynamic>
|
969
|
+
? (${input} as Map<String, dynamic>).map(
|
970
|
+
(_key_, _val_) => MapEntry(
|
971
|
+
_key_,
|
972
|
+
${innerType.fromJson("_val_")},
|
973
|
+
),
|
974
|
+
)
|
975
|
+
: null`;
|
978
976
|
}
|
979
|
-
return `${
|
977
|
+
return `${input} is Map<String, dynamic>
|
978
|
+
? (${input} as Map<String, dynamic>).map(
|
979
|
+
(_key_, _val_) => MapEntry(
|
980
|
+
_key_,
|
981
|
+
${innerType.fromJson("_val_")},
|
982
|
+
),
|
983
|
+
)
|
984
|
+
: <String, ${innerType.typeName}>{}`;
|
980
985
|
},
|
981
|
-
|
982
|
-
if (
|
983
|
-
return `${input}
|
986
|
+
toJson(input) {
|
987
|
+
if (context.isOptional) {
|
988
|
+
return `${input}!.map((_key_, _val_) => MapEntry(_key_, ${innerType.toJson("_val_", "", "")},),)`;
|
984
989
|
}
|
985
|
-
|
990
|
+
if (schema.nullable) {
|
991
|
+
return `${input}?.map((_key_, _val_) => MapEntry(_key_, ${innerType.toJson("_val_", "", "")},),)`;
|
992
|
+
}
|
993
|
+
return `${input}.map((_key_, _val_) => MapEntry(_key_, ${innerType.toJson("_val_", "", "")},),)`;
|
994
|
+
},
|
995
|
+
toQueryString() {
|
996
|
+
return `print(
|
997
|
+
"[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
986
998
|
},
|
987
|
-
content
|
999
|
+
content: innerType.content
|
988
1000
|
};
|
989
1001
|
}
|
990
|
-
|
991
|
-
|
992
|
-
const
|
993
|
-
const className =
|
994
|
-
|
995
|
-
|
1002
|
+
|
1003
|
+
function dartRefFromSchema(schema, context) {
|
1004
|
+
const isNullable = outputIsNullable(schema, context);
|
1005
|
+
const className = sanitizeIdentifier(
|
1006
|
+
pascalCase(schema.ref, { normalize: true })
|
1007
|
+
);
|
1008
|
+
const finalClassName = `${context.modelPrefix}${className}`;
|
1009
|
+
const typeName = isNullable ? `${finalClassName}?` : finalClassName;
|
1010
|
+
const defaultValue = isNullable ? `null` : `${finalClassName}.empty()`;
|
996
1011
|
return {
|
997
1012
|
typeName,
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
def.metadata?.description,
|
1002
|
-
def.metadata?.isDeprecated
|
1003
|
-
),
|
1004
|
-
constructorTemplate: additionalOptions.isOptional ? `this.${key}` : `required this.${key}`,
|
1005
|
-
fromJsonTemplate(input) {
|
1013
|
+
isNullable,
|
1014
|
+
defaultValue,
|
1015
|
+
fromJson(input) {
|
1006
1016
|
if (isNullable) {
|
1007
|
-
return `${input} is Map<String, dynamic>
|
1017
|
+
return `${input} is Map<String, dynamic>
|
1018
|
+
? ${finalClassName}.fromJson(${input})
|
1019
|
+
: null`;
|
1008
1020
|
}
|
1009
|
-
return `${
|
1021
|
+
return `${input} is Map<String, dynamic>
|
1022
|
+
? ${finalClassName}.fromJson(${input})
|
1023
|
+
: ${finalClassName}.empty()`;
|
1010
1024
|
},
|
1011
|
-
|
1012
|
-
if (
|
1025
|
+
toJson(input) {
|
1026
|
+
if (context.isOptional) {
|
1027
|
+
return `${input}!.toJson()`;
|
1028
|
+
}
|
1029
|
+
if (schema.nullable) {
|
1013
1030
|
return `${input}?.toJson()`;
|
1014
1031
|
}
|
1015
1032
|
return `${input}.toJson()`;
|
1016
1033
|
},
|
1034
|
+
toQueryString() {
|
1035
|
+
return `print(
|
1036
|
+
"[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
|
1037
|
+
},
|
1017
1038
|
content: ""
|
1018
1039
|
};
|
1019
1040
|
}
|
1020
1041
|
|
1021
|
-
|
1042
|
+
const dartClientGenerator = defineClientGeneratorPlugin(
|
1043
|
+
(options) => {
|
1044
|
+
return {
|
1045
|
+
async generator(def) {
|
1046
|
+
if (!options.outputFile) {
|
1047
|
+
throw new Error(
|
1048
|
+
'Missing "outputFile" cannot generate dart code'
|
1049
|
+
);
|
1050
|
+
}
|
1051
|
+
try {
|
1052
|
+
const result = createDartClient(def, options);
|
1053
|
+
const destination = path.resolve(options.outputFile);
|
1054
|
+
await fs.writeFile(destination, result);
|
1055
|
+
if (options.format !== false) {
|
1056
|
+
execSync(`dart format ${destination}`, {
|
1057
|
+
stdio: "inherit"
|
1058
|
+
});
|
1059
|
+
}
|
1060
|
+
} catch (err) {
|
1061
|
+
console.error(err);
|
1062
|
+
}
|
1063
|
+
},
|
1064
|
+
options
|
1065
|
+
};
|
1066
|
+
}
|
1067
|
+
);
|
1068
|
+
function createDartClient(def, options) {
|
1069
|
+
const typeParts = [];
|
1070
|
+
const context = {
|
1071
|
+
clientName: options.clientName ?? "Client",
|
1072
|
+
modelPrefix: options.modelPrefix ?? "",
|
1073
|
+
generatedTypes: [],
|
1074
|
+
instancePath: "",
|
1075
|
+
schemaPath: "",
|
1076
|
+
clientVersion: def.info?.version
|
1077
|
+
};
|
1078
|
+
const services = unflattenProcedures(def.procedures);
|
1079
|
+
const subServices = [];
|
1080
|
+
const subServiceParts = [];
|
1081
|
+
const rpcParts = [];
|
1082
|
+
for (const key of Object.keys(services)) {
|
1083
|
+
const subSchema = services[key];
|
1084
|
+
if (isServiceDefinition(subSchema)) {
|
1085
|
+
const service = dartServiceFromSchema(subSchema, {
|
1086
|
+
clientName: context.clientName,
|
1087
|
+
modelPrefix: context.modelPrefix,
|
1088
|
+
generatedTypes: context.generatedTypes,
|
1089
|
+
instancePath: key,
|
1090
|
+
schemaPath: `procedures.${key}`,
|
1091
|
+
clientVersion: context.clientVersion
|
1092
|
+
});
|
1093
|
+
if (service) {
|
1094
|
+
subServiceParts.push(service);
|
1095
|
+
subServices.push({
|
1096
|
+
key: validDartIdentifier(key),
|
1097
|
+
name: getServiceName(key, context.clientName)
|
1098
|
+
});
|
1099
|
+
}
|
1100
|
+
continue;
|
1101
|
+
}
|
1102
|
+
if (isRpcDefinition(subSchema)) {
|
1103
|
+
const rpc = dartRpcFromSchema(subSchema, {
|
1104
|
+
clientName: context.clientName,
|
1105
|
+
modelPrefix: context.modelPrefix,
|
1106
|
+
generatedTypes: context.generatedTypes,
|
1107
|
+
instancePath: key,
|
1108
|
+
schemaPath: `procedures.${key}`
|
1109
|
+
});
|
1110
|
+
if (rpc) {
|
1111
|
+
rpcParts.push(rpc);
|
1112
|
+
}
|
1113
|
+
continue;
|
1114
|
+
}
|
1115
|
+
console.warn(`Unknown schema in procedures at "${key}"`);
|
1116
|
+
}
|
1117
|
+
for (const key of Object.keys(def.definitions)) {
|
1118
|
+
const subDef = def.definitions[key];
|
1119
|
+
const result = dartTypeFromSchema(subDef, {
|
1120
|
+
clientName: context.clientName,
|
1121
|
+
modelPrefix: context.modelPrefix,
|
1122
|
+
generatedTypes: context.generatedTypes,
|
1123
|
+
instancePath: `/${key}`,
|
1124
|
+
schemaPath: `/${key}`
|
1125
|
+
});
|
1126
|
+
if (result.content) {
|
1127
|
+
typeParts.push(result.content);
|
1128
|
+
}
|
1129
|
+
}
|
1130
|
+
if (rpcParts.length === 0 && subServiceParts.length === 0) {
|
1131
|
+
const heading = `// this file was autogenerated by arri
|
1132
|
+
// ignore_for_file: type=lint, unused_field, unnecessary_cast
|
1133
|
+
import 'dart:convert';
|
1134
|
+
import 'package:arri_client/arri_client.dart';`;
|
1135
|
+
return `${heading}
|
1136
|
+
|
1137
|
+
${typeParts.join("\n\n")}`;
|
1138
|
+
}
|
1139
|
+
const clientName = validDartClassName(context.clientName, "");
|
1140
|
+
return `// this file was autogenerated by arri
|
1141
|
+
// ignore_for_file: type=lint, unused_field, unnecessary_cast
|
1142
|
+
import 'dart:async';
|
1143
|
+
import 'dart:convert';
|
1144
|
+
import 'package:arri_client/arri_client.dart';
|
1145
|
+
import 'package:http/http.dart' as http;
|
1146
|
+
|
1147
|
+
class ${clientName} {
|
1148
|
+
final http.Client? _httpClient;
|
1149
|
+
final String _baseUrl;
|
1150
|
+
final String _clientVersion = "${context.clientVersion ?? ""}";
|
1151
|
+
late final FutureOr<Map<String, String>> Function()? _headers;
|
1152
|
+
${clientName}({
|
1153
|
+
http.Client? httpClient,
|
1154
|
+
required String baseUrl,
|
1155
|
+
FutureOr<Map<String, String>> Function()? headers,
|
1156
|
+
}) : _httpClient = httpClient,
|
1157
|
+
_baseUrl = baseUrl,
|
1158
|
+
_headers = headers;
|
1159
|
+
|
1160
|
+
${rpcParts.join("\n\n")}
|
1161
|
+
|
1162
|
+
${subServices.map(
|
1163
|
+
(service) => ` ${service.name} get ${service.key} => ${service.name}(
|
1164
|
+
baseUrl: _baseUrl,
|
1165
|
+
headers: _headers,
|
1166
|
+
httpClient: _httpClient,
|
1167
|
+
);`
|
1168
|
+
).join("\n\n")}
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
${subServiceParts.join("\n\n")}
|
1172
|
+
|
1173
|
+
${typeParts.join("\n\n")}`;
|
1174
|
+
}
|
1175
|
+
function dartTypeFromSchema(schema, context) {
|
1176
|
+
if (isSchemaFormType(schema)) {
|
1177
|
+
switch (schema.type) {
|
1178
|
+
case "string":
|
1179
|
+
return dartStringFromSchema(schema, context);
|
1180
|
+
case "boolean":
|
1181
|
+
return dartBoolFromSchema(schema, context);
|
1182
|
+
case "timestamp":
|
1183
|
+
return dartDateTimeFromSchema(schema, context);
|
1184
|
+
case "float32":
|
1185
|
+
case "float64":
|
1186
|
+
return dartDoubleFromSchema(schema, context);
|
1187
|
+
case "int8":
|
1188
|
+
case "uint8":
|
1189
|
+
case "int16":
|
1190
|
+
case "uint16":
|
1191
|
+
case "int32":
|
1192
|
+
case "uint32":
|
1193
|
+
return dartIntFromSchema(schema, context);
|
1194
|
+
case "int64":
|
1195
|
+
case "uint64":
|
1196
|
+
return dartBigIntFromSchema(schema, context);
|
1197
|
+
default:
|
1198
|
+
schema.type;
|
1199
|
+
throw new Error(`Unhandled schema.type ${schema.type}`);
|
1200
|
+
}
|
1201
|
+
}
|
1202
|
+
if (isSchemaFormEnum(schema)) {
|
1203
|
+
return dartEnumFromSchema(schema, context);
|
1204
|
+
}
|
1205
|
+
if (isSchemaFormProperties(schema)) {
|
1206
|
+
return dartClassFromSchema(schema, context);
|
1207
|
+
}
|
1208
|
+
if (isSchemaFormElements(schema)) {
|
1209
|
+
return dartListFromSchema(schema, context);
|
1210
|
+
}
|
1211
|
+
if (isSchemaFormValues(schema)) {
|
1212
|
+
return dartMapFromSchema(schema, context);
|
1213
|
+
}
|
1214
|
+
if (isSchemaFormDiscriminator(schema)) {
|
1215
|
+
return dartSealedClassFromSchema(schema, context);
|
1216
|
+
}
|
1217
|
+
if (isSchemaFormRef(schema)) {
|
1218
|
+
return dartRefFromSchema(schema, context);
|
1219
|
+
}
|
1220
|
+
return dartAnyFromSchema(schema, context);
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
export { createDartClient, dartClientGenerator, dartTypeFromSchema };
|