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

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-B9dFb9Mu.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-DOSsavcH.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
  }
@@ -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")) {
@@ -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
  }
@@ -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")) {
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_generator = require("./generator-v_aUFbbV.cjs");
2
+ const require_generator = require("./generator-B9dFb9Mu.cjs");
3
3
  //#region src/client-target.ts
4
4
  /**
5
5
  * A Swift client target for `kizuna.config.ts`.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as generateSwiftClient } from "./generator-D2AtmA6u.mjs";
1
+ import { t as generateSwiftClient } from "./generator-DOSsavcH.mjs";
2
2
  //#region src/client-target.ts
3
3
  /**
4
4
  * A Swift client target for `kizuna.config.ts`.
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.10",
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.10"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "zod": "^4.0.0",
66
- "kizunajs": "2.0.0-beta.1"
66
+ "kizunajs": "2.0.0-beta.10"
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.10"
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",