@tailor-platform/sdk 1.30.0 → 1.32.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 (46) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +3 -1
  3. package/dist/{application-Bf8SUAtR.mjs → application-B8vok3w2.mjs} +257 -42
  4. package/dist/application-B8vok3w2.mjs.map +1 -0
  5. package/dist/{application-DAQVP9CS.mjs → application-DHifc-oA.mjs} +2 -2
  6. package/dist/cli/index.mjs +67 -70
  7. package/dist/cli/index.mjs.map +1 -1
  8. package/dist/cli/lib.d.mts +8 -8
  9. package/dist/cli/lib.mjs +8 -6
  10. package/dist/cli/lib.mjs.map +1 -1
  11. package/dist/client-B0wrLUVK.mjs +6 -0
  12. package/dist/{client-CZmQBXAY.mjs → client-DfdgRZlQ.mjs} +25 -13
  13. package/dist/{client-CZmQBXAY.mjs.map → client-DfdgRZlQ.mjs.map} +1 -1
  14. package/dist/configure/index.d.mts +4 -4
  15. package/dist/configure/index.mjs +1 -1
  16. package/dist/{crash-report-CYrETw1c.mjs → crash-report-BMEhRxeg.mjs} +1 -1
  17. package/dist/{crash-report-DizNMVnm.mjs → crash-report-wNxS0IUJ.mjs} +2 -2
  18. package/dist/{crash-report-DizNMVnm.mjs.map → crash-report-wNxS0IUJ.mjs.map} +1 -1
  19. package/dist/{env-DiWYe80_.d.mts → env-BgdHfWDn.d.mts} +2 -2
  20. package/dist/{index-BU7Cd5I4.d.mts → index-BAud4CE7.d.mts} +15 -15
  21. package/dist/{index-HvMUWjvV.d.mts → index-CdDzh-T2.d.mts} +2 -2
  22. package/dist/{index-rH_De6hM.d.mts → index-CxgBnxKM.d.mts} +2 -2
  23. package/dist/{index-DCEMVfJA.d.mts → index-D4Y81vh1.d.mts} +2 -2
  24. package/dist/{index-2WQbf_LH.d.mts → index-FZMBoUWm.d.mts} +2 -2
  25. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  26. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  27. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  28. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  29. package/dist/plugin/index.d.mts +2 -2
  30. package/dist/{plugin-C-UdAM8C.d.mts → plugin-DyVYXZWz.d.mts} +7 -7
  31. package/dist/{query-C3oQTLvb.mjs → runtime-DbX_UxlC.mjs} +67 -39
  32. package/dist/runtime-DbX_UxlC.mjs.map +1 -0
  33. package/dist/{schema-BePzTFBV.mjs → schema-CNWt2FKQ.mjs} +3 -14
  34. package/dist/schema-CNWt2FKQ.mjs.map +1 -0
  35. package/dist/utils/test/index.d.mts +8 -3
  36. package/dist/utils/test/index.mjs +15 -1
  37. package/dist/utils/test/index.mjs.map +1 -1
  38. package/dist/{workflow.generated-C5wMcCjB.d.mts → workflow.generated-DMQ-cjyT.d.mts} +2 -2
  39. package/docs/quickstart.md +12 -0
  40. package/docs/services/resolver.md +72 -0
  41. package/docs/services/tailordb.md +78 -6
  42. package/package.json +15 -12
  43. package/dist/application-Bf8SUAtR.mjs.map +0 -1
  44. package/dist/client-CW4Oh3iz.mjs +0 -6
  45. package/dist/query-C3oQTLvb.mjs.map +0 -1
  46. package/dist/schema-BePzTFBV.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # @tailor-platform/sdk
2
2
 
3
+ ## 1.32.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#805](https://github.com/tailor-platform/sdk/pull/805) [`d283a78`](https://github.com/tailor-platform/sdk/commit/d283a7802e2a0aaa6fc31c4ac2c7c3d4dc9654e6) Thanks [@toiroakr](https://github.com/toiroakr)! - Use TailorErrors for resolver input validation errors instead of generic Error, enabling the PF runtime to expand validation issues into individual GraphQL errors with field-level paths.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#813](https://github.com/tailor-platform/sdk/pull/813) [`34b525f`](https://github.com/tailor-platform/sdk/commit/34b525f69b1929394a2b246e4252308710032ee7) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @inquirer/core to v11.1.7
12
+
13
+ - [#828](https://github.com/tailor-platform/sdk/pull/828) [`d42bd97`](https://github.com/tailor-platform/sdk/commit/d42bd979085c800e3a46d73e76cc7c7e8251ecbb) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency knip to v6
14
+
15
+ ## 1.31.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [#793](https://github.com/tailor-platform/sdk/pull/793) [`517ed78`](https://github.com/tailor-platform/sdk/commit/517ed782e1c4705b981822422cdd97541bddeeef) Thanks [@dqn](https://github.com/dqn)! - Add Bun runtime support for CLI and expand CI test matrix
20
+
21
+ - Detect Bun/Deno runtimes and skip tsx registration for native TypeScript execution
22
+ - Use dynamic import for connect-node transport to support Bun runtime
23
+ - Expand CI smoke tests across OS, Node version, package manager, and runtime combinations
24
+
25
+ - [#746](https://github.com/tailor-platform/sdk/pull/746) [`b9113a0`](https://github.com/tailor-platform/sdk/commit/b9113a08698edcd03deae0bf7354701a59f4d76d) Thanks [@toiroakr](https://github.com/toiroakr)! - Add opt-in secure token storage via OS keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service). Set `TAILOR_USE_KEYRING=1` to enable. Default behavior remains unchanged (file-based V1 config) for backward compatibility with older SDK versions.
26
+
27
+ ### Patch Changes
28
+
29
+ - [#806](https://github.com/tailor-platform/sdk/pull/806) [`cfe2c4b`](https://github.com/tailor-platform/sdk/commit/cfe2c4b194acf8bae674e8c1030a40cf2cb29ba9) Thanks [@toiroakr](https://github.com/toiroakr)! - Add documentation for `typeName` on enum/object fields and `pickFields`/`omitFields` on TailorDBType
30
+
31
+ - [#807](https://github.com/tailor-platform/sdk/pull/807) [`13ad5cd`](https://github.com/tailor-platform/sdk/commit/13ad5cd4027c4fc5925a8934050b68d1a51cb41c) Thanks [@toiroakr](https://github.com/toiroakr)! - Remove unused `required` option from `FieldOptions` and dead `requiredExplicit` field from `FieldMetadata`
32
+
33
+ - [#744](https://github.com/tailor-platform/sdk/pull/744) [`5d2ab24`](https://github.com/tailor-platform/sdk/commit/5d2ab24393507b7333cfd3e4cdd2ec10e34abd44) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency @typescript/native-preview to v7.0.0-dev.20260320.1
34
+
35
+ - [#768](https://github.com/tailor-platform/sdk/pull/768) [`2d984a3`](https://github.com/tailor-platform/sdk/commit/2d984a3b798cd14bf9958eb89ad229a70b2c45c4) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @bufbuild/protobuf to v2.11.0
36
+
37
+ - [#774](https://github.com/tailor-platform/sdk/pull/774) [`a9160f4`](https://github.com/tailor-platform/sdk/commit/a9160f42dea8a8f62247e3bb4b2ffc307f50f33e) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @opentelemetry/exporter-trace-otlp-proto to v0.213.0
38
+
39
+ - [#777](https://github.com/tailor-platform/sdk/pull/777) [`cea90ef`](https://github.com/tailor-platform/sdk/commit/cea90ef1485fdcbc9e605cb34e48cdb55ef2a558) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency globals to v17.4.0
40
+
41
+ - [#783](https://github.com/tailor-platform/sdk/pull/783) [`858316f`](https://github.com/tailor-platform/sdk/commit/858316fa565031c77ea8e98890313c41d4c43d13) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency pkg-pr-new to v0.0.66
42
+
43
+ - [#785](https://github.com/tailor-platform/sdk/pull/785) [`8dcaac5`](https://github.com/tailor-platform/sdk/commit/8dcaac5420aec0cc7f193019cac80faaf0994c1b) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency ora to v9.3.0
44
+
45
+ - [#797](https://github.com/tailor-platform/sdk/pull/797) [`4863518`](https://github.com/tailor-platform/sdk/commit/4863518cb4b465aa8d8a794d3e333c8cf86da529) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency tsdown to v0.21.4
46
+
47
+ - [#798](https://github.com/tailor-platform/sdk/pull/798) [`e95f0a3`](https://github.com/tailor-platform/sdk/commit/e95f0a311732908191671942dab3ccd2be8319bb) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency typescript-eslint to v8.57.1
48
+
49
+ - [#801](https://github.com/tailor-platform/sdk/pull/801) [`030539d`](https://github.com/tailor-platform/sdk/commit/030539d0f568c5b5c0a4c7acafe303ea2d5a56dd) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): lock file maintenance
50
+
51
+ - [#802](https://github.com/tailor-platform/sdk/pull/802) [`27f2908`](https://github.com/tailor-platform/sdk/commit/27f2908536a540e3707af983c7fef49cb4a4dcc8) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update anthropics/claude-code-action action to v1.0.77
52
+
53
+ - [#810](https://github.com/tailor-platform/sdk/pull/810) [`c16d87c`](https://github.com/tailor-platform/sdk/commit/c16d87cc7d9ef210230cb3e366bd6569e8f646a7) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency @tailor-platform/function-types to v0.8.3
54
+
55
+ - [#811](https://github.com/tailor-platform/sdk/pull/811) [`5fc6e4b`](https://github.com/tailor-platform/sdk/commit/5fc6e4b32736828cea7453d0cc2b66dec9808946) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency aquaproj/aqua to v2.57.1
56
+
57
+ - [#812](https://github.com/tailor-platform/sdk/pull/812) [`1af673e`](https://github.com/tailor-platform/sdk/commit/1af673e978cd2642d6c9a8ef8c075dfc1098cb3c) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency turbo to v2.8.20
58
+
59
+ - [#815](https://github.com/tailor-platform/sdk/pull/815) [`d1b6d92`](https://github.com/tailor-platform/sdk/commit/d1b6d929f1317790b7fa4d7e2ea73580042c92f5) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @inquirer/prompts to v8.3.2
60
+
61
+ - [#816](https://github.com/tailor-platform/sdk/pull/816) [`dc3fc6e`](https://github.com/tailor-platform/sdk/commit/dc3fc6e99b11252232c9960cca705cd213cec11b) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency rolldown to v1.0.0-rc.10
62
+
63
+ - [#817](https://github.com/tailor-platform/sdk/pull/817) [`951ec13`](https://github.com/tailor-platform/sdk/commit/951ec13ea44ef3545a76e84e3e46779601ee5871) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency aquaproj/aqua-registry to v4.487.0
64
+
65
+ - [#818](https://github.com/tailor-platform/sdk/pull/818) [`25bbd17`](https://github.com/tailor-platform/sdk/commit/25bbd178609c7a102301c847c067483addcbf5df) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependency knip to v5.88.1
66
+
3
67
  ## 1.30.0
4
68
 
5
69
  ### Minor Changes
package/README.md CHANGED
@@ -30,6 +30,8 @@ npm install @tailor-platform/sdk
30
30
  yarn add @tailor-platform/sdk
31
31
  # OR
32
32
  pnpm add @tailor-platform/sdk
33
+ # OR
34
+ bun add @tailor-platform/sdk
33
35
  ```
34
36
 
35
37
  ## Quick Start
@@ -95,5 +97,5 @@ See [Create Tailor Platform SDK](https://github.com/tailor-platform/sdk/tree/mai
95
97
 
96
98
  ## Requirements
97
99
 
98
- - Node.js 22 or later
100
+ - Node.js 22 or later (or Bun)
99
101
  - A Tailor Platform account ([request access](https://www.tailor.tech/demo))
@@ -1,6 +1,7 @@
1
1
  import { n as isSdkBranded } from "./brand-GZnI4eYb.mjs";
2
2
  import { n as logger, r as styles } from "./logger-CqezTedh.mjs";
3
- import { c as initOAuth2Client } from "./client-CZmQBXAY.mjs";
3
+ import { l as initOAuth2Client } from "./client-DfdgRZlQ.mjs";
4
+ import { t as readPackageJson } from "./package-json-D3x2nBPB.mjs";
4
5
  import { n as seedPlugin, r as isPluginGeneratedType, t as SeedGeneratorID } from "./seed-CWkIDWMb.mjs";
5
6
  import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-D1nfn0qD.mjs";
6
7
  import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "./file-utils-Bctuzn3x.mjs";
@@ -18,6 +19,7 @@ import * as os from "node:os";
18
19
  import { parseTOML, parseYAML, stringifyYAML } from "confbox";
19
20
  import { findUpSync } from "find-up-simple";
20
21
  import ml from "multiline-ts";
22
+ import { lt } from "semver";
21
23
  import { xdgConfig } from "xdg-basedir";
22
24
  import * as rolldown from "rolldown";
23
25
  import * as fs from "node:fs/promises";
@@ -25,18 +27,112 @@ import { parseSync } from "oxc-parser";
25
27
  import * as inflection from "inflection";
26
28
  import * as globals from "globals";
27
29
 
30
+ //#region src/cli/shared/token-store.ts
31
+ const SERVICE_NAME = "tailor-platform-cli";
32
+ let entryClass;
33
+ async function getEntryClass() {
34
+ if (entryClass !== void 0) return entryClass;
35
+ try {
36
+ const mod = await import("@napi-rs/keyring");
37
+ const probe = new mod.Entry(SERVICE_NAME, "__probe__");
38
+ probe.setPassword("probe");
39
+ probe.deletePassword();
40
+ entryClass = mod.Entry;
41
+ } catch {
42
+ logger.warn("System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.");
43
+ entryClass = false;
44
+ }
45
+ return entryClass;
46
+ }
47
+ /**
48
+ * Check whether the OS keyring is available and functional.
49
+ * @returns true if keyring is available
50
+ */
51
+ async function isKeyringAvailable() {
52
+ return await getEntryClass() !== false;
53
+ }
54
+ /**
55
+ * Load tokens from the OS keyring for a given account.
56
+ * @param account - User identifier (e.g. email or client ID)
57
+ * @returns Token data or undefined if not found or keyring unavailable
58
+ */
59
+ async function loadKeyringTokens(account) {
60
+ const Entry = await getEntryClass();
61
+ if (!Entry) return void 0;
62
+ try {
63
+ const raw = new Entry(SERVICE_NAME, account).getPassword();
64
+ if (raw === null) return void 0;
65
+ return JSON.parse(raw);
66
+ } catch {
67
+ return;
68
+ }
69
+ }
70
+ /**
71
+ * Save tokens to the OS keyring for a given account.
72
+ * @param account - User identifier (e.g. email or client ID)
73
+ * @param tokens - Token data to store
74
+ */
75
+ async function saveKeyringTokens(account, tokens) {
76
+ const Entry = await getEntryClass();
77
+ if (!Entry) return;
78
+ new Entry(SERVICE_NAME, account).setPassword(JSON.stringify(tokens));
79
+ }
80
+ /**
81
+ * Delete tokens from the OS keyring for a given account.
82
+ * @param account - User identifier (e.g. email or client ID)
83
+ */
84
+ async function deleteKeyringTokens(account) {
85
+ const Entry = await getEntryClass();
86
+ if (!Entry) return;
87
+ try {
88
+ new Entry(SERVICE_NAME, account).deletePassword();
89
+ } catch {}
90
+ }
91
+
92
+ //#endregion
28
93
  //#region src/cli/shared/context.ts
29
- const pfConfigSchema = z.object({
94
+ const pfProfileSchema = z.object({
95
+ user: z.string(),
96
+ workspace_id: z.string()
97
+ });
98
+ const pfUserSchemaV1 = z.object({
99
+ access_token: z.string(),
100
+ refresh_token: z.string().optional(),
101
+ token_expires_at: z.string()
102
+ });
103
+ const pfUserKeyringSchema = z.object({
104
+ storage: z.literal("keyring"),
105
+ token_expires_at: z.string()
106
+ });
107
+ const pfUserFileSchema = z.object({
108
+ storage: z.literal("file"),
109
+ token_expires_at: z.string(),
110
+ access_token: z.string(),
111
+ refresh_token: z.string().optional()
112
+ });
113
+ const pfUserSchemaV2 = z.discriminatedUnion("storage", [pfUserKeyringSchema, pfUserFileSchema]);
114
+ const pfConfigSchemaV1 = z.object({
30
115
  version: z.literal(1),
31
- users: z.partialRecord(z.string(), z.object({
32
- access_token: z.string(),
33
- refresh_token: z.string().optional(),
34
- token_expires_at: z.string()
35
- })),
36
- profiles: z.partialRecord(z.string(), z.object({
37
- user: z.string(),
38
- workspace_id: z.string()
39
- })),
116
+ users: z.partialRecord(z.string(), pfUserSchemaV1),
117
+ profiles: z.partialRecord(z.string(), pfProfileSchema),
118
+ current_user: z.string().nullable()
119
+ });
120
+ const LATEST_CONFIG_VERSION = 2;
121
+ const V2_MIN_SDK_VERSION = "1.29.0";
122
+ const semverSchema = z.templateLiteral([
123
+ z.number().int(),
124
+ ".",
125
+ z.number().int(),
126
+ ".",
127
+ z.number().int()
128
+ ]);
129
+ const pfConfigSchemaV2 = z.object({
130
+ version: z.literal(LATEST_CONFIG_VERSION),
131
+ min_sdk_version: semverSchema,
132
+ latest_version: z.number().int().optional(),
133
+ latest_min_sdk_version: semverSchema.optional(),
134
+ users: z.partialRecord(z.string(), pfUserSchemaV2),
135
+ profiles: z.partialRecord(z.string(), pfProfileSchema),
40
136
  current_user: z.string().nullable()
41
137
  });
42
138
  function platformConfigPath() {
@@ -44,34 +140,104 @@ function platformConfigPath() {
44
140
  return path.join(xdgConfig, "tailor-platform", "config.yaml");
45
141
  }
46
142
  /**
47
- * Read Tailor Platform CLI configuration, migrating from tailorctl if necessary.
143
+ * Migrate a v1 config to v2.
144
+ * Tokens are kept in the config file (storage: "file") during migration.
145
+ * They will be moved to the OS keyring on next login or token refresh.
146
+ * @param v1Config - v1 configuration to migrate
147
+ * @returns Migrated v2 configuration
148
+ */
149
+ function migrateV1ToV2(v1Config) {
150
+ const users = {};
151
+ for (const [name, v1User] of Object.entries(v1Config.users)) {
152
+ if (!v1User) continue;
153
+ users[name] = {
154
+ access_token: v1User.access_token,
155
+ refresh_token: v1User.refresh_token,
156
+ token_expires_at: v1User.token_expires_at,
157
+ storage: "file"
158
+ };
159
+ }
160
+ return {
161
+ version: LATEST_CONFIG_VERSION,
162
+ min_sdk_version: V2_MIN_SDK_VERSION,
163
+ users,
164
+ profiles: v1Config.profiles,
165
+ current_user: v1Config.current_user
166
+ };
167
+ }
168
+ /**
169
+ * Read Tailor Platform CLI configuration, migrating from tailorctl or v1 if necessary.
48
170
  * @returns Parsed platform configuration
49
171
  */
50
- function readPlatformConfig() {
172
+ async function readPlatformConfig() {
51
173
  const configPath = platformConfigPath();
52
174
  if (!fs$1.existsSync(configPath)) {
53
175
  logger.warn(`Config not found at ${configPath}, migrating from tailorctl config...`);
54
176
  const tcConfig = readTailorctlConfig();
55
- const pfConfig = tcConfig ? fromTailorctlConfig(tcConfig) : {
177
+ const v1Config = tcConfig ? fromTailorctlConfig(tcConfig) : {
56
178
  version: 1,
57
179
  users: {},
58
180
  profiles: {},
59
181
  current_user: null
60
182
  };
61
- writePlatformConfig(pfConfig);
62
- return pfConfig;
183
+ writePlatformConfig(v1Config);
184
+ return migrateV1ToV2(v1Config);
63
185
  }
64
186
  const rawConfig = parseYAML(fs$1.readFileSync(configPath, "utf-8"));
65
- return pfConfigSchema.parse(rawConfig);
187
+ const version = rawConfig != null && typeof rawConfig === "object" && "version" in rawConfig ? rawConfig.version : void 0;
188
+ if (typeof version === "number" && version > LATEST_CONFIG_VERSION) {
189
+ const minSdk = "min_sdk_version" in rawConfig ? String(rawConfig.min_sdk_version) : void 0;
190
+ const updateHint = minSdk ? `Please update your SDK to >= ${minSdk}: pnpm update @tailor-platform/sdk` : "Please update your SDK: pnpm update @tailor-platform/sdk";
191
+ throw new Error(ml`
192
+ Config file uses version ${String(version)}, but this SDK only supports up to version ${String(LATEST_CONFIG_VERSION)}.
193
+ ${updateHint}
194
+ `);
195
+ }
196
+ const v2Result = pfConfigSchemaV2.safeParse(rawConfig);
197
+ if (v2Result.success) {
198
+ if (v2Result.data.latest_min_sdk_version) {
199
+ if (lt((await readPackageJson()).version ?? "0.0.0", v2Result.data.latest_min_sdk_version)) logger.warn(ml`
200
+ A newer config version (${String(v2Result.data.latest_version)}) is available.
201
+ Please update your SDK to >= ${v2Result.data.latest_min_sdk_version}: pnpm update @tailor-platform/sdk
202
+ `);
203
+ }
204
+ return v2Result.data;
205
+ }
206
+ const v1Result = pfConfigSchemaV1.safeParse(rawConfig);
207
+ if (v1Result.success) return migrateV1ToV2(v1Result.data);
208
+ throw new Error(ml`
209
+ Failed to parse config file at ${configPath}.
210
+ The file may be corrupted or created by an incompatible SDK version.
211
+ `);
212
+ }
213
+ function toV1ForDisk(config) {
214
+ const users = {};
215
+ for (const [name, entry] of Object.entries(config.users)) {
216
+ if (!entry || entry.storage === "keyring") continue;
217
+ users[name] = {
218
+ access_token: entry.access_token,
219
+ refresh_token: entry.refresh_token,
220
+ token_expires_at: entry.token_expires_at
221
+ };
222
+ }
223
+ return {
224
+ version: 1,
225
+ users,
226
+ profiles: config.profiles,
227
+ current_user: config.current_user
228
+ };
66
229
  }
67
230
  /**
68
231
  * Write Tailor Platform CLI configuration to disk.
232
+ * By default, V2 configs are converted to V1 for backward compatibility.
233
+ * Set TAILOR_USE_KEYRING to write V2 format (required for keyring storage).
69
234
  * @param config - Platform configuration to write
70
235
  */
71
236
  function writePlatformConfig(config) {
72
237
  const configPath = platformConfigPath();
73
238
  fs$1.mkdirSync(path.dirname(configPath), { recursive: true });
74
- fs$1.writeFileSync(configPath, stringifyYAML(config));
239
+ const diskConfig = config.version === 2 && !process.env.TAILOR_USE_KEYRING ? toV1ForDisk(config) : config;
240
+ fs$1.writeFileSync(configPath, stringifyYAML(diskConfig));
75
241
  }
76
242
  const tcContextConfigSchema = z.object({
77
243
  username: z.string().optional(),
@@ -127,12 +293,12 @@ function validateUUID(value, source) {
127
293
  * @param opts - Workspace and profile options
128
294
  * @returns Resolved workspace ID
129
295
  */
130
- function loadWorkspaceId(opts) {
296
+ async function loadWorkspaceId(opts) {
131
297
  if (opts?.workspaceId) return validateUUID(opts.workspaceId, "--workspace-id option");
132
298
  if (process.env.TAILOR_PLATFORM_WORKSPACE_ID) return validateUUID(process.env.TAILOR_PLATFORM_WORKSPACE_ID, "TAILOR_PLATFORM_WORKSPACE_ID environment variable");
133
299
  const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
134
300
  if (profile) {
135
- const wsId = readPlatformConfig().profiles[profile]?.workspace_id;
301
+ const wsId = (await readPlatformConfig()).profiles[profile]?.workspace_id;
136
302
  if (!wsId) throw new Error(`Profile "${profile}" not found`);
137
303
  return validateUUID(wsId, `profile "${profile}"`);
138
304
  }
@@ -154,7 +320,7 @@ async function loadAccessToken(opts) {
154
320
  logger.warn("TAILOR_TOKEN is deprecated. Please use TAILOR_PLATFORM_TOKEN instead.");
155
321
  return process.env.TAILOR_TOKEN;
156
322
  }
157
- const pfConfig = readPlatformConfig();
323
+ const pfConfig = await readPlatformConfig();
158
324
  let user;
159
325
  const profile = opts?.useProfile ? opts.profile || process.env.TAILOR_PLATFORM_PROFILE : void 0;
160
326
  if (profile) {
@@ -172,19 +338,71 @@ async function loadAccessToken(opts) {
172
338
  return await fetchLatestToken(pfConfig, user);
173
339
  }
174
340
  /**
341
+ * Resolve the actual token values for a user, reading from keyring or config as appropriate.
342
+ * @param userEntry - User entry from the config
343
+ * @param user - User identifier
344
+ * @returns Access token and optional refresh token
345
+ */
346
+ async function resolveTokens(userEntry, user) {
347
+ if (userEntry.storage === "keyring") {
348
+ const tokens = await loadKeyringTokens(user);
349
+ if (!tokens) throw new Error(ml`
350
+ Credentials not found in OS keyring for "${user}".
351
+ Please run 'tailor-sdk login' and try again.
352
+ `);
353
+ return tokens;
354
+ }
355
+ return {
356
+ accessToken: userEntry.access_token,
357
+ refreshToken: userEntry.refresh_token
358
+ };
359
+ }
360
+ /**
361
+ * Save tokens for a user, writing to keyring or config as appropriate.
362
+ * @param config - Platform config
363
+ * @param user - User identifier
364
+ * @param tokens - Token data to save
365
+ * @param tokens.accessToken
366
+ * @param tokens.refreshToken
367
+ * @param expiresAt - Token expiration date
368
+ */
369
+ async function saveUserTokens(config, user, tokens, expiresAt) {
370
+ if (process.env.TAILOR_USE_KEYRING && await isKeyringAvailable()) {
371
+ await saveKeyringTokens(user, tokens);
372
+ config.users[user] = {
373
+ token_expires_at: expiresAt,
374
+ storage: "keyring"
375
+ };
376
+ } else config.users[user] = {
377
+ access_token: tokens.accessToken,
378
+ refresh_token: tokens.refreshToken,
379
+ token_expires_at: expiresAt,
380
+ storage: "file"
381
+ };
382
+ }
383
+ /**
384
+ * Delete tokens for a user from keyring if applicable.
385
+ * @param config - Platform config
386
+ * @param user - User identifier
387
+ */
388
+ async function deleteUserTokens(config, user) {
389
+ if (config.users[user]?.storage === "keyring") await deleteKeyringTokens(user);
390
+ }
391
+ /**
175
392
  * Fetch the latest access token, refreshing if necessary.
176
393
  * @param config - Platform config
177
394
  * @param user - User name
178
395
  * @returns Latest access token
179
396
  */
180
397
  async function fetchLatestToken(config, user) {
181
- const tokens = config.users[user];
182
- if (!tokens) throw new Error(ml`
398
+ const userEntry = config.users[user];
399
+ if (!userEntry) throw new Error(ml`
183
400
  User "${user}" not found.
184
401
  Please verify your user name and login using 'tailor-sdk login' command.
185
402
  `);
186
- if (new Date(tokens.token_expires_at) > /* @__PURE__ */ new Date()) return tokens.access_token;
187
- if (!tokens.refresh_token) throw new Error(ml`
403
+ const tokens = await resolveTokens(userEntry, user);
404
+ if (new Date(userEntry.token_expires_at) > /* @__PURE__ */ new Date()) return tokens.accessToken;
405
+ if (!tokens.refreshToken) throw new Error(ml`
188
406
  Token expired.
189
407
  Please run 'tailor-sdk login' and try again.
190
408
  `);
@@ -192,9 +410,9 @@ async function fetchLatestToken(config, user) {
192
410
  let resp;
193
411
  try {
194
412
  resp = await client.refreshToken({
195
- accessToken: tokens.access_token,
196
- refreshToken: tokens.refresh_token,
197
- expiresAt: Date.parse(tokens.token_expires_at)
413
+ accessToken: tokens.accessToken,
414
+ refreshToken: tokens.refreshToken,
415
+ expiresAt: Date.parse(userEntry.token_expires_at)
198
416
  });
199
417
  } catch {
200
418
  throw new Error(ml`
@@ -202,11 +420,11 @@ async function fetchLatestToken(config, user) {
202
420
  Please run 'tailor-sdk login' and try again.
203
421
  `);
204
422
  }
205
- config.users[user] = {
206
- access_token: resp.accessToken,
207
- refresh_token: resp.refreshToken,
208
- token_expires_at: new Date(resp.expiresAt).toISOString()
209
- };
423
+ const newExpiresAt = new Date(resp.expiresAt).toISOString();
424
+ await saveUserTokens(config, user, {
425
+ accessToken: resp.accessToken,
426
+ refreshToken: resp.refreshToken ?? void 0
427
+ }, newExpiresAt);
210
428
  writePlatformConfig(config);
211
429
  return resp.accessToken;
212
430
  }
@@ -3571,13 +3789,10 @@ async function bundleSingleResolver(resolver, outputDir, tsconfig, triggerContex
3571
3789
  });
3572
3790
 
3573
3791
  if (result.issues) {
3574
- const errorMessages = result.issues
3575
- .map(issue => {
3576
- const path = issue.path ? issue.path.join('.') : '';
3577
- return path ? \` \${path}: \${issue.message}\` : issue.message;
3578
- })
3579
- .join('\\n');
3580
- throw new Error(\`Failed to input validation:\\n\${errorMessages}\`);
3792
+ throw new TailorErrors(result.issues.map(issue => ({
3793
+ message: issue.message,
3794
+ path: issue.path ?? [],
3795
+ })));
3581
3796
  }
3582
3797
  }
3583
3798
 
@@ -4717,5 +4932,5 @@ async function loadApplication(params) {
4717
4932
  }
4718
4933
 
4719
4934
  //#endregion
4720
- export { writePlatformConfig as S, hashFile as _, loadConfig as a, loadWorkspaceId as b, ExecutorSchema as c, TailorDBTypeSchema as d, stringifyFunction as f, getDistDir as g, createBundleCache as h, resolveInlineSourcemap as i, OAuth2ClientSchema as l, loadFilesWithIgnores as m, generatePluginFilesIfNeeded as n, WorkflowJobSchema as o, tailorUserMap as p, loadApplication as r, createExecutorService as s, defineApplication as t, ResolverSchema as u, fetchLatestToken as v, readPlatformConfig as x, loadAccessToken as y };
4721
- //# sourceMappingURL=application-Bf8SUAtR.mjs.map
4935
+ export { resolveTokens as C, readPlatformConfig as S, writePlatformConfig as T, hashFile as _, loadConfig as a, loadAccessToken as b, ExecutorSchema as c, TailorDBTypeSchema as d, stringifyFunction as f, getDistDir as g, createBundleCache as h, resolveInlineSourcemap as i, OAuth2ClientSchema as l, loadFilesWithIgnores as m, generatePluginFilesIfNeeded as n, WorkflowJobSchema as o, tailorUserMap as p, loadApplication as r, createExecutorService as s, defineApplication as t, ResolverSchema as u, deleteUserTokens as v, saveUserTokens as w, loadWorkspaceId as x, fetchLatestToken as y };
4936
+ //# sourceMappingURL=application-B8vok3w2.mjs.map