@arrirpc/codegen-swift 0.60.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 ADDED
@@ -0,0 +1,1536 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const codegenUtils = require('@arrirpc/codegen-utils');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
7
+
8
+ const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
9
+
10
+ function isNullableType(schema, context) {
11
+ return schema.nullable === true || context.isOptional === true;
12
+ }
13
+ function validTypeName(input) {
14
+ const formatted = codegenUtils.removeDisallowedChars(
15
+ codegenUtils.pascalCase(input.split("[").join("_").split("]").join("_"), {
16
+ normalize: true
17
+ }),
18
+ illegalPropertyChars
19
+ );
20
+ if (reservedKeywords[formatted]) {
21
+ return `_${formatted}`;
22
+ }
23
+ if (codegenUtils.stringStartsWithNumber(formatted)) {
24
+ return `_${formatted}`;
25
+ }
26
+ return formatted;
27
+ }
28
+ function getTypeName(schema, context) {
29
+ if (schema.metadata?.id) {
30
+ const typeName2 = validTypeName(schema.metadata.id);
31
+ return typeName2;
32
+ }
33
+ if (context.discriminatorParent && context.discriminatorValue) {
34
+ const typeName2 = validTypeName(
35
+ `${context.discriminatorParent}_${context.discriminatorValue}`
36
+ );
37
+ return typeName2;
38
+ }
39
+ const typeName = validTypeName(context.instancePath.split("/").join("_"));
40
+ return typeName;
41
+ }
42
+ const reservedKeywords = {
43
+ associatedType: true,
44
+ class: true,
45
+ deinit: true,
46
+ enum: true,
47
+ extension: true,
48
+ fileprivate: true,
49
+ func: true,
50
+ import: true,
51
+ init: true,
52
+ inout: true,
53
+ internal: true,
54
+ let: true,
55
+ open: true,
56
+ operator: true,
57
+ private: true,
58
+ precedencegroup: true,
59
+ protocol: true,
60
+ public: true,
61
+ rethrows: true,
62
+ static: true,
63
+ subscript: true,
64
+ typealias: true,
65
+ var: true,
66
+ break: true,
67
+ case: true,
68
+ catch: true,
69
+ continue: true,
70
+ default: true,
71
+ defer: true,
72
+ do: true,
73
+ else: true,
74
+ fallthrough: true,
75
+ for: true,
76
+ guard: true,
77
+ if: true,
78
+ in: true,
79
+ repeat: true,
80
+ return: true,
81
+ throw: true,
82
+ switch: true,
83
+ where: true,
84
+ while: true,
85
+ Any: true,
86
+ as: true,
87
+ false: true,
88
+ is: true,
89
+ nil: true,
90
+ self: true,
91
+ Self: true,
92
+ super: true,
93
+ true: true,
94
+ try: true
95
+ };
96
+ const illegalPropertyChars = "!@#$%^&*()+=[]{}\\|;:'\",./?><`~";
97
+ function validSwiftKey(input) {
98
+ const key = codegenUtils.removeDisallowedChars(
99
+ codegenUtils.camelCase(input, { normalize: true }),
100
+ illegalPropertyChars
101
+ );
102
+ if (reservedKeywords[key]) {
103
+ return `\`${key}\``;
104
+ }
105
+ if (codegenUtils.stringStartsWithNumber(key)) {
106
+ return `_${key}`;
107
+ }
108
+ return key;
109
+ }
110
+ function codeComments(schema, leading = "") {
111
+ const description = schema.metadata?.description?.split("\n").map((line) => `${leading}/// ${line}`).join("\n");
112
+ if (description && schema.metadata?.isDeprecated) {
113
+ return `${description}
114
+ ${leading}@available(*, deprecated)
115
+ `;
116
+ }
117
+ if (description) {
118
+ return `${description}
119
+ `;
120
+ }
121
+ if (schema.metadata?.isDeprecated) {
122
+ return `${leading}@available(*, deprecated)
123
+ `;
124
+ }
125
+ return "";
126
+ }
127
+
128
+ function swiftAnyFromSchema(schema, context) {
129
+ const isNullable = isNullableType(schema, context);
130
+ let defaultValue = "JSON()";
131
+ if (schema.nullable) {
132
+ defaultValue = 'JSON(parseJSON: "null")';
133
+ } else if (context.isOptional) {
134
+ defaultValue = "";
135
+ }
136
+ return {
137
+ typeName: context.isOptional ? "JSON?" : "JSON",
138
+ defaultValue,
139
+ isNullable,
140
+ canBeQueryString: false,
141
+ hasRequiredRef: false,
142
+ fromJsonTemplate(input, target) {
143
+ if (isNullable) {
144
+ return ` if ${input}.exists() {
145
+ ${target} = ${input}
146
+ }`;
147
+ }
148
+ return ` ${target} = ${input}`;
149
+ },
150
+ toJsonTemplate(input, target) {
151
+ if (context.isOptional) {
152
+ return ` ${target} += serializeAny(input: ${input}!)`;
153
+ }
154
+ return ` ${target} += serializeAny(input: ${input})`;
155
+ },
156
+ toQueryPartTemplate(_, __, ___) {
157
+ return ` print("[WARNING] any's cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
158
+ },
159
+ content: ""
160
+ };
161
+ }
162
+
163
+ function swiftArrayFromSchema(schema, context) {
164
+ const subType = swiftTypeFromSchema(schema.elements, {
165
+ clientVersion: context.clientVersion,
166
+ clientName: context.clientName,
167
+ typePrefix: context.typePrefix,
168
+ instancePath: `${context.instancePath}/[element]`,
169
+ schemaPath: `${context.schemaPath}/elements`,
170
+ generatedTypes: context.generatedTypes,
171
+ containsRequiredRef: context.containsRequiredRef
172
+ });
173
+ const isNullable = isNullableType(schema, context);
174
+ const typeName = isNullable ? `[${subType.typeName}]?` : `[${subType.typeName}]`;
175
+ const defaultValue = isNullable ? "" : "[]";
176
+ return {
177
+ typeName,
178
+ isNullable,
179
+ defaultValue,
180
+ canBeQueryString: false,
181
+ hasRequiredRef: false,
182
+ fromJsonTemplate(input, target, key) {
183
+ const innerKey = validSwiftKey(key);
184
+ const mainContent = ` ${target} = []
185
+ for __${innerKey}JsonElement in ${input}.array ?? [] {
186
+ var __${innerKey}JsonElementValue: ${subType.typeName}
187
+ ${subType.fromJsonTemplate(`__${innerKey}JsonElement`, `__${innerKey}JsonElementValue`, `element`)}
188
+ ${target}${isNullable ? "!" : ""}.append(__${innerKey}JsonElementValue)
189
+ }`;
190
+ if (context.isOptional) {
191
+ return ` if ${input}.exists() {
192
+ ${mainContent}
193
+ }`;
194
+ }
195
+ if (schema.nullable) {
196
+ return ` if ${input}.array != nil {
197
+ ${mainContent}
198
+ }`;
199
+ }
200
+ return mainContent;
201
+ },
202
+ toJsonTemplate(input, target) {
203
+ const mainContent = ` ${target} += "["
204
+ for (__index, __element) in ${input}${isNullable ? "!" : ""}.enumerated() {
205
+ if __index > 0 {
206
+ ${target} += ","
207
+ }
208
+ ${subType.toJsonTemplate(`__element`, target)}
209
+ }
210
+ ${target} += "]"`;
211
+ if (schema.nullable) {
212
+ return ` if ${input} != nil {
213
+ ${mainContent}
214
+ } else {
215
+ ${target} += "null"
216
+ }`;
217
+ }
218
+ return mainContent;
219
+ },
220
+ toQueryPartTemplate(_, __, ___) {
221
+ return ` print("[WARNING] arrays cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
222
+ },
223
+ cloneTemplate(input, key) {
224
+ const innerKey = validSwiftKey(key);
225
+ const subTypeClonedResult = subType.cloneTemplate?.(
226
+ `__${innerKey}Element`,
227
+ `__${innerKey}Element`
228
+ );
229
+ if (isNullable) {
230
+ return {
231
+ bodyContent: `var __${innerKey}Cloned: ${typeName}
232
+ if ${input} != nil {
233
+ __${innerKey}Cloned = []
234
+ for __${innerKey}Element in ${input}! {
235
+ ${subTypeClonedResult?.bodyContent ?? ""}
236
+ __${innerKey}Cloned!.append(${subTypeClonedResult?.fieldContent || `__${innerKey}Element`})
237
+ }
238
+ }`,
239
+ fieldContent: `__${innerKey}Cloned`
240
+ };
241
+ }
242
+ return {
243
+ bodyContent: `var __${innerKey}Cloned: ${typeName} = []
244
+ for __${innerKey}Element in ${input} {
245
+ ${subTypeClonedResult?.bodyContent ?? ""}
246
+ __${innerKey}Cloned.append(${subTypeClonedResult?.fieldContent || `__${innerKey}Element`})
247
+ }`,
248
+ fieldContent: `__${innerKey}Cloned`
249
+ };
250
+ },
251
+ content: subType.content
252
+ };
253
+ }
254
+
255
+ function swiftObjectFromSchema(schema, context) {
256
+ const typeName = getTypeName(schema, context);
257
+ const prefixedTypeName = `${context.typePrefix}${typeName}`;
258
+ const isNullable = isNullableType(schema, context);
259
+ const defaultValue = isNullable ? "" : `${prefixedTypeName}()`;
260
+ const result = {
261
+ typeName: isNullable ? `${prefixedTypeName}?` : prefixedTypeName,
262
+ defaultValue,
263
+ isNullable,
264
+ canBeQueryString: false,
265
+ hasRequiredRef: context.containsRequiredRef[typeName] ?? false,
266
+ fromJsonTemplate(input, target) {
267
+ if (context.isOptional) {
268
+ return ` if ${input}.exists() {
269
+ ${target} = ${prefixedTypeName}(json: ${input})
270
+ }`;
271
+ }
272
+ if (schema.nullable) {
273
+ return ` if ${input}.dictionary != nil {
274
+ ${target} = ${prefixedTypeName}(json: ${input})
275
+ }`;
276
+ }
277
+ return ` ${target} = ${prefixedTypeName}(json: ${input})`;
278
+ },
279
+ toJsonTemplate(input, target) {
280
+ if (context.isOptional) {
281
+ return ` ${target} += ${input}!.toJSONString()`;
282
+ }
283
+ if (schema.nullable) {
284
+ return ` if ${input} != nil {
285
+ ${target} += ${input}!.toJSONString()
286
+ } else {
287
+ ${target} += "null"
288
+ }`;
289
+ }
290
+ return ` ${target} += ${input}.toJSONString()`;
291
+ },
292
+ toQueryPartTemplate(_, __, ___) {
293
+ return ` print("[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
294
+ },
295
+ cloneTemplate(input, _key) {
296
+ let fieldContent = `${input}.clone()`;
297
+ if (isNullable) {
298
+ fieldContent = `${input}?.clone()`;
299
+ }
300
+ return {
301
+ tempKey: "",
302
+ bodyContent: "",
303
+ fieldContent
304
+ };
305
+ },
306
+ content: ""
307
+ };
308
+ if (context.generatedTypes.includes(typeName)) {
309
+ return result;
310
+ }
311
+ const fieldNames = [];
312
+ const fieldNameParts = [];
313
+ const initArgParts = [];
314
+ const initBodyParts = [];
315
+ const initFromJsonParts = [];
316
+ const toJsonParts = [];
317
+ const toQueryStringParts = [];
318
+ const cloneBodyParts = [];
319
+ const cloneFieldParts = [];
320
+ const subContent = [];
321
+ let numKeys = 0;
322
+ let canBeQueryString = false;
323
+ let hasRecursiveSubType = false;
324
+ if (context.discriminatorKey && context.discriminatorValue) {
325
+ numKeys++;
326
+ canBeQueryString = true;
327
+ const discriminatorKey = validSwiftKey(context.discriminatorKey);
328
+ fieldNames.push(discriminatorKey);
329
+ fieldNameParts.push(
330
+ ` let ${discriminatorKey}: String = "${context.discriminatorValue}"`
331
+ );
332
+ toJsonParts.push(
333
+ ` __json += "\\"${context.discriminatorKey}\\":\\"${context.discriminatorValue}\\""`
334
+ );
335
+ toQueryStringParts.push(
336
+ ` __queryParts.append(URLQueryItem(name: "${context.discriminatorKey}", value: "${context.discriminatorValue}"))`
337
+ );
338
+ }
339
+ for (const key of Object.keys(schema.properties)) {
340
+ const subSchema = schema.properties[key];
341
+ const subType = swiftTypeFromSchema(subSchema, {
342
+ clientVersion: context.clientVersion,
343
+ clientName: context.clientName,
344
+ typePrefix: context.typePrefix,
345
+ instancePath: `/${typeName}/${key}`,
346
+ schemaPath: `${context.schemaPath}/properties/${key}`,
347
+ generatedTypes: context.generatedTypes,
348
+ containsRequiredRef: context.containsRequiredRef
349
+ });
350
+ if (subType.content)
351
+ subContent.push(subType.content);
352
+ if (subType.hasRequiredRef && !subType.isNullable) {
353
+ context.containsRequiredRef[typeName] = true;
354
+ result.hasRequiredRef = true;
355
+ }
356
+ if (codegenUtils.isSchemaFormRef(subSchema)) {
357
+ hasRecursiveSubType = true;
358
+ }
359
+ if (subType.canBeQueryString)
360
+ canBeQueryString = true;
361
+ const fieldName = validSwiftKey(key);
362
+ fieldNames.push(fieldName);
363
+ if (subType.defaultValue) {
364
+ fieldNameParts.push(
365
+ `${codeComments(subSchema, " ")} public var ${fieldName}: ${subType.typeName} = ${subType.defaultValue}`
366
+ );
367
+ } else {
368
+ fieldNameParts.push(
369
+ `${codeComments(subSchema, " ")} public var ${fieldName}: ${subType.typeName}`
370
+ );
371
+ }
372
+ initArgParts.push(` ${fieldName}: ${subType.typeName}`);
373
+ initBodyParts.push(` self.${fieldName} = ${fieldName}`);
374
+ initFromJsonParts.push(
375
+ subType.fromJsonTemplate(
376
+ `json["${key}"]`,
377
+ `self.${fieldName}`,
378
+ key
379
+ )
380
+ );
381
+ if (numKeys > 0) {
382
+ toJsonParts.push(` __json += ",\\"${key}\\":"`);
383
+ } else {
384
+ toJsonParts.push(` __json += "\\"${key}\\":"`);
385
+ }
386
+ toJsonParts.push(subType.toJsonTemplate(`self.${fieldName}`, `__json`));
387
+ if (subType.canBeQueryString)
388
+ canBeQueryString = true;
389
+ toQueryStringParts.push(
390
+ subType.toQueryPartTemplate(
391
+ `self.${fieldName}`,
392
+ `__queryParts`,
393
+ key
394
+ )
395
+ );
396
+ const cloneResult = subType.cloneTemplate?.(
397
+ `self.${fieldName}`,
398
+ fieldName
399
+ );
400
+ if (cloneResult) {
401
+ cloneBodyParts.push(cloneResult.bodyContent);
402
+ cloneFieldParts.push(
403
+ ` ${fieldName}: ${cloneResult.fieldContent}`
404
+ );
405
+ } else {
406
+ cloneFieldParts.push(
407
+ ` ${fieldName.split("`").join("")}: self.${fieldName}`
408
+ );
409
+ }
410
+ numKeys++;
411
+ }
412
+ let numOptionalKeys = 0;
413
+ for (const key of Object.keys(schema.optionalProperties ?? {})) {
414
+ const subSchema = schema.optionalProperties[key];
415
+ const subType = swiftTypeFromSchema(subSchema, {
416
+ clientVersion: context.clientVersion,
417
+ clientName: context.clientName,
418
+ typePrefix: context.typePrefix,
419
+ instancePath: `/${typeName}/${key}`,
420
+ schemaPath: `${context.schemaPath}/optionalProperties/${key}`,
421
+ generatedTypes: context.generatedTypes,
422
+ isOptional: true,
423
+ containsRequiredRef: context.containsRequiredRef
424
+ });
425
+ if (subType.content)
426
+ subContent.push(subType.content);
427
+ if (codegenUtils.isSchemaFormRef(subSchema)) {
428
+ hasRecursiveSubType = true;
429
+ }
430
+ if (subType.canBeQueryString)
431
+ canBeQueryString = true;
432
+ const fieldName = validSwiftKey(key);
433
+ fieldNames.push(fieldName);
434
+ fieldNameParts.push(
435
+ `${codeComments(subSchema, " ")} public var ${fieldName}: ${subType.typeName}`
436
+ );
437
+ initArgParts.push(` ${fieldName}: ${subType.typeName}`);
438
+ initBodyParts.push(` self.${fieldName} = ${fieldName}`);
439
+ initFromJsonParts.push(
440
+ subType.fromJsonTemplate(
441
+ `json["${key}"]`,
442
+ `self.${fieldName}`,
443
+ key
444
+ )
445
+ );
446
+ let toJsonContent = ``;
447
+ if (numKeys > 0) {
448
+ toJsonContent += ` __json += ",\\"${key}\\":"
449
+ `;
450
+ } else {
451
+ if (numOptionalKeys > 0) {
452
+ toJsonContent += ` if __numKeys > 0 {
453
+ __json += ","
454
+ }
455
+ `;
456
+ }
457
+ toJsonContent += ` __json += "\\"${key}\\":"
458
+ `;
459
+ }
460
+ toJsonContent += subType.toJsonTemplate(`self.${fieldName}`, `__json`);
461
+ if (numKeys === 0) {
462
+ toJsonContent += `
463
+ __numKeys += 1`;
464
+ }
465
+ toJsonParts.push(` if self.${fieldName} != nil {
466
+ ${toJsonContent}
467
+ }`);
468
+ if (subType.canBeQueryString)
469
+ canBeQueryString = true;
470
+ toQueryStringParts.push(
471
+ subType.toQueryPartTemplate(
472
+ `self.${fieldName}`,
473
+ `__queryParts`,
474
+ key
475
+ )
476
+ );
477
+ const cloneResult = subType.cloneTemplate?.(
478
+ `self.${fieldName}`,
479
+ fieldName
480
+ );
481
+ if (cloneResult) {
482
+ cloneBodyParts.push(cloneResult.bodyContent);
483
+ cloneFieldParts.push(
484
+ ` ${fieldName}: ${cloneResult.fieldContent}`
485
+ );
486
+ } else {
487
+ cloneFieldParts.push(
488
+ ` ${fieldName.split("`").join("")}: self.${fieldName}`
489
+ );
490
+ }
491
+ numOptionalKeys++;
492
+ }
493
+ const declaration = hasRecursiveSubType ? `final class` : "struct";
494
+ const initPrefix = hasRecursiveSubType ? `public required` : `public`;
495
+ const initJsonStringPrefix = hasRecursiveSubType ? `public required convenience` : `public`;
496
+ let equalsPart = "";
497
+ if (hasRecursiveSubType) {
498
+ equalsPart = `public static func == (lhs: ${prefixedTypeName}, rhs: ${prefixedTypeName}) -> Bool {
499
+ return
500
+ ${fieldNames.map((field) => ` lhs.${field} == rhs.${field}`).join(" &&\n")}
501
+ }`;
502
+ }
503
+ result.content = `${codeComments(schema)}public ${declaration} ${prefixedTypeName}: ArriClientModel {
504
+ ${fieldNameParts.join("\n")}
505
+ ${initPrefix} init(
506
+ ${initArgParts.join(",\n")}
507
+ ) {
508
+ ${initBodyParts.join("\n")}
509
+ }
510
+ ${initPrefix} init() {}
511
+ ${initPrefix} init(json: JSON) {
512
+ ${initFromJsonParts.join("\n")}
513
+ }
514
+ ${initJsonStringPrefix} init(JSONData: Data) {
515
+ do {
516
+ let json = try JSON(data: JSONData)
517
+ self.init(json: json)
518
+ } catch {
519
+ print("[WARNING] Error parsing JSON: \\(error)")
520
+ self.init()
521
+ }
522
+ }
523
+ ${initJsonStringPrefix} init(JSONString: String) {
524
+ do {
525
+ let json = try JSON(data: JSONString.data(using: .utf8) ?? Data())
526
+ self.init(json: json)
527
+ } catch {
528
+ print("[WARNING] Error parsing JSON: \\(error)")
529
+ self.init()
530
+ }
531
+ }
532
+ public func toJSONString() -> String {
533
+ var __json = "{"
534
+ ${numKeys === 0 ? ` var __numKeys = 0` : ""}
535
+ ${toJsonParts.join("\n")}
536
+ __json += "}"
537
+ return __json
538
+ }
539
+ public func toURLQueryParts() -> [URLQueryItem] {
540
+ ${canBeQueryString ? `var __queryParts: [URLQueryItem] = []` : ""}
541
+ ${toQueryStringParts.join("\n")}
542
+ ${canBeQueryString ? `return __queryParts` : `return []`}
543
+ }
544
+ public func clone() -> ${prefixedTypeName} {
545
+ ${cloneBodyParts.join("\n")}
546
+ return ${prefixedTypeName}(
547
+ ${cloneFieldParts.join(",\n")}
548
+ )
549
+ }
550
+ ${equalsPart}
551
+ }
552
+
553
+ ${subContent.join("\n")}`;
554
+ context.generatedTypes.push(typeName);
555
+ return result;
556
+ }
557
+
558
+ function swiftTaggedUnionFromSchema(schema, context) {
559
+ const typeName = getTypeName(schema, context);
560
+ const prefixedTypeName = `${context.typePrefix}${typeName}`;
561
+ const isNullable = isNullableType(schema, context);
562
+ const defaultValue = isNullable ? `` : `${prefixedTypeName}()`;
563
+ const result = {
564
+ typeName: isNullable ? `${prefixedTypeName}?` : prefixedTypeName,
565
+ isNullable,
566
+ defaultValue,
567
+ canBeQueryString: false,
568
+ hasRequiredRef: context.containsRequiredRef[typeName] ?? false,
569
+ fromJsonTemplate(input, target, _) {
570
+ if (context.isOptional) {
571
+ return ` if ${input}.exists() {
572
+ ${target} = ${prefixedTypeName}(json: ${input})
573
+ }`;
574
+ }
575
+ if (schema.nullable) {
576
+ return ` if ${input}.dictionary != nil {
577
+ ${target} = ${prefixedTypeName}(json: ${input})
578
+ }`;
579
+ }
580
+ return ` ${target} = ${prefixedTypeName}(json: ${input})`;
581
+ },
582
+ toJsonTemplate(input, target) {
583
+ if (context.isOptional) {
584
+ return ` ${target} += ${input}!.toJSONString()`;
585
+ }
586
+ if (schema.nullable) {
587
+ return ` if ${input} != nil {
588
+ ${target} += ${input}!.toJSONString()
589
+ } else {
590
+ ${target} += "null"
591
+ }`;
592
+ }
593
+ return ` ${target} += ${input}.toJSONString()`;
594
+ },
595
+ toQueryPartTemplate(_, __, ___) {
596
+ return ` print("[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
597
+ },
598
+ cloneTemplate(input, _) {
599
+ return {
600
+ fieldContent: `${input}${isNullable ? "?" : ""}.clone()`,
601
+ bodyContent: ""
602
+ };
603
+ },
604
+ content: ""
605
+ };
606
+ if (context.generatedTypes.includes(typeName)) {
607
+ return result;
608
+ }
609
+ const discriminatorParts = [];
610
+ const discriminatorKey = schema.discriminator;
611
+ for (const key of Object.keys(schema.mapping)) {
612
+ const discriminatorValue = key;
613
+ const subSchema = schema.mapping[key];
614
+ const subType = swiftObjectFromSchema(subSchema, {
615
+ clientVersion: context.clientVersion,
616
+ clientName: context.clientName,
617
+ typePrefix: context.typePrefix,
618
+ instancePath: context.instancePath,
619
+ schemaPath: `${context.schemaPath}/mapping/${key}`,
620
+ generatedTypes: context.generatedTypes,
621
+ discriminatorKey,
622
+ discriminatorParent: typeName,
623
+ discriminatorValue: key,
624
+ containsRequiredRef: context.containsRequiredRef
625
+ });
626
+ const discriminatorCase = validSwiftKey(key);
627
+ const discriminatorPart = {
628
+ discriminatorValue,
629
+ discriminatorCase,
630
+ hasRequiredRef: subType.hasRequiredRef,
631
+ typeName: subType.typeName.replace("?", ""),
632
+ content: subType.content
633
+ };
634
+ discriminatorParts.push(discriminatorPart);
635
+ }
636
+ if (!discriminatorParts.length) {
637
+ throw new Error(
638
+ `Invalid schema at ${context.schemaPath}. Discriminators must have at least one mapping.`
639
+ );
640
+ }
641
+ let defaultPart;
642
+ for (const part of discriminatorParts) {
643
+ if (part.hasRequiredRef)
644
+ continue;
645
+ defaultPart = part;
646
+ break;
647
+ }
648
+ if (!defaultPart) {
649
+ throw new Error(
650
+ `Invalid schema a ${context.schemaPath}. All subtypes have a required recursive reference. This creates an infinite loop.`
651
+ );
652
+ }
653
+ result.content = `${codeComments(schema)}public enum ${prefixedTypeName}: ArriClientModel {
654
+ ${discriminatorParts.map((part) => ` case ${part.discriminatorCase}(${part.typeName})`).join("\n")}
655
+ public init() {
656
+ self = .${defaultPart.discriminatorCase}(${defaultPart.typeName}())
657
+ }
658
+ public init(json: JSON) {
659
+ let discriminator = json["${discriminatorKey}"].string ?? ""
660
+ switch (discriminator) {
661
+ ${discriminatorParts.map(
662
+ (part) => ` case "${part.discriminatorValue}":
663
+ self = .${part.discriminatorCase}(${part.typeName}(json: json))
664
+ break`
665
+ ).join("\n")}
666
+ default:
667
+ self = .${defaultPart.discriminatorCase}(${defaultPart.typeName}())
668
+ break
669
+ }
670
+ }
671
+ public init(JSONData: Data) {
672
+ do {
673
+ let json = try JSON(data: JSONData)
674
+ self.init(json: json)
675
+ } catch {
676
+ print("[WARNING] Error parsing JSON: \\(error)")
677
+ self.init()
678
+ }
679
+ }
680
+ public init(JSONString: String) {
681
+ do {
682
+ let json = try JSON(data: JSONString.data(using: .utf8) ?? Data())
683
+ self.init(json: json)
684
+ } catch {
685
+ print("[WARNING] Error parsing JSON: \\(error)")
686
+ self.init()
687
+ }
688
+ }
689
+ public func toJSONString() -> String {
690
+ switch(self) {
691
+ ${discriminatorParts.map(
692
+ (part) => ` case .${part.discriminatorCase}(let __innerVal):
693
+ return __innerVal.toJSONString()`
694
+ ).join("\n")}
695
+ }
696
+ }
697
+ public func toURLQueryParts() -> [URLQueryItem] {
698
+ switch(self) {
699
+ ${discriminatorParts.map(
700
+ (part) => ` case .${part.discriminatorCase}(let __innerVal):
701
+ return __innerVal.toURLQueryParts()`
702
+ ).join("\n")}
703
+ }
704
+ }
705
+ public func clone() -> ${prefixedTypeName} {
706
+ switch(self) {
707
+ ${discriminatorParts.map(
708
+ (part) => ` case .${part.discriminatorCase}(let __innerVal):
709
+ return .${part.discriminatorCase}(__innerVal.clone())`
710
+ ).join("\n")}
711
+ }
712
+ }
713
+ }
714
+
715
+ ${discriminatorParts.map((part) => part.content).join("\n")}`;
716
+ context.generatedTypes.push(typeName);
717
+ return result;
718
+ }
719
+
720
+ function swiftEnumFromSchema(schema, context) {
721
+ if (!schema.enum[0]) {
722
+ throw new Error(
723
+ `Error at ${context.instancePath}. Must have at least one enum value.`
724
+ );
725
+ }
726
+ const typeName = getTypeName(schema, context);
727
+ const isNullable = isNullableType(schema, context);
728
+ const defaultEnumValue = codegenUtils.camelCase(schema.enum[0], { normalize: true });
729
+ const prefixedTypeName = `${context.typePrefix}${typeName}`;
730
+ const defaultValue = isNullable ? "" : `${prefixedTypeName}.${defaultEnumValue}`;
731
+ const result = {
732
+ typeName: isNullable ? `${typeName}?` : typeName,
733
+ isNullable,
734
+ defaultValue,
735
+ canBeQueryString: true,
736
+ hasRequiredRef: false,
737
+ fromJsonTemplate(input, target) {
738
+ if (context.isOptional) {
739
+ return ` if ${input}.exists() {
740
+ ${target} = ${prefixedTypeName}(serialValue: ${input}.string ?? "")
741
+ }`;
742
+ }
743
+ if (schema.nullable) {
744
+ return ` if ${input}.string != nil {
745
+ ${target} = ${prefixedTypeName}(serialValue: ${input}.string ?? "")
746
+ }`;
747
+ }
748
+ return ` ${target} = ${prefixedTypeName}(serialValue: ${input}.string ?? "")`;
749
+ },
750
+ toJsonTemplate(input, target) {
751
+ if (context.isOptional) {
752
+ return ` ${target} += "\\"\\(${input}!.serialValue())\\""`;
753
+ }
754
+ if (schema.nullable) {
755
+ return ` if ${input} != nil {
756
+ ${target} += "\\"\\(${input}!.serialValue())\\""
757
+ } else {
758
+ ${target} += "null"
759
+ }`;
760
+ }
761
+ return ` ${target} += "\\"\\(${input}.serialValue())\\""`;
762
+ },
763
+ toQueryPartTemplate(input, target, key) {
764
+ if (context.isOptional) {
765
+ return ` if ${input} != nil {
766
+ ${target}.append(URLQueryItem(name: "${key}", value: ${input}!.serialValue()))
767
+ }`;
768
+ }
769
+ if (schema.nullable) {
770
+ return ` if ${input} != nil {
771
+ ${target}.append(URLQueryItem(name: "${key}", value: ${input}!.serialValue()))
772
+ } else {
773
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
774
+ }`;
775
+ }
776
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: ${input}.serialValue()))`;
777
+ },
778
+ content: ""
779
+ };
780
+ if (context.generatedTypes.includes(typeName)) {
781
+ return result;
782
+ }
783
+ result.content = `public enum ${prefixedTypeName}: ArriClientEnum {
784
+ ${schema.enum.map((val) => ` case ${codegenUtils.camelCase(val, { normalize: true })}`).join("\n")}
785
+ public init() {
786
+ self = .${defaultEnumValue}
787
+ }
788
+ public init(serialValue: String) {
789
+ switch(serialValue) {
790
+ ${schema.enum.map(
791
+ (val) => ` case "${val}":
792
+ self = .${codegenUtils.camelCase(val, { normalize: true })}
793
+ break;`
794
+ ).join("\n")}
795
+ default:
796
+ self = .${defaultEnumValue}
797
+ }
798
+ }
799
+ public func serialValue() -> String {
800
+ switch (self) {
801
+ ${schema.enum.map(
802
+ (val) => ` case .${codegenUtils.camelCase(val, { normalize: true })}:
803
+ return "${val}"`
804
+ ).join("\n")}
805
+ }
806
+ }
807
+ }`;
808
+ context.generatedTypes.push(typeName);
809
+ return result;
810
+ }
811
+
812
+ function swiftStringFromSchema(schema, context) {
813
+ const isNullable = isNullableType(schema, context);
814
+ const typeName = isNullable ? "String?" : "String";
815
+ const defaultValue = isNullable ? "" : '""';
816
+ return {
817
+ typeName,
818
+ isNullable,
819
+ defaultValue,
820
+ canBeQueryString: true,
821
+ hasRequiredRef: false,
822
+ fromJsonTemplate(input, target) {
823
+ if (context.isOptional) {
824
+ return ` if ${input}.exists() {
825
+ ${target} = ${input}.string
826
+ }`;
827
+ }
828
+ if (schema.nullable) {
829
+ return ` if ${input}.string != nil {
830
+ ${target} = ${input}.string
831
+ }`;
832
+ }
833
+ return ` ${target} = ${input}.string ?? ""`;
834
+ },
835
+ toJsonTemplate(input, target) {
836
+ if (context.isOptional) {
837
+ return ` ${target} += serializeString(input: ${input}!)`;
838
+ }
839
+ if (schema.nullable) {
840
+ return ` if ${input} != nil {
841
+ ${target} += serializeString(input: ${input}!)
842
+ } else {
843
+ ${target} += "null"
844
+ }`;
845
+ }
846
+ return ` ${target} += serializeString(input: ${input})`;
847
+ },
848
+ toQueryPartTemplate(input, target, key) {
849
+ if (context.isOptional) {
850
+ return ` if ${input} != nil {
851
+ ${target}.append(URLQueryItem(name: "${key}", value: ${input}!))
852
+ }`;
853
+ }
854
+ if (schema.nullable) {
855
+ return ` if ${input} != nil {
856
+ ${target}.append(URLQueryItem(name: "${key}", value: ${input}!))
857
+ } else {
858
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
859
+ }`;
860
+ }
861
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: ${input}))`;
862
+ },
863
+ content: ""
864
+ };
865
+ }
866
+ function swiftBooleanFromSchema(schema, context) {
867
+ const isNullable = isNullableType(schema, context);
868
+ const typeName = isNullable ? "Bool?" : "Bool";
869
+ const defaultValue = isNullable ? "" : "false";
870
+ return {
871
+ typeName,
872
+ isNullable,
873
+ defaultValue,
874
+ canBeQueryString: true,
875
+ hasRequiredRef: false,
876
+ fromJsonTemplate(input, target) {
877
+ if (context.isOptional) {
878
+ return ` if ${input}.exists() {
879
+ ${target} = ${input}.bool
880
+ }`;
881
+ }
882
+ if (schema.nullable) {
883
+ return ` if ${input}.bool != nil {
884
+ ${target} = ${input}.bool
885
+ }`;
886
+ }
887
+ return ` ${target} = ${input}.bool ?? false`;
888
+ },
889
+ toJsonTemplate(input, target) {
890
+ if (context.isOptional) {
891
+ return `${target} += "\\(${input}!)"`;
892
+ }
893
+ if (schema.nullable) {
894
+ return ` if ${input} != nil {
895
+ ${target} += "\\(${input}!)"
896
+ } else {
897
+ ${target} += "null"
898
+ }`;
899
+ }
900
+ return ` ${target} += "\\(${input})"`;
901
+ },
902
+ toQueryPartTemplate(input, target, key) {
903
+ if (context.isOptional) {
904
+ return ` if ${input} != nil {
905
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
906
+ }`;
907
+ }
908
+ if (schema.nullable) {
909
+ return ` if ${input} != nil {
910
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
911
+ } else {
912
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
913
+ }`;
914
+ }
915
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input})"))`;
916
+ },
917
+ content: ""
918
+ };
919
+ }
920
+ function swiftTimestampFromSchema(schema, context) {
921
+ const isNullable = isNullableType(schema, context);
922
+ const typeName = isNullable ? "Date?" : "Date";
923
+ const defaultValue = isNullable ? "" : "Date()";
924
+ return {
925
+ typeName,
926
+ defaultValue,
927
+ isNullable,
928
+ canBeQueryString: true,
929
+ hasRequiredRef: false,
930
+ fromJsonTemplate(input, target) {
931
+ if (context.isOptional) {
932
+ return ` if ${input}.exists() {
933
+ ${target} = parseDate(${input}.string ?? "") ?? Date()
934
+ }`;
935
+ }
936
+ if (schema.nullable) {
937
+ return ` if ${input}.string != nil {
938
+ ${target} = parseDate(${input}.string ?? "") ?? Date()
939
+ }`;
940
+ }
941
+ return ` ${target} = parseDate(${input}.string ?? "") ?? Date()`;
942
+ },
943
+ toJsonTemplate(input, target) {
944
+ if (context.isOptional) {
945
+ return ` ${target} += serializeDate(${input}!)`;
946
+ }
947
+ if (schema.nullable) {
948
+ return ` if ${input} != nil {
949
+ ${target} += serializeDate(${input}!)
950
+ } else {
951
+ ${target} += "null"
952
+ }`;
953
+ }
954
+ return ` ${target} += serializeDate(${input})`;
955
+ },
956
+ toQueryPartTemplate(input, target, key) {
957
+ if (context.isOptional) {
958
+ return ` if ${input} != nil {
959
+ ${target}.append(URLQueryItem(name: "${key}", value: serializeDate(${input}!, withQuotes: false)))
960
+ }`;
961
+ }
962
+ if (schema.nullable) {
963
+ return ` if ${input} != nil {
964
+ ${target}.append(URLQueryItem(name: "${key}", value: serializeDate(${input}!, withQuotes: false)))
965
+ } else {
966
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
967
+ }`;
968
+ }
969
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: serializeDate(${input}, withQuotes: false)))`;
970
+ },
971
+ content: ""
972
+ };
973
+ }
974
+ function swiftNumberFromSchema(schema, context, typeName, jsonAccessor, defaultValue) {
975
+ const isNullable = isNullableType(schema, context);
976
+ return {
977
+ typeName: isNullable ? `${typeName}?` : typeName,
978
+ defaultValue: isNullable ? "" : defaultValue,
979
+ isNullable,
980
+ canBeQueryString: true,
981
+ hasRequiredRef: false,
982
+ fromJsonTemplate(input, target) {
983
+ if (context.isOptional) {
984
+ return ` if ${input}.exists() {
985
+ ${target} = ${input}.${jsonAccessor}
986
+ }`;
987
+ }
988
+ if (schema.nullable) {
989
+ return ` if ${input}.${jsonAccessor} != nil {
990
+ ${target} = ${input}.${jsonAccessor}
991
+ }`;
992
+ }
993
+ return ` ${target} = ${input}.${jsonAccessor} ?? ${defaultValue}`;
994
+ },
995
+ toJsonTemplate(input, target) {
996
+ if (context.isOptional) {
997
+ return ` ${target} += "\\(${input}!)"`;
998
+ }
999
+ if (schema.nullable) {
1000
+ return ` if ${input} != nil {
1001
+ ${target} += "\\(${input}!)"
1002
+ } else {
1003
+ ${target} += "null"
1004
+ }`;
1005
+ }
1006
+ return ` ${target} += "\\(${input})"`;
1007
+ },
1008
+ toQueryPartTemplate(input, target, key) {
1009
+ if (context.isOptional) {
1010
+ return ` if ${input} != nil {
1011
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
1012
+ }`;
1013
+ }
1014
+ if (schema.nullable) {
1015
+ return ` if ${input} != nil {
1016
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
1017
+ } else {
1018
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
1019
+ }`;
1020
+ }
1021
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input})"))`;
1022
+ },
1023
+ content: ""
1024
+ };
1025
+ }
1026
+ function swiftLargeIntFromSchema(schema, context, typeName) {
1027
+ const isNullable = isNullableType(schema, context);
1028
+ return {
1029
+ typeName: isNullable ? `${typeName}?` : typeName,
1030
+ defaultValue: isNullable ? "" : "0",
1031
+ isNullable,
1032
+ canBeQueryString: true,
1033
+ hasRequiredRef: false,
1034
+ fromJsonTemplate(input, target) {
1035
+ if (context.isOptional) {
1036
+ return ` if ${input}.exists() {
1037
+ ${target} = ${typeName}(${input}.string ?? "0")
1038
+ }`;
1039
+ }
1040
+ if (schema.nullable) {
1041
+ return ` if ${input}.string != nil {
1042
+ ${target} = ${typeName}(${input}.string ?? "0")
1043
+ }`;
1044
+ }
1045
+ return ` ${target} = ${typeName}(${input}.string ?? "0") ?? 0`;
1046
+ },
1047
+ toJsonTemplate(input, target) {
1048
+ if (context.isOptional) {
1049
+ return ` ${target} += "\\"\\(${input}!)\\""`;
1050
+ }
1051
+ if (schema.nullable) {
1052
+ return ` if ${input} != nil {
1053
+ ${target} += "\\"\\(${input}!)\\""
1054
+ } else {
1055
+ ${target} += "null"
1056
+ }`;
1057
+ }
1058
+ return ` ${target} += "\\"\\(${input})\\""`;
1059
+ },
1060
+ toQueryPartTemplate(input, target, key) {
1061
+ if (context.isOptional) {
1062
+ return ` if ${input} != nil {
1063
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
1064
+ }`;
1065
+ }
1066
+ if (schema.nullable) {
1067
+ return ` if ${input} != nil {
1068
+ ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input}!)"))
1069
+ } else {
1070
+ ${target}.append(URLQueryItem(name: "${key}", value: "null"))
1071
+ }`;
1072
+ }
1073
+ return ` ${target}.append(URLQueryItem(name: "${key}", value: "\\(${input})"))`;
1074
+ },
1075
+ content: ""
1076
+ };
1077
+ }
1078
+
1079
+ function swiftProcedureFromSchema(schema, context) {
1080
+ switch (schema.transport) {
1081
+ case "http":
1082
+ return swiftHttpProcedureFromSchema(schema, context);
1083
+ case "ws":
1084
+ return swiftWsProcedureFromSchema(schema, context);
1085
+ default:
1086
+ console.warn(
1087
+ `[swift-codegen] Unsupported transport type at ${context.instancePath}`
1088
+ );
1089
+ return "";
1090
+ }
1091
+ }
1092
+ function swiftHttpProcedureFromSchema(schema, context) {
1093
+ const rpcName = getRpcName(context.instancePath);
1094
+ const comments = codeComments(
1095
+ {
1096
+ metadata: {
1097
+ description: schema.description,
1098
+ isDeprecated: schema.isDeprecated
1099
+ }
1100
+ },
1101
+ " "
1102
+ );
1103
+ const params = schema.params ? `${context.typePrefix}${validTypeName(schema.params)}` : void 0;
1104
+ const response = schema.response ? `${context.typePrefix}${validTypeName(schema.response)}` : void 0;
1105
+ if (schema.isEventStream) {
1106
+ return `${comments} public func ${rpcName}(${params ? `_ params: ${params}, ` : ""}options: EventSourceOptions<${response ?? "EmptyArriModel"}>) -> Task<(), Never> {
1107
+ let task = Task {
1108
+ var eventSource = EventSource<${response ?? "EmptyArriModel"}>(
1109
+ url: "\\(self.baseURL)${schema.path}",
1110
+ method: "${schema.method.toUpperCase()}",
1111
+ headers: self.headers,
1112
+ params: ${params ? "params" : "nil"},
1113
+ delegate: self.delegate,
1114
+ clientVersion: "${context.clientVersion}",
1115
+ options: options
1116
+ )
1117
+ await eventSource.sendRequest()
1118
+ }
1119
+ return task
1120
+ }`;
1121
+ }
1122
+ return `${comments} public func ${rpcName}(${params ? `_ params: ${params}` : ""}) async throws -> ${response ?? "()"} {
1123
+ ${response ? `let result: ${response} = ` : "let _: EmptyArriModel = "}try await parsedArriHttpRequest(
1124
+ delegate: self.delegate,
1125
+ url: "\\(self.baseURL)${schema.path}",
1126
+ method: "${schema.method.toUpperCase()}",
1127
+ headers: self.headers,
1128
+ clientVersion: "${context.clientVersion}",
1129
+ ${params ? `params: params` : "params: EmptyArriModel()"}
1130
+ )
1131
+ ${response ? `return result` : ""}
1132
+ }`;
1133
+ }
1134
+ function getRpcName(instancePath) {
1135
+ const part = instancePath.split(".").pop();
1136
+ if (!part) {
1137
+ throw new Error(`Error determining procedure name at ${instancePath}`);
1138
+ }
1139
+ return validSwiftKey(part);
1140
+ }
1141
+ function swiftWsProcedureFromSchema(schema, context) {
1142
+ console.warn(
1143
+ "[swift-codegen] Websocket procedures are not supported at this time."
1144
+ );
1145
+ const name = getRpcName(context.instancePath);
1146
+ const params = schema.params ? `${context.typePrefix}${validTypeName(schema.params)}` : void 0;
1147
+ const response = schema.response ? `${context.typePrefix}${validTypeName(schema.response)}` : void 0;
1148
+ const comments = codeComments(
1149
+ {
1150
+ metadata: {
1151
+ description: schema.description,
1152
+ isDeprecated: schema.isDeprecated
1153
+ }
1154
+ },
1155
+ ` `
1156
+ );
1157
+ return `${comments} public func ${name}(${params ? `_ params: ${params}` : ""}) async throws -> ${response ?? "()"} {
1158
+ throw ArriRequestError.notImplemented
1159
+ }`;
1160
+ }
1161
+ function swiftServiceFromSchema(schema, context) {
1162
+ const serviceName = getServiceName(
1163
+ context.instancePath,
1164
+ context.clientName
1165
+ );
1166
+ const services = [];
1167
+ const procedureParts = [];
1168
+ const subContent = [];
1169
+ for (const key of Object.keys(schema)) {
1170
+ const subSchema = schema[key];
1171
+ if (codegenUtils.isServiceDefinition(subSchema)) {
1172
+ const subService = swiftServiceFromSchema(subSchema, {
1173
+ clientVersion: context.clientVersion,
1174
+ clientName: context.clientName,
1175
+ typePrefix: context.typePrefix,
1176
+ instancePath: `${context.instancePath}.${key}`,
1177
+ schemaPath: `${context.schemaPath}.${key}`,
1178
+ generatedTypes: context.generatedTypes,
1179
+ containsRequiredRef: context.containsRequiredRef
1180
+ });
1181
+ if (subService) {
1182
+ const subServiceKey = validSwiftKey(key);
1183
+ const subServiceName = getServiceName(
1184
+ `${context.instancePath}.${key}`,
1185
+ context.clientName
1186
+ );
1187
+ services.push({
1188
+ key: subServiceKey,
1189
+ typeName: subServiceName
1190
+ });
1191
+ subContent.push(subService);
1192
+ }
1193
+ continue;
1194
+ }
1195
+ if (codegenUtils.isRpcDefinition(subSchema)) {
1196
+ const rpc = swiftProcedureFromSchema(subSchema, {
1197
+ clientVersion: context.clientVersion,
1198
+ clientName: context.clientName,
1199
+ typePrefix: context.typePrefix,
1200
+ instancePath: `${context.instancePath}.${key}`,
1201
+ schemaPath: `${context.schemaPath}.${key}`,
1202
+ generatedTypes: context.generatedTypes,
1203
+ containsRequiredRef: context.containsRequiredRef
1204
+ });
1205
+ if (rpc) {
1206
+ procedureParts.push(rpc);
1207
+ }
1208
+ continue;
1209
+ }
1210
+ }
1211
+ return `public class ${serviceName} {
1212
+ let baseURL: String
1213
+ let delegate: ArriRequestDelegate
1214
+ let headers: () -> Dictionary<String, String>
1215
+ ${services.map((service) => ` public let ${service.key}: ${service.typeName}`).join("\n")}
1216
+ public init(
1217
+ baseURL: String,
1218
+ delegate: ArriRequestDelegate,
1219
+ headers: @escaping () -> Dictionary<String, String>
1220
+ ) {
1221
+ self.baseURL = baseURL
1222
+ self.delegate = delegate
1223
+ self.headers = headers
1224
+ ${services.map(
1225
+ (service) => ` self.${service.key} = ${service.typeName}(
1226
+ baseURL: baseURL,
1227
+ delegate: delegate,
1228
+ headers: headers
1229
+ )`
1230
+ ).join("\n")}
1231
+ }
1232
+ ${procedureParts.join("\n")}
1233
+
1234
+ }
1235
+
1236
+ ${subContent.join("\n")}`;
1237
+ }
1238
+ function getServiceName(instancePath, clientName) {
1239
+ if (instancePath.length === 0) {
1240
+ return clientName;
1241
+ }
1242
+ const name = `${clientName}${validTypeName(instancePath.split(".").join("_"))}Service`;
1243
+ return name;
1244
+ }
1245
+
1246
+ function swiftDictionaryFromSchema(schema, context) {
1247
+ const subType = swiftTypeFromSchema(schema.values, {
1248
+ clientVersion: context.clientVersion,
1249
+ clientName: context.clientName,
1250
+ typePrefix: context.typePrefix,
1251
+ instancePath: `${context.instancePath}/[value]`,
1252
+ schemaPath: `${context.schemaPath}/values`,
1253
+ generatedTypes: context.generatedTypes,
1254
+ containsRequiredRef: context.containsRequiredRef
1255
+ });
1256
+ const isNullable = isNullableType(schema, context);
1257
+ const typeName = isNullable ? `Dictionary<String, ${subType.typeName}>?` : `Dictionary<String, ${subType.typeName}>`;
1258
+ const defaultValue = isNullable ? `` : `Dictionary()`;
1259
+ return {
1260
+ typeName,
1261
+ isNullable,
1262
+ defaultValue,
1263
+ canBeQueryString: false,
1264
+ hasRequiredRef: false,
1265
+ fromJsonTemplate(input, target, _) {
1266
+ const mainContent = ` ${target} = Dictionary()
1267
+ for (__key, __value) in ${input}.dictionary ?? Dictionary() {
1268
+ var __parsedValue: ${subType.typeName}
1269
+ ${subType.fromJsonTemplate(`__value`, `__parsedValue`, `__parsedValue`)}
1270
+ ${target}${isNullable ? "!" : ""}[__key] = __parsedValue
1271
+ }`;
1272
+ if (context.isOptional) {
1273
+ return ` if ${input}.exists() {
1274
+ ${mainContent}
1275
+ }`;
1276
+ }
1277
+ if (schema.nullable) {
1278
+ return ` if ${input}.dictionary != nil {
1279
+ ${mainContent}
1280
+ }`;
1281
+ }
1282
+ return mainContent;
1283
+ },
1284
+ toJsonTemplate(input, target) {
1285
+ const mainContent = ` ${target} += "{"
1286
+ for (__index, (__key, __value)) in ${input}${isNullable ? "!" : ""}.enumerated() {
1287
+ if __index > 0 {
1288
+ ${target} += ","
1289
+ }
1290
+ ${target} += "\\"\\(__key)\\":"
1291
+ ${subType.toJsonTemplate("__value", target)}
1292
+ }
1293
+ ${target} += "}"`;
1294
+ if (schema.nullable) {
1295
+ return `if ${input} != nil {
1296
+ ${mainContent}
1297
+ } else {
1298
+ ${target} += "null"
1299
+ }`;
1300
+ }
1301
+ return mainContent;
1302
+ },
1303
+ toQueryPartTemplate(_, __, ___) {
1304
+ return ` print("[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
1305
+ },
1306
+ cloneTemplate(input, key) {
1307
+ const innerKey = validSwiftKey(key);
1308
+ const subTypeClonedResult = subType.cloneTemplate?.(
1309
+ `__${innerKey}Value`,
1310
+ `__${innerKey}Value`
1311
+ );
1312
+ if (isNullable) {
1313
+ return {
1314
+ bodyContent: `var __${innerKey}Cloned: ${typeName}
1315
+ if ${input} != nil {
1316
+ __${innerKey}Cloned = Dictionary()
1317
+ for (__${innerKey}Key, __${innerKey}Value) in ${input}! {
1318
+ ${subTypeClonedResult?.bodyContent ?? ""}
1319
+ __${innerKey}Cloned![__${innerKey}Key] = ${subTypeClonedResult?.fieldContent ?? `__${innerKey}Value`}
1320
+ }
1321
+ }`,
1322
+ fieldContent: `__${innerKey}Cloned`
1323
+ };
1324
+ }
1325
+ return {
1326
+ bodyContent: `var __${innerKey}Cloned: ${typeName} = Dictionary()
1327
+ for (__${innerKey}Key, __${innerKey}Value) in ${input} {
1328
+ ${subTypeClonedResult?.bodyContent ?? ""}
1329
+ __${innerKey}Cloned[__${innerKey}Key] = ${subTypeClonedResult?.fieldContent ?? `__${innerKey}Value`}
1330
+ }`,
1331
+ fieldContent: `__${innerKey}Cloned`
1332
+ };
1333
+ },
1334
+ content: subType.content
1335
+ };
1336
+ }
1337
+
1338
+ function swiftRefFromSchema(schema, context) {
1339
+ const typeName = validTypeName(schema.ref);
1340
+ const prefixedTypeName = `${context.typePrefix}${typeName}`;
1341
+ const isNullable = isNullableType(schema, context);
1342
+ const defaultValue = isNullable ? `` : `${prefixedTypeName}()`;
1343
+ return {
1344
+ typeName: isNullable ? `${prefixedTypeName}?` : prefixedTypeName,
1345
+ isNullable,
1346
+ defaultValue,
1347
+ canBeQueryString: false,
1348
+ hasRequiredRef: !isNullable,
1349
+ fromJsonTemplate(input, target, _key) {
1350
+ if (context.isOptional) {
1351
+ return `if ${input}.exists() {
1352
+ ${target} = ${prefixedTypeName}(json: ${input})
1353
+ }`;
1354
+ }
1355
+ if (schema.nullable) {
1356
+ return `if ${input}.dictionary != nil {
1357
+ ${target} = ${prefixedTypeName}(json: ${input})
1358
+ }`;
1359
+ }
1360
+ return `${target} = ${prefixedTypeName}(json: ${input})`;
1361
+ },
1362
+ toJsonTemplate(input, target) {
1363
+ const mainContent = `${target} += ${input}${isNullable ? "!" : ""}.toJSONString()`;
1364
+ if (schema.nullable) {
1365
+ return `if ${input} != nil {
1366
+ ${mainContent}
1367
+ } else {
1368
+ ${target} += "null"
1369
+ }`;
1370
+ }
1371
+ return mainContent;
1372
+ },
1373
+ toQueryPartTemplate(_, __, ___) {
1374
+ return `print("[WARNING] nested objects cannot be serialized to query params. Skipping field at ${context.instancePath}.")`;
1375
+ },
1376
+ cloneTemplate(input, _) {
1377
+ return {
1378
+ bodyContent: "",
1379
+ fieldContent: `${input}${isNullable ? "?" : ""}.clone()`
1380
+ };
1381
+ },
1382
+ content: ""
1383
+ };
1384
+ }
1385
+
1386
+ const swiftClientGenerator = codegenUtils.defineGeneratorPlugin(
1387
+ (options) => {
1388
+ return {
1389
+ async generator(def, _isDevServer) {
1390
+ const content = createSwiftClient(def, options);
1391
+ fs__default.writeFileSync(options.outputFile, content, "utf8");
1392
+ },
1393
+ options
1394
+ };
1395
+ }
1396
+ );
1397
+ function createSwiftClient(def, options) {
1398
+ const context = {
1399
+ clientVersion: def.info?.version ?? "",
1400
+ clientName: options.clientName,
1401
+ typePrefix: options.typePrefix ?? "",
1402
+ instancePath: "",
1403
+ schemaPath: "",
1404
+ generatedTypes: [],
1405
+ containsRequiredRef: {}
1406
+ };
1407
+ const services = codegenUtils.unflattenProcedures(def.procedures);
1408
+ const mainService = swiftServiceFromSchema(services, context);
1409
+ const typeContent = [];
1410
+ for (const key of Object.keys(def.definitions)) {
1411
+ const subSchema = def.definitions[key];
1412
+ const subType = swiftTypeFromSchema(subSchema, {
1413
+ clientVersion: context.clientVersion,
1414
+ clientName: context.clientName,
1415
+ typePrefix: context.typePrefix,
1416
+ instancePath: `/${key}`,
1417
+ schemaPath: `/${key}`,
1418
+ generatedTypes: context.generatedTypes,
1419
+ containsRequiredRef: context.containsRequiredRef
1420
+ });
1421
+ if (subType.content) {
1422
+ typeContent.push(subType.content);
1423
+ }
1424
+ }
1425
+ return `import Foundation
1426
+ import ArriClient
1427
+
1428
+ ${mainService}
1429
+ ${typeContent.join("\n")}`;
1430
+ }
1431
+ function swiftTypeFromSchema(schema, context) {
1432
+ if (codegenUtils.isSchemaFormType(schema)) {
1433
+ switch (schema.type) {
1434
+ case "string":
1435
+ return swiftStringFromSchema(schema, context);
1436
+ case "boolean":
1437
+ return swiftBooleanFromSchema(schema, context);
1438
+ case "timestamp":
1439
+ return swiftTimestampFromSchema(schema, context);
1440
+ case "float32":
1441
+ return swiftNumberFromSchema(
1442
+ schema,
1443
+ context,
1444
+ "Float32",
1445
+ "float",
1446
+ "0.0"
1447
+ );
1448
+ case "float64":
1449
+ return swiftNumberFromSchema(
1450
+ schema,
1451
+ context,
1452
+ "Float64",
1453
+ "double",
1454
+ "0.0"
1455
+ );
1456
+ case "int8":
1457
+ return swiftNumberFromSchema(
1458
+ schema,
1459
+ context,
1460
+ "Int8",
1461
+ "int8",
1462
+ "0"
1463
+ );
1464
+ case "uint8":
1465
+ return swiftNumberFromSchema(
1466
+ schema,
1467
+ context,
1468
+ "UInt8",
1469
+ "uInt8",
1470
+ "0"
1471
+ );
1472
+ case "int16":
1473
+ return swiftNumberFromSchema(
1474
+ schema,
1475
+ context,
1476
+ "Int16",
1477
+ "int16",
1478
+ "0"
1479
+ );
1480
+ case "uint16":
1481
+ return swiftNumberFromSchema(
1482
+ schema,
1483
+ context,
1484
+ "UInt16",
1485
+ "uInt16",
1486
+ "0"
1487
+ );
1488
+ case "int32":
1489
+ return swiftNumberFromSchema(
1490
+ schema,
1491
+ context,
1492
+ "Int32",
1493
+ "int32",
1494
+ "0"
1495
+ );
1496
+ case "uint32":
1497
+ return swiftNumberFromSchema(
1498
+ schema,
1499
+ context,
1500
+ "UInt32",
1501
+ "uInt32",
1502
+ "0"
1503
+ );
1504
+ case "int64":
1505
+ return swiftLargeIntFromSchema(schema, context, "Int64");
1506
+ case "uint64":
1507
+ return swiftLargeIntFromSchema(schema, context, "UInt64");
1508
+ default:
1509
+ schema.type;
1510
+ break;
1511
+ }
1512
+ }
1513
+ if (codegenUtils.isSchemaFormEnum(schema)) {
1514
+ return swiftEnumFromSchema(schema, context);
1515
+ }
1516
+ if (codegenUtils.isSchemaFormProperties(schema)) {
1517
+ return swiftObjectFromSchema(schema, context);
1518
+ }
1519
+ if (codegenUtils.isSchemaFormElements(schema)) {
1520
+ return swiftArrayFromSchema(schema, context);
1521
+ }
1522
+ if (codegenUtils.isSchemaFormValues(schema)) {
1523
+ return swiftDictionaryFromSchema(schema, context);
1524
+ }
1525
+ if (codegenUtils.isSchemaFormDiscriminator(schema)) {
1526
+ return swiftTaggedUnionFromSchema(schema, context);
1527
+ }
1528
+ if (codegenUtils.isSchemaFormRef(schema)) {
1529
+ return swiftRefFromSchema(schema, context);
1530
+ }
1531
+ return swiftAnyFromSchema(schema, context);
1532
+ }
1533
+
1534
+ exports.createSwiftClient = createSwiftClient;
1535
+ exports.swiftClientGenerator = swiftClientGenerator;
1536
+ exports.swiftTypeFromSchema = swiftTypeFromSchema;