@kizunajs/swift 2.0.0-beta.1 → 2.0.0-beta.11

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/README.md CHANGED
@@ -10,8 +10,24 @@ pnpm add -D @kizunajs/swift
10
10
 
11
11
  ## Usage
12
12
 
13
+ Name the client in your config, and `kizuna generate` writes it with the rest:
14
+
15
+ ```ts
16
+ import { swiftClient } from '@kizunajs/swift';
17
+
18
+ export default defineConfig({
19
+ routes,
20
+ clients: [
21
+ swiftClient({
22
+ output: '../ios/MyApp/Generated/APIClient.swift',
23
+ namespace: 'API',
24
+ }),
25
+ ],
26
+ });
27
+ ```
28
+
13
29
  ```sh
14
- kizuna-swift generate --config kizuna.config.ts --output ios/MyApp/Generated/APIClient.swift --namespace-name API
30
+ kizuna generate
15
31
  ```
16
32
 
17
33
  ## Documentation
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_generator = require("./generator-v_aUFbbV.cjs");
2
+ const require_generator = require("./generator-BmO3raeP.cjs");
3
3
  let node_fs = require("node:fs");
4
4
  let node_path = require("node:path");
5
5
  let node_util = require("node:util");
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as generateSwiftClient } from "./generator-D2AtmA6u.mjs";
2
+ import { t as generateSwiftClient } from "./generator-CqKvXynF.mjs";
3
3
  import { mkdirSync, writeFileSync } from "node:fs";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { parseArgs } from "node:util";
@@ -100,8 +100,7 @@ const propertyName = (key, camelCase) => {
100
100
  if (!camel) return "field";
101
101
  return /^[0-9]/.test(camel) ? `_${camel}` : camel;
102
102
  };
103
- const objectFields = (schema, registry, hint) => {
104
- const shape = (0, kizunajs_generator.readObjectShape)(schema) ?? {};
103
+ const objectFields = (schema, registry, hint, shape = (0, kizunajs_generator.readObjectShape)(schema) ?? {}) => {
105
104
  const fields = [];
106
105
  const seen = /* @__PURE__ */ new Map();
107
106
  for (const [key, value] of Object.entries(shape)) {
@@ -199,8 +198,8 @@ const mapType = (schema, registry, hint) => {
199
198
  optional: false
200
199
  };
201
200
  }
202
- const { inner, optional } = (0, kizunajs_generator.unwrapOptionalWrappers)(schema);
203
- if (optional) {
201
+ const { inner, optional, nullable } = (0, kizunajs_generator.unwrapOptionalWrappers)(schema);
202
+ if (optional || nullable) {
204
203
  const innerResult = mapType(inner, registry, hint);
205
204
  return {
206
205
  expression: innerResult.expression.endsWith("?") ? innerResult.expression : `${innerResult.expression}?`,
@@ -253,8 +252,9 @@ const mapType = (schema, registry, hint) => {
253
252
  optional: false
254
253
  };
255
254
  }
255
+ const elementType = mapType(element, registry, `${hint}Item`).expression.replace(/\?$/, "");
256
256
  return {
257
- expression: `[${mapType(element, registry, `${hint}Item`).expression.replace(/\?$/, "")}]`,
257
+ expression: `[${(0, kizunajs_generator.unwrapOptionalWrappers)(element).nullable ? `${elementType}?` : elementType}]`,
258
258
  optional: false
259
259
  };
260
260
  }
@@ -556,7 +556,7 @@ const buildRouteMethod = (routeKey, route, registry, deprecated, deprecationMess
556
556
  stream
557
557
  };
558
558
  };
559
- const swiftGenerator = (0, kizunajs_generator.createGenerator)((options, _api) => {
559
+ const swiftRoutesWalk = (options) => {
560
560
  const flatMethods = [];
561
561
  const groupMap = /* @__PURE__ */ new Map();
562
562
  return {
@@ -588,7 +588,7 @@ const swiftGenerator = (0, kizunajs_generator.createGenerator)((options, _api) =
588
588
  };
589
589
  }
590
590
  };
591
- });
591
+ };
592
592
  const SWIFT_KEYWORDS = new Set([
593
593
  "associatedtype",
594
594
  "class",
@@ -955,13 +955,33 @@ const SWIFT_PRIMITIVE_TYPES = new Set([
955
955
  "Void",
956
956
  "Foundation.Data"
957
957
  ]);
958
+ /**
959
+ * Where a dictionary's key ends and its value begins, or -1 for an array.
960
+ */
961
+ const dictionarySeparator = (inner) => {
962
+ let depth = 0;
963
+ for (let index = 0; index < inner.length; index += 1) {
964
+ const character = inner[index];
965
+ if (character === "[") depth += 1;
966
+ else if (character === "]") depth -= 1;
967
+ else if (character === ":" && depth === 0) return index;
968
+ }
969
+ return -1;
970
+ };
958
971
  const resolveType = (typeName, currentOperation, context, scope = "actor") => {
959
972
  const { operationTypeMap, namespaceName, clientName, fileLevelTypeNames } = context;
960
973
  const optional = typeName.endsWith("?");
961
974
  const base = optional ? typeName.slice(0, -1) : typeName;
962
975
  if (SWIFT_PRIMITIVE_TYPES.has(base)) return typeName;
963
976
  if (base.startsWith("[") && base.endsWith("]")) {
964
- const resolved = resolveType(base.slice(1, -1), currentOperation, context, scope);
977
+ const inner = base.slice(1, -1);
978
+ const separator = dictionarySeparator(inner);
979
+ if (separator !== -1) {
980
+ const key = resolveType(inner.slice(0, separator).trim(), currentOperation, context, scope);
981
+ const value = resolveType(inner.slice(separator + 1).trim(), currentOperation, context, scope);
982
+ return optional ? `[${key}: ${value}]?` : `[${key}: ${value}]`;
983
+ }
984
+ const resolved = resolveType(inner, currentOperation, context, scope);
965
985
  return optional ? `[${resolved}]?` : `[${resolved}]`;
966
986
  }
967
987
  if (base === "MultipartFile" || base === "ValidationError" || base === "ValidationIssue") {
@@ -1038,6 +1058,8 @@ const emitToolTracking = (writer, method) => {
1038
1058
  writer.line("/// How far along the call is.");
1039
1059
  writer.block("public enum State: Sendable, Equatable", () => {
1040
1060
  writer.line("case running");
1061
+ writer.line("/// The call waits for the person to approve it.");
1062
+ writer.line("case needsApproval");
1041
1063
  writer.line("case done");
1042
1064
  writer.line("case failed");
1043
1065
  });
@@ -1070,6 +1092,9 @@ const emitToolTracking = (writer, method) => {
1070
1092
  writer.line("case .tool_call(let payload):");
1071
1093
  writer.line(" var tracked = at(payload.id, payload.name)");
1072
1094
  writer.line(" tracked.call = payload");
1095
+ writer.line(" if payload.needsApproval == true, tracked.state == .running {");
1096
+ writer.line(" tracked.state = .needsApproval");
1097
+ writer.line(" }");
1073
1098
  writer.line(" calls[payload.id] = tracked");
1074
1099
  }
1075
1100
  if (names.has("tool_result")) {
@@ -1971,18 +1996,8 @@ const emitClient = (writer, config, partition, context, typesByOperation) => {
1971
1996
  }
1972
1997
  });
1973
1998
  };
1974
- /**
1975
- * Generate a Swift API client from a kizuna config.
1976
- *
1977
- * - `namespaceName`: the actor class. Defaults to `APIClient`.
1978
- */
1979
- const generateSwiftClient = (api, options) => {
1980
- const { namespaceName, camelCaseProperties = false, unknownEnumCase = false } = options;
1981
- const registry = new TypeRegistry(camelCaseProperties, unknownEnumCase);
1982
- const partition = swiftGenerator(api, {
1983
- namespaceName,
1984
- registry
1985
- });
1999
+ const renderSwiftClient = (api, partition, registry, options) => {
2000
+ const { namespaceName } = options;
1986
2001
  const allMethods = [...partition.flatMethods, ...partition.groups.flatMap((group) => group.methods)];
1987
2002
  const operationTypeMap = buildOperationTypeMap(allMethods, registry);
1988
2003
  const clientName = `${namespaceName}Client`;
@@ -2059,6 +2074,26 @@ const generateSwiftClient = (api, options) => {
2059
2074
  for (const warning of registry.warnings()) process.stderr.write(`[kizuna/swift] AnyCodable fallback at ${warning}\n`);
2060
2075
  return writer.toString();
2061
2076
  };
2077
+ /**
2078
+ * The Swift client's walk: the routes into a partition, then the file.
2079
+ */
2080
+ const swiftClientWalk = (api, options) => {
2081
+ const registry = new TypeRegistry(options.camelCaseProperties ?? false, options.unknownEnumCase ?? false);
2082
+ const routes = swiftRoutesWalk({
2083
+ namespaceName: options.namespaceName,
2084
+ registry
2085
+ });
2086
+ return {
2087
+ processRoute: routes.processRoute,
2088
+ finalize: () => renderSwiftClient(api, routes.finalize(), registry, options)
2089
+ };
2090
+ };
2091
+ /**
2092
+ * Generate a Swift API client from a kizuna config.
2093
+ *
2094
+ * - `namespaceName`: the actor class. Defaults to `APIClient`.
2095
+ */
2096
+ const generateSwiftClient = (api, options) => (0, kizunajs_generator.walkApi)(api, swiftClientWalk(api, options), { skipHidden: true });
2062
2097
  //#endregion
2063
2098
  Object.defineProperty(exports, "generateSwiftClient", {
2064
2099
  enumerable: true,
@@ -2066,3 +2101,9 @@ Object.defineProperty(exports, "generateSwiftClient", {
2066
2101
  return generateSwiftClient;
2067
2102
  }
2068
2103
  });
2104
+ Object.defineProperty(exports, "swiftClientWalk", {
2105
+ enumerable: true,
2106
+ get: function() {
2107
+ return swiftClientWalk;
2108
+ }
2109
+ });
@@ -1,4 +1,4 @@
1
- import { createGenerator, isBinarySchema, isDiscriminatedUnionSchema, isFileSchema, isHintPrefix, isIntegerSchema, isJsonMediaType, isNamedStream, isObjectSchema, isStreamResponse, isSuccessStatus, isVoidSchema, localTypeName, mergeHeaderFields, parsePath, readDef, readDefType, readDeprecation, readDiscriminatedUnion, readDiscriminatorStringLiteral, readMetaDescription, readMetaId, readObjectShape, resolveResponseBody, resolveResponseContentType, resolveResponseHeaders, routeStreams, sanitizeFieldName, sanitizeIdentifier, shortTypeName, soleStreamResponse, statusToCamelCase, streamMode, toCamelCase, toPascalCase, unwrapOptionalWrappers } from "kizunajs/generator";
1
+ import { isBinarySchema, isDiscriminatedUnionSchema, isFileSchema, isHintPrefix, isIntegerSchema, isJsonMediaType, isNamedStream, isObjectSchema, isStreamResponse, isSuccessStatus, isVoidSchema, localTypeName, mergeHeaderFields, parsePath, readDef, readDefType, readDeprecation, readDiscriminatedUnion, readDiscriminatorStringLiteral, readMetaDescription, readMetaId, readObjectShape, resolveResponseBody, resolveResponseContentType, resolveResponseHeaders, routeStreams, sanitizeFieldName, sanitizeIdentifier, shortTypeName, soleStreamResponse, statusToCamelCase, streamMode, toCamelCase, toPascalCase, unwrapOptionalWrappers, walkApi } from "kizunajs/generator";
2
2
  //#region src/emit.ts
3
3
  var SwiftWriter = class {
4
4
  lines = [];
@@ -100,8 +100,7 @@ const propertyName = (key, camelCase) => {
100
100
  if (!camel) return "field";
101
101
  return /^[0-9]/.test(camel) ? `_${camel}` : camel;
102
102
  };
103
- const objectFields = (schema, registry, hint) => {
104
- const shape = readObjectShape(schema) ?? {};
103
+ const objectFields = (schema, registry, hint, shape = readObjectShape(schema) ?? {}) => {
105
104
  const fields = [];
106
105
  const seen = /* @__PURE__ */ new Map();
107
106
  for (const [key, value] of Object.entries(shape)) {
@@ -199,8 +198,8 @@ const mapType = (schema, registry, hint) => {
199
198
  optional: false
200
199
  };
201
200
  }
202
- const { inner, optional } = unwrapOptionalWrappers(schema);
203
- if (optional) {
201
+ const { inner, optional, nullable } = unwrapOptionalWrappers(schema);
202
+ if (optional || nullable) {
204
203
  const innerResult = mapType(inner, registry, hint);
205
204
  return {
206
205
  expression: innerResult.expression.endsWith("?") ? innerResult.expression : `${innerResult.expression}?`,
@@ -253,8 +252,9 @@ const mapType = (schema, registry, hint) => {
253
252
  optional: false
254
253
  };
255
254
  }
255
+ const elementType = mapType(element, registry, `${hint}Item`).expression.replace(/\?$/, "");
256
256
  return {
257
- expression: `[${mapType(element, registry, `${hint}Item`).expression.replace(/\?$/, "")}]`,
257
+ expression: `[${unwrapOptionalWrappers(element).nullable ? `${elementType}?` : elementType}]`,
258
258
  optional: false
259
259
  };
260
260
  }
@@ -556,7 +556,7 @@ const buildRouteMethod = (routeKey, route, registry, deprecated, deprecationMess
556
556
  stream
557
557
  };
558
558
  };
559
- const swiftGenerator = createGenerator((options, _api) => {
559
+ const swiftRoutesWalk = (options) => {
560
560
  const flatMethods = [];
561
561
  const groupMap = /* @__PURE__ */ new Map();
562
562
  return {
@@ -588,7 +588,7 @@ const swiftGenerator = createGenerator((options, _api) => {
588
588
  };
589
589
  }
590
590
  };
591
- });
591
+ };
592
592
  const SWIFT_KEYWORDS = new Set([
593
593
  "associatedtype",
594
594
  "class",
@@ -955,13 +955,33 @@ const SWIFT_PRIMITIVE_TYPES = new Set([
955
955
  "Void",
956
956
  "Foundation.Data"
957
957
  ]);
958
+ /**
959
+ * Where a dictionary's key ends and its value begins, or -1 for an array.
960
+ */
961
+ const dictionarySeparator = (inner) => {
962
+ let depth = 0;
963
+ for (let index = 0; index < inner.length; index += 1) {
964
+ const character = inner[index];
965
+ if (character === "[") depth += 1;
966
+ else if (character === "]") depth -= 1;
967
+ else if (character === ":" && depth === 0) return index;
968
+ }
969
+ return -1;
970
+ };
958
971
  const resolveType = (typeName, currentOperation, context, scope = "actor") => {
959
972
  const { operationTypeMap, namespaceName, clientName, fileLevelTypeNames } = context;
960
973
  const optional = typeName.endsWith("?");
961
974
  const base = optional ? typeName.slice(0, -1) : typeName;
962
975
  if (SWIFT_PRIMITIVE_TYPES.has(base)) return typeName;
963
976
  if (base.startsWith("[") && base.endsWith("]")) {
964
- const resolved = resolveType(base.slice(1, -1), currentOperation, context, scope);
977
+ const inner = base.slice(1, -1);
978
+ const separator = dictionarySeparator(inner);
979
+ if (separator !== -1) {
980
+ const key = resolveType(inner.slice(0, separator).trim(), currentOperation, context, scope);
981
+ const value = resolveType(inner.slice(separator + 1).trim(), currentOperation, context, scope);
982
+ return optional ? `[${key}: ${value}]?` : `[${key}: ${value}]`;
983
+ }
984
+ const resolved = resolveType(inner, currentOperation, context, scope);
965
985
  return optional ? `[${resolved}]?` : `[${resolved}]`;
966
986
  }
967
987
  if (base === "MultipartFile" || base === "ValidationError" || base === "ValidationIssue") {
@@ -1038,6 +1058,8 @@ const emitToolTracking = (writer, method) => {
1038
1058
  writer.line("/// How far along the call is.");
1039
1059
  writer.block("public enum State: Sendable, Equatable", () => {
1040
1060
  writer.line("case running");
1061
+ writer.line("/// The call waits for the person to approve it.");
1062
+ writer.line("case needsApproval");
1041
1063
  writer.line("case done");
1042
1064
  writer.line("case failed");
1043
1065
  });
@@ -1070,6 +1092,9 @@ const emitToolTracking = (writer, method) => {
1070
1092
  writer.line("case .tool_call(let payload):");
1071
1093
  writer.line(" var tracked = at(payload.id, payload.name)");
1072
1094
  writer.line(" tracked.call = payload");
1095
+ writer.line(" if payload.needsApproval == true, tracked.state == .running {");
1096
+ writer.line(" tracked.state = .needsApproval");
1097
+ writer.line(" }");
1073
1098
  writer.line(" calls[payload.id] = tracked");
1074
1099
  }
1075
1100
  if (names.has("tool_result")) {
@@ -1971,18 +1996,8 @@ const emitClient = (writer, config, partition, context, typesByOperation) => {
1971
1996
  }
1972
1997
  });
1973
1998
  };
1974
- /**
1975
- * Generate a Swift API client from a kizuna config.
1976
- *
1977
- * - `namespaceName`: the actor class. Defaults to `APIClient`.
1978
- */
1979
- const generateSwiftClient = (api, options) => {
1980
- const { namespaceName, camelCaseProperties = false, unknownEnumCase = false } = options;
1981
- const registry = new TypeRegistry(camelCaseProperties, unknownEnumCase);
1982
- const partition = swiftGenerator(api, {
1983
- namespaceName,
1984
- registry
1985
- });
1999
+ const renderSwiftClient = (api, partition, registry, options) => {
2000
+ const { namespaceName } = options;
1986
2001
  const allMethods = [...partition.flatMethods, ...partition.groups.flatMap((group) => group.methods)];
1987
2002
  const operationTypeMap = buildOperationTypeMap(allMethods, registry);
1988
2003
  const clientName = `${namespaceName}Client`;
@@ -2059,5 +2074,25 @@ const generateSwiftClient = (api, options) => {
2059
2074
  for (const warning of registry.warnings()) process.stderr.write(`[kizuna/swift] AnyCodable fallback at ${warning}\n`);
2060
2075
  return writer.toString();
2061
2076
  };
2077
+ /**
2078
+ * The Swift client's walk: the routes into a partition, then the file.
2079
+ */
2080
+ const swiftClientWalk = (api, options) => {
2081
+ const registry = new TypeRegistry(options.camelCaseProperties ?? false, options.unknownEnumCase ?? false);
2082
+ const routes = swiftRoutesWalk({
2083
+ namespaceName: options.namespaceName,
2084
+ registry
2085
+ });
2086
+ return {
2087
+ processRoute: routes.processRoute,
2088
+ finalize: () => renderSwiftClient(api, routes.finalize(), registry, options)
2089
+ };
2090
+ };
2091
+ /**
2092
+ * Generate a Swift API client from a kizuna config.
2093
+ *
2094
+ * - `namespaceName`: the actor class. Defaults to `APIClient`.
2095
+ */
2096
+ const generateSwiftClient = (api, options) => walkApi(api, swiftClientWalk(api, options), { skipHidden: true });
2062
2097
  //#endregion
2063
- export { generateSwiftClient as t };
2098
+ export { swiftClientWalk as n, generateSwiftClient as t };
package/dist/index.cjs CHANGED
@@ -1,17 +1,44 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_generator = require("./generator-v_aUFbbV.cjs");
2
+ const require_generator = require("./generator-BmO3raeP.cjs");
3
+ let kizunajs_generator = require("kizunajs/generator");
4
+ let zod = require("zod");
3
5
  //#region src/client-target.ts
6
+ const SwiftClientOptionsSchema = zod.z.object({
7
+ /**
8
+ * Name of the generated namespace enum.
9
+ *
10
+ * @default 'API'
11
+ */
12
+ namespace: zod.z.string().default("API"),
13
+ /**
14
+ * Convert wire field names to camelCase properties, mapping the wire name
15
+ * back via `CodingKeys`.
16
+ *
17
+ * @default false
18
+ */
19
+ camelCaseProperties: zod.z.boolean().optional(),
20
+ /**
21
+ * Give every enum an `unknown` case, so a value the client has not been
22
+ * generated for decodes instead of throwing.
23
+ *
24
+ * @default false
25
+ */
26
+ unknownEnumCase: zod.z.boolean().optional()
27
+ });
4
28
  /**
5
- * A Swift client target for `kizuna.config.ts`.
29
+ * A Swift client for `kizuna.config.ts`.
6
30
  *
7
31
  * @example
8
- * swiftClient({ output: './Sources/APIClient/APIClient.swift', namespace: 'API' });
32
+ * swiftClient({
33
+ * output: './Sources/APIClient/APIClient.swift',
34
+ * namespace: 'API',
35
+ * });
9
36
  */
10
- const swiftClient = (options) => ({
11
- kind: "swift",
12
- output: options.output,
13
- generate: (contract) => require_generator.generateSwiftClient(contract, {
14
- namespaceName: options.namespace ?? "API",
37
+ const swiftClient = (0, kizunajs_generator.defineClient)({
38
+ target: "swift",
39
+ options: SwiftClientOptionsSchema,
40
+ generate: ({ options, api }) => require_generator.swiftClientWalk(api, {
41
+ namespaceName: options.namespace,
15
42
  camelCaseProperties: options.camelCaseProperties,
16
43
  unknownEnumCase: options.unknownEnumCase
17
44
  })
package/dist/index.d.cts CHANGED
@@ -1,4 +1,7 @@
1
- import { ApiDefinition, ClientTarget } from "kizunajs";
1
+ import { GeneratedFileOptions } from "kizunajs/generator";
2
+ import * as _$kizunajs from "kizunajs";
3
+ import { ApiDefinition } from "kizunajs";
4
+ import { z } from "zod";
2
5
 
3
6
  //#region src/generator.d.ts
4
7
  interface SwiftConfig {
@@ -29,41 +32,28 @@ interface SwiftConfig {
29
32
  declare const generateSwiftClient: (api: ApiDefinition, options: SwiftConfig) => string;
30
33
  //#endregion
31
34
  //#region src/client-target.d.ts
35
+ declare const SwiftClientOptionsSchema: z.ZodObject<{
36
+ namespace: z.ZodDefault<z.ZodString>;
37
+ camelCaseProperties: z.ZodOptional<z.ZodBoolean>;
38
+ unknownEnumCase: z.ZodOptional<z.ZodBoolean>;
39
+ }, z.core.$strip>;
32
40
  /**
33
41
  * Where a generated Swift client is written, and what it is called there.
34
42
  */
35
- interface SwiftClientOptions {
36
- /**
37
- * Path the generated file is written to.
38
- */
39
- output: string;
40
- /**
41
- * Name of the generated namespace enum.
42
- *
43
- * @default 'API'
44
- */
45
- namespace?: string;
46
- /**
47
- * Convert wire field names to camelCase properties, mapping the wire name
48
- * back via `CodingKeys`.
49
- *
50
- * @default false
51
- */
52
- camelCaseProperties?: boolean;
53
- /**
54
- * Give every enum an `unknown` case, so a value the client has not been
55
- * generated for decodes instead of throwing.
56
- *
57
- * @default false
58
- */
59
- unknownEnumCase?: boolean;
60
- }
43
+ type SwiftClientOptions = z.input<typeof SwiftClientOptionsSchema> & GeneratedFileOptions;
61
44
  /**
62
- * A Swift client target for `kizuna.config.ts`.
45
+ * A Swift client for `kizuna.config.ts`.
63
46
  *
64
47
  * @example
65
- * swiftClient({ output: './Sources/APIClient/APIClient.swift', namespace: 'API' });
48
+ * swiftClient({
49
+ * output: './Sources/APIClient/APIClient.swift',
50
+ * namespace: 'API',
51
+ * });
66
52
  */
67
- declare const swiftClient: (options: SwiftClientOptions) => ClientTarget;
53
+ declare const swiftClient: (options: {
54
+ namespace?: string | undefined;
55
+ camelCaseProperties?: boolean | undefined;
56
+ unknownEnumCase?: boolean | undefined;
57
+ } & GeneratedFileOptions) => _$kizunajs.GeneratedFile;
68
58
  //#endregion
69
59
  export { type SwiftClientOptions, type SwiftConfig, generateSwiftClient, swiftClient };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,7 @@
1
- import { ApiDefinition, ClientTarget } from "kizunajs";
1
+ import { GeneratedFileOptions } from "kizunajs/generator";
2
+ import { z } from "zod";
3
+ import * as _$kizunajs from "kizunajs";
4
+ import { ApiDefinition } from "kizunajs";
2
5
 
3
6
  //#region src/generator.d.ts
4
7
  interface SwiftConfig {
@@ -29,41 +32,28 @@ interface SwiftConfig {
29
32
  declare const generateSwiftClient: (api: ApiDefinition, options: SwiftConfig) => string;
30
33
  //#endregion
31
34
  //#region src/client-target.d.ts
35
+ declare const SwiftClientOptionsSchema: z.ZodObject<{
36
+ namespace: z.ZodDefault<z.ZodString>;
37
+ camelCaseProperties: z.ZodOptional<z.ZodBoolean>;
38
+ unknownEnumCase: z.ZodOptional<z.ZodBoolean>;
39
+ }, z.core.$strip>;
32
40
  /**
33
41
  * Where a generated Swift client is written, and what it is called there.
34
42
  */
35
- interface SwiftClientOptions {
36
- /**
37
- * Path the generated file is written to.
38
- */
39
- output: string;
40
- /**
41
- * Name of the generated namespace enum.
42
- *
43
- * @default 'API'
44
- */
45
- namespace?: string;
46
- /**
47
- * Convert wire field names to camelCase properties, mapping the wire name
48
- * back via `CodingKeys`.
49
- *
50
- * @default false
51
- */
52
- camelCaseProperties?: boolean;
53
- /**
54
- * Give every enum an `unknown` case, so a value the client has not been
55
- * generated for decodes instead of throwing.
56
- *
57
- * @default false
58
- */
59
- unknownEnumCase?: boolean;
60
- }
43
+ type SwiftClientOptions = z.input<typeof SwiftClientOptionsSchema> & GeneratedFileOptions;
61
44
  /**
62
- * A Swift client target for `kizuna.config.ts`.
45
+ * A Swift client for `kizuna.config.ts`.
63
46
  *
64
47
  * @example
65
- * swiftClient({ output: './Sources/APIClient/APIClient.swift', namespace: 'API' });
48
+ * swiftClient({
49
+ * output: './Sources/APIClient/APIClient.swift',
50
+ * namespace: 'API',
51
+ * });
66
52
  */
67
- declare const swiftClient: (options: SwiftClientOptions) => ClientTarget;
53
+ declare const swiftClient: (options: {
54
+ namespace?: string | undefined;
55
+ camelCaseProperties?: boolean | undefined;
56
+ unknownEnumCase?: boolean | undefined;
57
+ } & GeneratedFileOptions) => _$kizunajs.GeneratedFile;
68
58
  //#endregion
69
59
  export { type SwiftClientOptions, type SwiftConfig, generateSwiftClient, swiftClient };
package/dist/index.mjs CHANGED
@@ -1,16 +1,41 @@
1
- import { t as generateSwiftClient } from "./generator-D2AtmA6u.mjs";
2
- //#region src/client-target.ts
1
+ import { n as swiftClientWalk, t as generateSwiftClient } from "./generator-CqKvXynF.mjs";
2
+ import { defineClient } from "kizunajs/generator";
3
+ import { z } from "zod";
3
4
  /**
4
- * A Swift client target for `kizuna.config.ts`.
5
+ * A Swift client for `kizuna.config.ts`.
5
6
  *
6
7
  * @example
7
- * swiftClient({ output: './Sources/APIClient/APIClient.swift', namespace: 'API' });
8
+ * swiftClient({
9
+ * output: './Sources/APIClient/APIClient.swift',
10
+ * namespace: 'API',
11
+ * });
8
12
  */
9
- const swiftClient = (options) => ({
10
- kind: "swift",
11
- output: options.output,
12
- generate: (contract) => generateSwiftClient(contract, {
13
- namespaceName: options.namespace ?? "API",
13
+ const swiftClient = defineClient({
14
+ target: "swift",
15
+ options: z.object({
16
+ /**
17
+ * Name of the generated namespace enum.
18
+ *
19
+ * @default 'API'
20
+ */
21
+ namespace: z.string().default("API"),
22
+ /**
23
+ * Convert wire field names to camelCase properties, mapping the wire name
24
+ * back via `CodingKeys`.
25
+ *
26
+ * @default false
27
+ */
28
+ camelCaseProperties: z.boolean().optional(),
29
+ /**
30
+ * Give every enum an `unknown` case, so a value the client has not been
31
+ * generated for decodes instead of throwing.
32
+ *
33
+ * @default false
34
+ */
35
+ unknownEnumCase: z.boolean().optional()
36
+ }),
37
+ generate: ({ options, api }) => swiftClientWalk(api, {
38
+ namespaceName: options.namespace,
14
39
  camelCaseProperties: options.camelCaseProperties,
15
40
  unknownEnumCase: options.unknownEnumCase
16
41
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kizunajs/swift",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0-beta.11",
4
4
  "description": "Swift client generation for Kizuna.js APIs",
5
5
  "keywords": [
6
6
  "kizunajs",
@@ -59,18 +59,18 @@
59
59
  "access": "public"
60
60
  },
61
61
  "dependencies": {
62
- "@kizunajs/cli": "2.0.0-beta.1"
62
+ "@kizunajs/cli": "2.0.0-beta.11"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "zod": "^4.0.0",
66
- "kizunajs": "2.0.0-beta.1"
66
+ "kizunajs": "2.0.0-beta.11"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/node": "^24",
70
70
  "tsdown": "^0.21.0",
71
71
  "typescript": "^6.0.3",
72
72
  "zod": "^4.0.0",
73
- "kizunajs": "2.0.0-beta.1"
73
+ "kizunajs": "2.0.0-beta.11"
74
74
  },
75
75
  "scripts": {
76
76
  "build": "tsdown src/index.ts src/cli.ts --format esm,cjs --dts --clean --external kizunajs --external @kizunajs/cli --external zod",