ajsc 5.2.3 → 7.0.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.
Files changed (141) hide show
  1. package/README.md +253 -145
  2. package/dist/converter/BaseConverter.d.ts +283 -0
  3. package/dist/converter/BaseConverter.js +131 -0
  4. package/dist/converter/BaseConverter.js.map +1 -0
  5. package/dist/converter/Emitter.d.ts +35 -0
  6. package/dist/converter/Emitter.js +50 -0
  7. package/dist/converter/Emitter.js.map +1 -0
  8. package/dist/converter/discriminatedUnions.d.ts +47 -0
  9. package/dist/converter/discriminatedUnions.js +168 -0
  10. package/dist/converter/discriminatedUnions.js.map +1 -0
  11. package/dist/converter/formatDefault.d.ts +20 -0
  12. package/dist/converter/formatDefault.js +31 -0
  13. package/dist/converter/formatDefault.js.map +1 -0
  14. package/dist/converter/index.d.ts +2 -0
  15. package/dist/converter/index.js +2 -0
  16. package/dist/converter/index.js.map +1 -0
  17. package/dist/converter/mergeUnions.d.ts +36 -0
  18. package/dist/converter/mergeUnions.js +189 -0
  19. package/dist/converter/mergeUnions.js.map +1 -0
  20. package/dist/converter/naming.d.ts +29 -0
  21. package/dist/converter/naming.js +130 -0
  22. package/dist/converter/naming.js.map +1 -0
  23. package/dist/converter/registry.d.ts +18 -0
  24. package/dist/converter/registry.js +50 -0
  25. package/dist/converter/registry.js.map +1 -0
  26. package/dist/converter/walk.d.ts +9 -0
  27. package/dist/converter/walk.js +40 -0
  28. package/dist/converter/walk.js.map +1 -0
  29. package/dist/index.d.ts +71 -3
  30. package/dist/index.js +63 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/{JSONSchemaConverter.d.ts → ir/JSONSchemaConverter.d.ts} +1 -1
  33. package/dist/{JSONSchemaConverter.js → ir/JSONSchemaConverter.js} +9 -3
  34. package/dist/ir/JSONSchemaConverter.js.map +1 -0
  35. package/dist/ir/index.d.ts +1 -0
  36. package/dist/ir/index.js +2 -0
  37. package/dist/ir/index.js.map +1 -0
  38. package/dist/kotlin/KotlinBaseConverter.d.ts +18 -0
  39. package/dist/kotlin/KotlinBaseConverter.js +36 -0
  40. package/dist/kotlin/KotlinBaseConverter.js.map +1 -0
  41. package/dist/kotlin/KotlinConverter.d.ts +67 -0
  42. package/dist/kotlin/KotlinConverter.js +140 -0
  43. package/dist/kotlin/KotlinConverter.js.map +1 -0
  44. package/dist/kotlin/annotations.d.ts +26 -0
  45. package/dist/kotlin/annotations.js +35 -0
  46. package/dist/kotlin/annotations.js.map +1 -0
  47. package/dist/kotlin/enums.d.ts +15 -0
  48. package/dist/kotlin/enums.js +58 -0
  49. package/dist/kotlin/enums.js.map +1 -0
  50. package/dist/kotlin/index.d.ts +2 -0
  51. package/dist/kotlin/index.js +3 -0
  52. package/dist/kotlin/index.js.map +1 -0
  53. package/dist/kotlin/objectEmitter.d.ts +12 -0
  54. package/dist/kotlin/objectEmitter.js +74 -0
  55. package/dist/kotlin/objectEmitter.js.map +1 -0
  56. package/dist/kotlin/sealedUnion.d.ts +17 -0
  57. package/dist/kotlin/sealedUnion.js +74 -0
  58. package/dist/kotlin/sealedUnion.js.map +1 -0
  59. package/dist/kotlin/typeMapper.d.ts +17 -0
  60. package/dist/kotlin/typeMapper.js +107 -0
  61. package/dist/kotlin/typeMapper.js.map +1 -0
  62. package/dist/kotlin/unsupported.d.ts +13 -0
  63. package/dist/kotlin/unsupported.js +53 -0
  64. package/dist/kotlin/unsupported.js.map +1 -0
  65. package/dist/swift/SwiftBaseConverter.d.ts +18 -0
  66. package/dist/swift/SwiftBaseConverter.js +38 -0
  67. package/dist/swift/SwiftBaseConverter.js.map +1 -0
  68. package/dist/swift/SwiftConverter.d.ts +60 -0
  69. package/dist/swift/SwiftConverter.js +111 -0
  70. package/dist/swift/SwiftConverter.js.map +1 -0
  71. package/dist/swift/discriminatedEnum.d.ts +18 -0
  72. package/dist/swift/discriminatedEnum.js +99 -0
  73. package/dist/swift/discriminatedEnum.js.map +1 -0
  74. package/dist/swift/enums.d.ts +15 -0
  75. package/dist/swift/enums.js +62 -0
  76. package/dist/swift/enums.js.map +1 -0
  77. package/dist/swift/index.d.ts +2 -0
  78. package/dist/swift/index.js +3 -0
  79. package/dist/swift/index.js.map +1 -0
  80. package/dist/swift/structEmitter.d.ts +12 -0
  81. package/dist/swift/structEmitter.js +70 -0
  82. package/dist/swift/structEmitter.js.map +1 -0
  83. package/dist/swift/typeMapper.d.ts +18 -0
  84. package/dist/swift/typeMapper.js +106 -0
  85. package/dist/swift/typeMapper.js.map +1 -0
  86. package/dist/swift/unsupported.d.ts +19 -0
  87. package/dist/swift/unsupported.js +88 -0
  88. package/dist/swift/unsupported.js.map +1 -0
  89. package/dist/typescript/TypescriptBaseConverter.d.ts +25 -0
  90. package/dist/typescript/TypescriptBaseConverter.js +178 -0
  91. package/dist/typescript/TypescriptBaseConverter.js.map +1 -0
  92. package/dist/typescript/TypescriptConverter.d.ts +74 -0
  93. package/dist/typescript/TypescriptConverter.js +252 -0
  94. package/dist/typescript/TypescriptConverter.js.map +1 -0
  95. package/dist/typescript/index.d.ts +2 -0
  96. package/dist/typescript/index.js +3 -0
  97. package/dist/typescript/index.js.map +1 -0
  98. package/dist/utils/index.d.ts +2 -0
  99. package/dist/utils/index.js +3 -0
  100. package/dist/utils/index.js.map +1 -0
  101. package/package.json +37 -5
  102. package/dist/JSONSchemaConverter.js.map +0 -1
  103. package/dist/JSONSchemaConverter.test.d.ts +0 -1
  104. package/dist/JSONSchemaConverter.test.js +0 -585
  105. package/dist/JSONSchemaConverter.test.js.map +0 -1
  106. package/dist/Typebox.test.d.ts +0 -1
  107. package/dist/Typebox.test.js +0 -88
  108. package/dist/Typebox.test.js.map +0 -1
  109. package/dist/TypescriptBaseConverter.d.ts +0 -75
  110. package/dist/TypescriptBaseConverter.js +0 -321
  111. package/dist/TypescriptBaseConverter.js.map +0 -1
  112. package/dist/TypescriptConverter.additionalProperties.test.d.ts +0 -1
  113. package/dist/TypescriptConverter.additionalProperties.test.js +0 -110
  114. package/dist/TypescriptConverter.additionalProperties.test.js.map +0 -1
  115. package/dist/TypescriptConverter.arrays.test.d.ts +0 -1
  116. package/dist/TypescriptConverter.arrays.test.js +0 -130
  117. package/dist/TypescriptConverter.arrays.test.js.map +0 -1
  118. package/dist/TypescriptConverter.composites.advanced.test.d.ts +0 -1
  119. package/dist/TypescriptConverter.composites.advanced.test.js +0 -924
  120. package/dist/TypescriptConverter.composites.advanced.test.js.map +0 -1
  121. package/dist/TypescriptConverter.composites.test.d.ts +0 -1
  122. package/dist/TypescriptConverter.composites.test.js +0 -335
  123. package/dist/TypescriptConverter.composites.test.js.map +0 -1
  124. package/dist/TypescriptConverter.d.ts +0 -163
  125. package/dist/TypescriptConverter.js +0 -595
  126. package/dist/TypescriptConverter.js.map +0 -1
  127. package/dist/TypescriptConverter.jsdoc.test.d.ts +0 -1
  128. package/dist/TypescriptConverter.jsdoc.test.js +0 -194
  129. package/dist/TypescriptConverter.jsdoc.test.js.map +0 -1
  130. package/dist/TypescriptConverter.objects.test.d.ts +0 -1
  131. package/dist/TypescriptConverter.objects.test.js +0 -258
  132. package/dist/TypescriptConverter.objects.test.js.map +0 -1
  133. package/dist/TypescriptConverter.options.test.d.ts +0 -1
  134. package/dist/TypescriptConverter.options.test.js +0 -501
  135. package/dist/TypescriptConverter.options.test.js.map +0 -1
  136. package/dist/TypescriptConverter.primitives.test.d.ts +0 -1
  137. package/dist/TypescriptConverter.primitives.test.js +0 -26
  138. package/dist/TypescriptConverter.primitives.test.js.map +0 -1
  139. package/dist/utils/path-utils.test.d.ts +0 -1
  140. package/dist/utils/path-utils.test.js +0 -92
  141. package/dist/utils/path-utils.test.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { BaseConverter } from "../converter/BaseConverter.js";
2
+ export const SWIFT_RESERVED = new Set([
3
+ "associatedtype", "class", "deinit", "enum", "extension", "fileprivate",
4
+ "func", "import", "init", "inout", "internal", "let", "open", "operator",
5
+ "private", "protocol", "public", "static", "struct", "subscript",
6
+ "typealias", "var", "break", "case", "continue", "default", "defer",
7
+ "do", "else", "fallthrough", "for", "guard", "if", "in", "repeat",
8
+ "return", "switch", "where", "while", "as", "Any", "catch", "false",
9
+ "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws",
10
+ "true", "try",
11
+ ]);
12
+ /**
13
+ * Converts a JSON property key to a valid Swift identifier:
14
+ * - kebab/snake → camelCase
15
+ * - non-identifier chars stripped
16
+ * - leading digit gets `_` prefix
17
+ * - reserved words wrapped in backticks
18
+ * - empty result becomes "value"
19
+ */
20
+ export function sanitizeSwiftIdentifier(raw) {
21
+ let name = raw.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
22
+ name = name.replace(/[^a-zA-Z0-9_]/g, "");
23
+ if (!name)
24
+ name = "value";
25
+ if (/^\d/.test(name))
26
+ name = "_" + name;
27
+ if (SWIFT_RESERVED.has(name))
28
+ name = "`" + name + "`";
29
+ return name;
30
+ }
31
+ export class SwiftBaseConverter extends BaseConverter {
32
+ constructor() {
33
+ super(...arguments);
34
+ /** @internal Mutated by SwiftConverter helper modules; not part of the public API. */
35
+ this.importsSet = new Set();
36
+ }
37
+ }
38
+ //# sourceMappingURL=SwiftBaseConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwiftBaseConverter.js","sourceRoot":"","sources":["../../src/swift/SwiftBaseConverter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqB,MAAM,+BAA+B,CAAC;AAGjF,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IACpC,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa;IACvE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU;IACxE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW;IAChE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO;IACnE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ;IACjE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO;IACnE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;IACnE,MAAM,EAAE,KAAK;CACd,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,IAAI,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAE,CAAY,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI;QAAE,IAAI,GAAG,OAAO,CAAC;IAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACxC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAgB,kBAAmB,SAAQ,aAAa;IAA9D;;QACE,sFAAsF;QAC/E,eAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAIxC,CAAC;CAAA"}
@@ -0,0 +1,60 @@
1
+ import { JSONSchema7Definition } from "json-schema";
2
+ import { ILanguageConverter, IRNode } from "../types.js";
3
+ import { BaseConverterContext, BaseConverterOpts, GenerateTypeUtils, LanguageProfile } from "../converter/BaseConverter.js";
4
+ import { SwiftBaseConverter } from "./SwiftBaseConverter.js";
5
+ export interface SwiftConverterOpts extends BaseConverterOpts {
6
+ serializer?: "codable" | "none";
7
+ accessLevel?: "public" | "internal";
8
+ }
9
+ /**
10
+ * The state-and-method surface that helper modules in `src/swift/` need to
11
+ * operate on a SwiftConverter instance. SwiftConverter implements this;
12
+ * helpers take it as their first argument.
13
+ *
14
+ * @internal
15
+ */
16
+ export interface SwiftConverterContext extends BaseConverterContext {
17
+ readonly isCodable: boolean;
18
+ readonly accessLevel: "public" | "internal";
19
+ needsAnyCodable: boolean;
20
+ readonly importsSet: Set<string>;
21
+ readonly docFormatNodes: WeakMap<IRNode, string>;
22
+ readonly enumDecls: Map<string, {
23
+ name: string;
24
+ values: string[];
25
+ }>;
26
+ readonly sealedEnumDecls: string[];
27
+ generateType(ir: IRNode, utils: GenerateTypeUtils): string;
28
+ emitSwiftDiscriminatedEnum(ir: IRNode, utils: GenerateTypeUtils): string;
29
+ }
30
+ export declare class SwiftConverter extends SwiftBaseConverter implements ILanguageConverter, SwiftConverterContext {
31
+ readonly code: string;
32
+ readonly rootTypeName: string;
33
+ readonly extractedTypeNames: string[];
34
+ readonly imports: string[];
35
+ /** @internal Public for `BaseConverterContext`; treat as protected for subclasses. */
36
+ readonly languageProfile: LanguageProfile;
37
+ /** @internal Mutated by SwiftConverter helper modules; not part of the public API. */
38
+ isCodable: boolean;
39
+ /** @internal */
40
+ accessLevel: "public" | "internal";
41
+ /** @internal */
42
+ enumDecls: Map<string, {
43
+ name: string;
44
+ values: string[];
45
+ }>;
46
+ /** @internal */
47
+ docFormatNodes: WeakMap<IRNode, string>;
48
+ /** @internal */
49
+ sealedEnumDecls: string[];
50
+ /** @internal */
51
+ needsAnyCodable: boolean;
52
+ constructor(schema: JSONSchema7Definition, opts?: SwiftConverterOpts);
53
+ protected codableConformance(): string;
54
+ /** @internal Public for `SwiftConverterContext`; treat as protected for subclasses. */
55
+ generateType(ir: IRNode, utils: GenerateTypeUtils): string;
56
+ /** @internal Public for `BaseConverterContext`; treat as protected for subclasses. */
57
+ generateObjectType(ir: IRNode, utils: GenerateTypeUtils): string;
58
+ /** @internal Public for `SwiftConverterContext`; treat as protected for subclasses. */
59
+ emitSwiftDiscriminatedEnum(ir: IRNode, utils: GenerateTypeUtils): string;
60
+ }
@@ -0,0 +1,111 @@
1
+ import { JSONSchemaConverter } from "../ir/JSONSchemaConverter.js";
2
+ import { SwiftBaseConverter } from "./SwiftBaseConverter.js";
3
+ import { guardUnsupportedKeywords, anyCodableHelper } from "./unsupported.js";
4
+ import { buildEnumDeclarations } from "./enums.js";
5
+ import { generateSwiftType } from "./typeMapper.js";
6
+ import { generateSwiftObjectType } from "./structEmitter.js";
7
+ import { emitSwiftDiscriminatedEnum } from "./discriminatedEnum.js";
8
+ export class SwiftConverter extends SwiftBaseConverter {
9
+ constructor(schema, opts) {
10
+ super();
11
+ /** @internal */
12
+ this.enumDecls = new Map();
13
+ /** @internal */
14
+ this.docFormatNodes = new WeakMap();
15
+ /** @internal */
16
+ this.sealedEnumDecls = [];
17
+ /** @internal */
18
+ this.needsAnyCodable = false;
19
+ this.baseOpts = opts;
20
+ this.isCodable = (opts?.serializer ?? "codable") === "codable";
21
+ this.accessLevel = opts?.accessLevel ?? "public";
22
+ this.languageProfile = {
23
+ language: "swift",
24
+ processOneOfAsDiscriminatedUnion: true,
25
+ shouldEraseDiscriminator: this.isCodable,
26
+ getDiscriminatedVariantParentName: () => "",
27
+ };
28
+ const ir = this.mergeCompatibleUnions(new JSONSchemaConverter(schema).irNode);
29
+ this.enhanceDiscriminatedUnions(ir);
30
+ guardUnsupportedKeywords(this, ir);
31
+ if (opts?.rootTypeName)
32
+ ir.name = opts.rootTypeName;
33
+ if (!ir.name)
34
+ ir.name = ir.title || "Root";
35
+ this.rootName = ir.name;
36
+ this.usedDeclarationNames.add(ir.name);
37
+ const utils = {
38
+ getReferencedType: this.getReferencedType.bind(this),
39
+ };
40
+ // Root-level string enum: emit a single Swift `enum` and skip the struct path.
41
+ if (ir.type === "enum" && ir.values?.every((v) => typeof v === "string")) {
42
+ const key = JSON.stringify([...ir.values].sort());
43
+ this.enumDecls.set(key, { name: ir.name, values: ir.values });
44
+ const enumCode = buildEnumDeclarations(this);
45
+ this.code = enumCode.join("\n\n") + "\n";
46
+ this.rootTypeName = ir.name;
47
+ this.extractedTypeNames = [];
48
+ this.imports = [...this.importsSet].sort();
49
+ return;
50
+ }
51
+ let rootDecl;
52
+ let needsRootStruct = true;
53
+ if (ir.type === "union" &&
54
+ ir.options?.length &&
55
+ ir.options.every((o) => this.variantNames.has(o))) {
56
+ // Root IS the discriminated union — emit it as a Swift enum directly.
57
+ this.emitSwiftDiscriminatedEnum(ir, utils);
58
+ needsRootStruct = false;
59
+ rootDecl = "";
60
+ }
61
+ else {
62
+ const rootBody = this.generateObjectType(ir, utils);
63
+ const rootDoc = this.rootDoc;
64
+ const rootDocPrefix = rootDoc ? `/// ${rootDoc}\n` : "";
65
+ rootDecl = `${rootDocPrefix}${this.accessLevel} struct ${ir.name}${this.codableConformance()} ${rootBody}`;
66
+ }
67
+ const childDecls = this.refTypes
68
+ .filter(({ name }) => name !== this.rootName)
69
+ .map(({ name, code, doc }) => {
70
+ const docPrefix = doc ? `/// ${doc}\n` : "";
71
+ return `${docPrefix}${this.accessLevel} struct ${name}${this.codableConformance()} ${code}`;
72
+ });
73
+ const enumCode = buildEnumDeclarations(this);
74
+ const allDecls = [...enumCode, ...this.sealedEnumDecls, ...childDecls];
75
+ if (needsRootStruct)
76
+ allDecls.push(rootDecl);
77
+ this.code = allDecls.filter(Boolean).join("\n\n") + "\n";
78
+ if (this.needsAnyCodable) {
79
+ this.code += "\n" + anyCodableHelper(this) + "\n";
80
+ }
81
+ this.rootTypeName = ir.name;
82
+ const refTypeNames = this.computeExtractedTypeNames().filter((n) => n !== this.rootTypeName);
83
+ const enumNames = [...this.enumDecls.values()].map(({ name }) => name).filter((n) => n !== this.rootTypeName);
84
+ const variantStructNames = [];
85
+ for (const decl of this.sealedEnumDecls) {
86
+ const matches = decl.matchAll(/struct (\w+)/g);
87
+ for (const m of matches) {
88
+ if (m[1] !== this.rootTypeName)
89
+ variantStructNames.push(m[1]);
90
+ }
91
+ }
92
+ this.extractedTypeNames = [...new Set([...variantStructNames, ...enumNames, ...refTypeNames])];
93
+ this.imports = [...this.importsSet].sort();
94
+ }
95
+ codableConformance() {
96
+ return this.isCodable ? ": Codable" : "";
97
+ }
98
+ /** @internal Public for `SwiftConverterContext`; treat as protected for subclasses. */
99
+ generateType(ir, utils) {
100
+ return generateSwiftType(this, ir, utils);
101
+ }
102
+ /** @internal Public for `BaseConverterContext`; treat as protected for subclasses. */
103
+ generateObjectType(ir, utils) {
104
+ return generateSwiftObjectType(this, ir, utils);
105
+ }
106
+ /** @internal Public for `SwiftConverterContext`; treat as protected for subclasses. */
107
+ emitSwiftDiscriminatedEnum(ir, utils) {
108
+ return emitSwiftDiscriminatedEnum(this, ir, utils);
109
+ }
110
+ }
111
+ //# sourceMappingURL=SwiftConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwiftConverter.js","sourceRoot":"","sources":["../../src/swift/SwiftConverter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { GenerateTypeUtils } from "../converter/BaseConverter.js";
2
+ import { IRNode } from "../types.js";
3
+ import type { SwiftConverterContext } from "./SwiftConverter.js";
4
+ /**
5
+ * Emits a Swift `enum` with associated-value cases plus per-variant nested
6
+ * `struct` declarations for a discriminated union, registering them in
7
+ * `c.sealedEnumDecls`. Idempotent for nested visits: re-emitting the same
8
+ * enum short-circuits via `sealedEnumDeclsContainsName`.
9
+ */
10
+ export declare function emitSwiftDiscriminatedEnum(c: SwiftConverterContext, ir: IRNode, utils: GenerateTypeUtils): string;
11
+ /** Derives the Swift discriminated-enum name for a union IR node. */
12
+ export declare function deriveSwiftSealedName(c: SwiftConverterContext, ir: IRNode): string;
13
+ /**
14
+ * Substring-scans `c.sealedEnumDecls` for an existing declaration matching the
15
+ * given name. Used to detect prior emission so the orchestrator can skip the
16
+ * regular ref-types path for sealed variants.
17
+ */
18
+ export declare function sealedEnumDeclsContainsName(c: SwiftConverterContext, name: string): boolean;
@@ -0,0 +1,99 @@
1
+ import { Emitter } from "../converter/Emitter.js";
2
+ import { toSwiftCaseName } from "./enums.js";
3
+ import { generateSwiftObjectType } from "./structEmitter.js";
4
+ /**
5
+ * Emits a Swift `enum` with associated-value cases plus per-variant nested
6
+ * `struct` declarations for a discriminated union, registering them in
7
+ * `c.sealedEnumDecls`. Idempotent for nested visits: re-emitting the same
8
+ * enum short-circuits via `sealedEnumDeclsContainsName`.
9
+ */
10
+ export function emitSwiftDiscriminatedEnum(c, ir, utils) {
11
+ const enumName = deriveSwiftSealedName(c, ir);
12
+ if (c.usedDeclarationNames.has(enumName) && sealedEnumDeclsContainsName(c, enumName)) {
13
+ return enumName;
14
+ }
15
+ c.usedDeclarationNames.add(enumName);
16
+ const options = ir.options;
17
+ const discriminator = c.findDiscriminatorProperty(options, c.collectUnionPropertyNames(options).sharedPropNames);
18
+ if (!discriminator)
19
+ return "Any";
20
+ const variants = [];
21
+ for (const opt of options) {
22
+ const variantName = c.variantNames.get(opt);
23
+ const discValue = c.getConstStringValue(opt.properties[discriminator]);
24
+ const caseName = toSwiftCaseName(discValue);
25
+ // Build nested struct body, optionally erasing discriminator under codable
26
+ const tempIR = c.stripDiscriminatorField(opt, discriminator);
27
+ const body = generateSwiftObjectType(c, tempIR, utils);
28
+ variants.push({ caseName, structName: variantName, discValue, body });
29
+ }
30
+ const accessLevel = c.accessLevel;
31
+ const conformance = c.isCodable ? ": Codable" : "";
32
+ const e = new Emitter({ indentUnit: " " });
33
+ e.block(`${accessLevel} enum ${enumName}${conformance}`, () => {
34
+ for (const v of variants) {
35
+ e.line(`case ${v.caseName}(${v.structName})`);
36
+ }
37
+ e.blank();
38
+ // Nested variant structs. `v.body` is a `{\n ... \n}` block with its own
39
+ // 2-space inner indentation; `raw()` prefixes each non-empty line with the
40
+ // current Emitter indent (4 spaces here), preserving the existing inner
41
+ // 2-space indent for struct fields.
42
+ for (const v of variants) {
43
+ e.raw(`${accessLevel} struct ${v.structName}${conformance} ${v.body}`);
44
+ e.blank();
45
+ }
46
+ if (c.isCodable) {
47
+ e.line(`private enum CodingKeys: String, CodingKey { case ${discriminator} }`);
48
+ const kindCases = variants
49
+ .map((v) => v.caseName === v.discValue
50
+ ? `case ${v.caseName}`
51
+ : `case ${v.caseName} = "${v.discValue}"`)
52
+ .join("; ");
53
+ e.line(`private enum Kind: String, Codable { ${kindCases} }`);
54
+ e.blank();
55
+ e.block(`${accessLevel} init(from decoder: Decoder) throws`, () => {
56
+ e.line("let container = try decoder.container(keyedBy: CodingKeys.self)");
57
+ e.line(`let kind = try container.decode(Kind.self, forKey: .${discriminator})`);
58
+ e.line("let single = try decoder.singleValueContainer()");
59
+ e.block("switch kind", () => {
60
+ for (const v of variants) {
61
+ e.line(`case .${v.caseName}: self = .${v.caseName}(try single.decode(${v.structName}.self))`);
62
+ }
63
+ });
64
+ });
65
+ e.blank();
66
+ e.block(`${accessLevel} func encode(to encoder: Encoder) throws`, () => {
67
+ e.line("var container = encoder.singleValueContainer()");
68
+ e.block("switch self", () => {
69
+ for (const v of variants) {
70
+ e.line(`case .${v.caseName}(let v): try container.encode(v)`);
71
+ }
72
+ });
73
+ });
74
+ }
75
+ });
76
+ c.sealedEnumDecls.push(e.toString());
77
+ for (const v of variants)
78
+ c.usedDeclarationNames.add(v.structName);
79
+ return enumName;
80
+ }
81
+ /** Derives the Swift discriminated-enum name for a union IR node. */
82
+ export function deriveSwiftSealedName(c, ir) {
83
+ if (ir.name)
84
+ return ir.name;
85
+ if (ir.title)
86
+ return ir.title;
87
+ const segments = ir.path.split(".").filter((x) => !/^\d+$/.test(x));
88
+ const baseName = segments.map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("") || "Union";
89
+ return c.findAvailableName(baseName);
90
+ }
91
+ /**
92
+ * Substring-scans `c.sealedEnumDecls` for an existing declaration matching the
93
+ * given name. Used to detect prior emission so the orchestrator can skip the
94
+ * regular ref-types path for sealed variants.
95
+ */
96
+ export function sealedEnumDeclsContainsName(c, name) {
97
+ return c.sealedEnumDecls.some((d) => d.includes(`enum ${name}`));
98
+ }
99
+ //# sourceMappingURL=discriminatedEnum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discriminatedEnum.js","sourceRoot":"","sources":["../../src/swift/discriminatedEnum.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { SwiftConverterContext } from "./SwiftConverter.js";
2
+ /**
3
+ * Returns or creates a Swift `enum` declaration name for a given set of
4
+ * string values, deduplicating by sorted-values key. Tracks the declaration
5
+ * for later emission via {@link buildEnumDeclarations}.
6
+ */
7
+ export declare function getOrCreateEnumDecl(c: SwiftConverterContext, values: string[], path: string): string;
8
+ /** Sanitizes a JSON enum value into a Swift enum case name (lowerCamelCase). */
9
+ export declare function toSwiftCaseName(value: string): string;
10
+ /**
11
+ * Builds Swift raw-value `enum` declarations from the converter's accumulated
12
+ * `enumDecls` map. Used for both nested enums (rendered alongside structs) and
13
+ * root-level enum schemas (where the root IS the enum).
14
+ */
15
+ export declare function buildEnumDeclarations(c: SwiftConverterContext): string[];
@@ -0,0 +1,62 @@
1
+ import { toPascalCase } from "../utils/to-pascal-case.js";
2
+ /**
3
+ * Returns or creates a Swift `enum` declaration name for a given set of
4
+ * string values, deduplicating by sorted-values key. Tracks the declaration
5
+ * for later emission via {@link buildEnumDeclarations}.
6
+ */
7
+ export function getOrCreateEnumDecl(c, values, path) {
8
+ const key = JSON.stringify([...values].sort());
9
+ const existing = c.enumDecls.get(key);
10
+ if (existing)
11
+ return existing.name;
12
+ const segments = path.split(".").filter((x) => !/^\d+$/.test(x));
13
+ const baseName = segments.map((s) => toPascalCase(s)).join("") || "Value";
14
+ const name = c.findAvailableName(baseName);
15
+ c.usedDeclarationNames.add(name);
16
+ c.enumDecls.set(key, { name, values });
17
+ return name;
18
+ }
19
+ /** Sanitizes a JSON enum value into a Swift enum case name (lowerCamelCase). */
20
+ export function toSwiftCaseName(value) {
21
+ // Step 1: kebab/snake → camelCase, then strip invalid chars.
22
+ let n = value.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
23
+ n = n.replace(/[^a-zA-Z0-9_]/g, "");
24
+ if (!n)
25
+ n = "value";
26
+ if (/^\d/.test(n))
27
+ n = "_" + n;
28
+ // Preserve all-uppercase identifiers (e.g. "US", "URL", "ID") to match Swift convention
29
+ // for acronyms — otherwise they'd render awkwardly as `uS`, `uRL`, etc.
30
+ if (n.length >= 2 && /^[A-Z][A-Z0-9_]*$/.test(n))
31
+ return n;
32
+ // Otherwise lowerCamelCase per Swift convention.
33
+ return n.charAt(0).toLowerCase() + n.slice(1);
34
+ }
35
+ /**
36
+ * Builds Swift raw-value `enum` declarations from the converter's accumulated
37
+ * `enumDecls` map. Used for both nested enums (rendered alongside structs) and
38
+ * root-level enum schemas (where the root IS the enum).
39
+ */
40
+ export function buildEnumDeclarations(c) {
41
+ return [...c.enumDecls.values()].map(({ name, values }) => {
42
+ const usedCases = new Set();
43
+ const cases = values.map((v) => {
44
+ let caseName = toSwiftCaseName(v);
45
+ const baseC = caseName;
46
+ let i = 2;
47
+ while (usedCases.has(caseName)) {
48
+ caseName = baseC + i;
49
+ i++;
50
+ }
51
+ usedCases.add(caseName);
52
+ // emit `case foo` if caseName matches v exactly, else `case foo = "raw"`
53
+ if (caseName === v) {
54
+ return ` case ${caseName}`;
55
+ }
56
+ return ` case ${caseName} = "${v}"`;
57
+ });
58
+ const conformance = c.isCodable ? ", Codable" : "";
59
+ return `${c.accessLevel} enum ${name}: String${conformance} {\n${cases.join("\n")}\n}`;
60
+ });
61
+ }
62
+ //# sourceMappingURL=enums.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enums.js","sourceRoot":"","sources":["../../src/swift/enums.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./SwiftBaseConverter.js";
2
+ export * from "./SwiftConverter.js";
@@ -0,0 +1,3 @@
1
+ export * from "./SwiftBaseConverter.js";
2
+ export * from "./SwiftConverter.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/swift/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { GenerateTypeUtils } from "../converter/BaseConverter.js";
2
+ import { IRNode } from "../types.js";
3
+ import type { SwiftConverterContext } from "./SwiftConverter.js";
4
+ /** Returns true if the property is optional or its type union includes null. */
5
+ export declare function isPropertyNullable(prop: IRNode): boolean;
6
+ /**
7
+ * Emits a Swift struct body for an object IR node, including the property
8
+ * declarations, doc comments for formatted strings, and a `CodingKeys` block
9
+ * when codable conformance requires JSON-key remapping (kebab/snake renames
10
+ * or backticked reserved words).
11
+ */
12
+ export declare function generateSwiftObjectType(c: SwiftConverterContext, ir: IRNode, utils: GenerateTypeUtils): string;
@@ -0,0 +1,70 @@
1
+ import { formatPrimitiveDefault } from "../converter/formatDefault.js";
2
+ import { sanitizeSwiftIdentifier } from "./SwiftBaseConverter.js";
3
+ import { generateSwiftType } from "./typeMapper.js";
4
+ /** Returns true if the property is optional or its type union includes null. */
5
+ export function isPropertyNullable(prop) {
6
+ if (!prop.required)
7
+ return true;
8
+ if (prop.type === "union" && prop.options?.some((o) => o.type === "null"))
9
+ return true;
10
+ return false;
11
+ }
12
+ /**
13
+ * Emits a Swift struct body for an object IR node, including the property
14
+ * declarations, doc comments for formatted strings, and a `CodingKeys` block
15
+ * when codable conformance requires JSON-key remapping (kebab/snake renames
16
+ * or backticked reserved words).
17
+ */
18
+ export function generateSwiftObjectType(c, ir, utils) {
19
+ if (ir.additionalProperties && typeof ir.additionalProperties !== "boolean") {
20
+ const apType = generateSwiftType(c, ir.additionalProperties, utils);
21
+ const note = `Note: schema permits additional keys of type ${apType} — not modeled.`;
22
+ if (ir.signature) {
23
+ const entry = c.refTypes.find((e) => e.signature === ir.signature);
24
+ if (entry)
25
+ entry.doc = note;
26
+ }
27
+ if (ir.name === c.rootName) {
28
+ c.rootDoc = note;
29
+ }
30
+ }
31
+ if (!ir.properties || Object.keys(ir.properties).length === 0) {
32
+ return "{}";
33
+ }
34
+ const propInfos = [];
35
+ const lines = [];
36
+ for (const [key, prop] of Object.entries(ir.properties)) {
37
+ const swiftName = sanitizeSwiftIdentifier(key);
38
+ const type = generateSwiftType(c, prop, utils);
39
+ const nullable = isPropertyNullable(prop);
40
+ const def = formatPrimitiveDefault(prop.defaultValue);
41
+ let suffix;
42
+ if (nullable) {
43
+ suffix = def !== undefined ? `? = ${def}` : "?";
44
+ }
45
+ else {
46
+ suffix = def !== undefined ? ` = ${def}` : "";
47
+ }
48
+ if (c.docFormatNodes.has(prop)) {
49
+ lines.push(` /// ${c.docFormatNodes.get(prop)}`);
50
+ }
51
+ lines.push(` ${c.accessLevel} let ${swiftName}: ${type}${suffix}`);
52
+ // Need a CodingKey if the swift name differs from the JSON key (kebab/snake renames)
53
+ // OR if the swift name uses backticks (reserved word)
54
+ const needsCodingKey = swiftName !== key || swiftName.startsWith("`");
55
+ propInfos.push({ jsonKey: key, swiftName, needsCodingKey });
56
+ }
57
+ // CodingKeys block under codable when any prop needs mapping.
58
+ // Swift requires ALL properties be listed when CodingKeys is present.
59
+ if (c.isCodable && propInfos.some((p) => p.needsCodingKey)) {
60
+ const cases = propInfos.map(({ jsonKey, swiftName }) => {
61
+ return ` case ${swiftName} = "${jsonKey}"`;
62
+ });
63
+ lines.push("");
64
+ lines.push(" enum CodingKeys: String, CodingKey {");
65
+ lines.push(...cases);
66
+ lines.push(" }");
67
+ }
68
+ return `{\n${lines.join("\n")}\n}`;
69
+ }
70
+ //# sourceMappingURL=structEmitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structEmitter.js","sourceRoot":"","sources":["../../src/swift/structEmitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { GenerateTypeUtils } from "../converter/BaseConverter.js";
2
+ import { IRNode } from "../types.js";
3
+ import type { SwiftConverterContext } from "./SwiftConverter.js";
4
+ export declare const PRIMITIVES: Record<string, string>;
5
+ export declare const FORMAT_MAP: Record<string, {
6
+ type: string;
7
+ needsFoundation: boolean;
8
+ doc?: string;
9
+ }>;
10
+ export declare const STRING_DOC_FORMATS: Set<string>;
11
+ /**
12
+ * Maps an IRNode to its Swift type expression. Handles primitives, formatted
13
+ * strings (with `Foundation` import and doc-comment tracking), arrays, tuples
14
+ * (homogeneous → array, heterogeneous → Swift tuple under `serializer: 'none'`),
15
+ * referenced object types, string enums, literals, and unions (T | null
16
+ * unwrapping, discriminated-enum dispatch, unsupported-union policy).
17
+ */
18
+ export declare function generateSwiftType(c: SwiftConverterContext, ir: IRNode, utils: GenerateTypeUtils): string;