@keystrokehq/cli 0.0.1

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 (122) hide show
  1. package/AGENTS-blurb.md +123 -0
  2. package/LICENSE +42 -0
  3. package/README.md +177 -0
  4. package/THIRD_PARTY_NOTICES.md +16 -0
  5. package/bin/keystroke.mjs +107 -0
  6. package/dist/_manifest-JSRE3H8k.mjs +385 -0
  7. package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
  8. package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
  9. package/dist/agents-CZJGxVqV.mjs +228 -0
  10. package/dist/api-keys-D2lgguuY.mjs +40 -0
  11. package/dist/auth-DN2VusyU.mjs +59 -0
  12. package/dist/auth.handler-CT1BQUvu.mjs +340 -0
  13. package/dist/browser-qwFrUH82.mjs +24 -0
  14. package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
  15. package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
  16. package/dist/build-progress-DgYKb4hB.mjs +183 -0
  17. package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
  18. package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
  19. package/dist/build.handler-4799CjWH.mjs +36 -0
  20. package/dist/chunk-CH6r78ws.mjs +37 -0
  21. package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
  22. package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
  23. package/dist/clear.handler-BydlX-zE.mjs +11 -0
  24. package/dist/commander-DfTVqQ-3.mjs +133 -0
  25. package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
  26. package/dist/connect-BUXkeH0F.mjs +43 -0
  27. package/dist/connect.handler-CYel9cy6.mjs +430 -0
  28. package/dist/constants-CPpPdSNg.mjs +8 -0
  29. package/dist/context-T7HZuB97.mjs +138 -0
  30. package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
  31. package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
  32. package/dist/credentials-CvmjU0lK.mjs +171 -0
  33. package/dist/credentials-OfVHOtG3.mjs +151216 -0
  34. package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
  35. package/dist/current.handler-B8zKzfPp.mjs +21 -0
  36. package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
  37. package/dist/deploy-7Jjls436.mjs +26 -0
  38. package/dist/deploy-BOPIpRWm.mjs +74 -0
  39. package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
  40. package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
  41. package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
  42. package/dist/diff-utils-NEfcjqxt.mjs +185 -0
  43. package/dist/diff.handler-Du7SY8K4.mjs +47 -0
  44. package/dist/dist-BkJUoBiG.mjs +1116 -0
  45. package/dist/dist-CUK7yBM0.mjs +308 -0
  46. package/dist/env-91KwMKov.mjs +140 -0
  47. package/dist/env.handler-BAzBuMzQ.mjs +277 -0
  48. package/dist/error-boundary-VL-JLfIa.mjs +34 -0
  49. package/dist/file-metadata-D1vm-XY2.mjs +191 -0
  50. package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
  51. package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
  52. package/dist/init-DpMCotSK.mjs +45 -0
  53. package/dist/init.handler-CPRnif52.mjs +585 -0
  54. package/dist/inspect.handler-DT_cD036.mjs +146 -0
  55. package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
  56. package/dist/integrations-DlatPK4W.mjs +79 -0
  57. package/dist/keystroke.d.mts +3 -0
  58. package/dist/keystroke.mjs +707 -0
  59. package/dist/layout-CbMtQ2tm.mjs +67 -0
  60. package/dist/list-enrichment-y-cwizLr.mjs +189 -0
  61. package/dist/list.handler-BTWvCyjA.mjs +52 -0
  62. package/dist/list.handler-CWF_Dj15.mjs +24 -0
  63. package/dist/list.handler-CZ6G2x_G.mjs +75 -0
  64. package/dist/list.handler-DWaQkJaR.mjs +51 -0
  65. package/dist/list.handler-DqbFcBW7.mjs +180 -0
  66. package/dist/list.handler-lq3ZGAn4.mjs +104 -0
  67. package/dist/logs-BEg9L5l8.mjs +28 -0
  68. package/dist/logs.handler-6hoMBzqw.mjs +35 -0
  69. package/dist/logs.handler-BD_dXiL1.mjs +231 -0
  70. package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
  71. package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
  72. package/dist/options-CeaTcFxP.mjs +43 -0
  73. package/dist/org-xLzBtt2_.mjs +41 -0
  74. package/dist/output-DM4b7KgY.mjs +72 -0
  75. package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
  76. package/dist/paused.handler-BMFm9Cff.mjs +94 -0
  77. package/dist/project-config-D1qsQlO7.mjs +107 -0
  78. package/dist/projects-CHkRE9rS.mjs +1574 -0
  79. package/dist/projects-Cjb7sovS.mjs +30 -0
  80. package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
  81. package/dist/register.handler-BPCdor1_.mjs +86 -0
  82. package/dist/requirements.handler-DPXdSks3.mjs +201 -0
  83. package/dist/resolve-project-DDJ29sCF.mjs +35 -0
  84. package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
  85. package/dist/run-polling-CAgFRdK3.mjs +20 -0
  86. package/dist/runs-D9hNLb9A.mjs +259 -0
  87. package/dist/schedule-BXx3uXwr.mjs +1142 -0
  88. package/dist/schema-17qMfNyI.mjs +18 -0
  89. package/dist/schema-display-CgmeKigW.mjs +130 -0
  90. package/dist/schemas-CDib1RhE.mjs +125 -0
  91. package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
  92. package/dist/skills.command-CrjI2dN9.mjs +35 -0
  93. package/dist/skills.handler-Bz8bJKql.mjs +9 -0
  94. package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
  95. package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
  96. package/dist/src-C0X6u_Mw.mjs +1340 -0
  97. package/dist/src-eHwu-Gfw.mjs +369 -0
  98. package/dist/status.handler-BO4nwvWn.mjs +101 -0
  99. package/dist/switch.handler-D_9213Vf.mjs +51 -0
  100. package/dist/sync-BL_Mo5st.mjs +39 -0
  101. package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
  102. package/dist/sync.handler-BUFPdzWz.mjs +82 -0
  103. package/dist/task-B2sZMaZu.mjs +8 -0
  104. package/dist/task-target-build-CBeCKbu2.mjs +432 -0
  105. package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
  106. package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
  107. package/dist/task-target-deploy-runner.d.mts +3 -0
  108. package/dist/task-target-deploy-runner.mjs +202 -0
  109. package/dist/test-BHTgR3UA.mjs +698 -0
  110. package/dist/test.handler-BcPQ8b74.mjs +13 -0
  111. package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
  112. package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
  113. package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
  114. package/dist/upload-CkU--iDC.mjs +207 -0
  115. package/dist/upload.handler-DCtiznQp.mjs +441 -0
  116. package/dist/utils-CywxCDM7.mjs +14 -0
  117. package/dist/validate.handler-DOcTaJL0.mjs +280 -0
  118. package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
  119. package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
  120. package/dist/workflows-g9z87AJJ.mjs +799 -0
  121. package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
  122. package/package.json +87 -0
@@ -0,0 +1,441 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { D as throwReportedCliExit, h as toErrorMessage, t as ui } from "./keystroke.mjs";
4
+ import { t as assertWorkflowProjectRoot } from "./project-config-D1qsQlO7.mjs";
5
+ import { a as writeJsonError, i as writeJson } from "./output-DM4b7KgY.mjs";
6
+ import { a as readManifestsFromOutDir, t as collectCredentialFingerprintMapFromProjectDist } from "./dist-BkJUoBiG.mjs";
7
+ import { t as requireWorkflowsDir } from "./resolve-project-DDJ29sCF.mjs";
8
+ import { n as getProcessEnv } from "./env-91KwMKov.mjs";
9
+ import { i as requireClient } from "./context-T7HZuB97.mjs";
10
+ import { t as getIntegrationCatalog } from "./integration-catalog-Bt-L3GjF.mjs";
11
+ import { t as readCredentialEnvMap } from "./credential-env-map-CI8yWHVy.mjs";
12
+ import { a as verifyCredentialResolvable, i as validateManualCredentialWithHook, n as resolveCredentialValuesFromEnv, r as uploadCredential, t as groupCredentialRequirements } from "./credentials-OfVHOtG3.mjs";
13
+ import { n as renderCredentialSchemaMismatchText, r as writeCredentialSchemaMismatchJson, t as isCredentialSchemaMismatchErrorLike } from "./credential-schema-mismatch-BKo5PjcQ.mjs";
14
+ import * as path$1 from "node:path";
15
+ import { confirm, isCancel } from "@clack/prompts";
16
+ //#region src/commands/credentials/upload/upload.handler.ts
17
+ function resolveEnvVarName(credentialSetId, key, envMap) {
18
+ return envMap?.[credentialSetId]?.[key] ?? `KEYSTROKE_${key}`;
19
+ }
20
+ function resolveExpectedEnvVarNames(credentialSetId, keys, envMap) {
21
+ return keys.map((key) => resolveEnvVarName(credentialSetId, key, envMap));
22
+ }
23
+ function quoteCliArg(value) {
24
+ return /\s/.test(value) ? `"${value.replace(/"/g, "\\\"")}"` : value;
25
+ }
26
+ function getCredentialDisplayName(catalog, credentialSetId) {
27
+ const info = catalog.byResolvedCredentialSetId.get(credentialSetId);
28
+ if (info?.role === "connection" && info.integrationPublicId) return info.integrationPublicId;
29
+ return credentialSetId;
30
+ }
31
+ function isCatalogCredentialSet(catalog, credentialSetId) {
32
+ return catalog.byResolvedCredentialSetId.has(credentialSetId);
33
+ }
34
+ function buildMissingSchemaFingerprintMessage(params) {
35
+ return `Cannot upload non-official credential set "${params.credentialSetId}" because the CLI could not discover its schema fingerprint from local build artifacts. Run \`keystroke workflows build\` in "${params.projectRoot}" and retry. Use --path to point at the owning Keystroke project if needed.`;
36
+ }
37
+ function buildRerunCommand(options) {
38
+ const parts = ["keystroke credentials upload"];
39
+ if (options.credentialSet && options.keys) {
40
+ parts.push(`--credential-set ${quoteCliArg(options.credentialSet)}`);
41
+ parts.push(`--keys ${quoteCliArg(options.keys)}`);
42
+ } else if (options.integration) parts.push(`--integration ${quoteCliArg(options.integration)}`);
43
+ if (options.update) parts.push("--update");
44
+ if (options.scope !== "user") parts.push(`--scope ${options.scope}`);
45
+ if (options.path) parts.push(`--path ${quoteCliArg(options.path)}`);
46
+ return parts.join(" ");
47
+ }
48
+ function formatUploadOutcomeMessage(params) {
49
+ const { credentialSetId, uploadedCredentialSetId, action, scope, keyCount } = params;
50
+ const scopeLabel = `scope: ${scope}`;
51
+ if (action === "created") return {
52
+ level: "success",
53
+ message: `${credentialSetId}: created credential set ${uploadedCredentialSetId} (${scopeLabel}) and uploaded ${keyCount} key(s).`
54
+ };
55
+ if (action === "updated-values") return {
56
+ level: "success",
57
+ message: `${credentialSetId}: updated values for existing credential set ${uploadedCredentialSetId} (${scopeLabel}) using ${keyCount} key(s) from your current env vars.`
58
+ };
59
+ if (action === "marked-default") return {
60
+ level: "warn",
61
+ message: `${credentialSetId}: already configured (${uploadedCredentialSetId}, ${scopeLabel}). Marked as default; values unchanged — use --update to refresh from env vars.`
62
+ };
63
+ return {
64
+ level: "warn",
65
+ message: `${credentialSetId}: already configured (${uploadedCredentialSetId}, ${scopeLabel}). Values unchanged — use --update to refresh from env vars.`
66
+ };
67
+ }
68
+ function renderSkippedCredentials(skipped) {
69
+ if (skipped.length === 0) return;
70
+ ui.br();
71
+ ui.warn(`Skipped ${skipped.length} credential set(s) — env vars not found:`);
72
+ for (const item of skipped) ui.text(` - ${item.displayName} (missing: ${item.missingEnvVars.join(", ")})`);
73
+ }
74
+ function renderSummary(results) {
75
+ const created = results.filter((r) => r.action === "created").length;
76
+ const updated = results.filter((r) => r.action === "updated-values").length;
77
+ const unchanged = results.filter((r) => r.action === "unchanged" || r.action === "marked-default").length;
78
+ const parts = [];
79
+ if (created > 0) parts.push(`${created} created`);
80
+ if (updated > 0) parts.push(`${updated} updated`);
81
+ if (unchanged > 0) parts.push(`${unchanged} unchanged`);
82
+ if (parts.length > 0) {
83
+ ui.br();
84
+ ui.text(`Done: ${parts.join(", ")}.`);
85
+ }
86
+ }
87
+ async function resolveProjectIdForUpload(params) {
88
+ const { client, projectRoot } = params;
89
+ const projectConfig = await assertWorkflowProjectRoot(projectRoot);
90
+ const auth = await client.public.auth.validate();
91
+ if (projectConfig.organizationId !== auth.organizationId) {
92
+ const message = `This checkout is configured for organization "${projectConfig.organizationId}", but the current credentials are scoped to "${auth.organizationId}".`;
93
+ ui.error(message);
94
+ ui.hint("Switch organizations or update your local project config before running this command.");
95
+ throwReportedCliExit(message);
96
+ }
97
+ return projectConfig.projectId;
98
+ }
99
+ async function resolveUploadScopeContext(params) {
100
+ const { client, scope, projectRoot } = params;
101
+ if (scope === "user") return {};
102
+ if (scope === "organization") return { organizationId: (await client.public.auth.validate()).organizationId };
103
+ return { projectId: await resolveProjectIdForUpload({
104
+ client,
105
+ projectRoot
106
+ }) };
107
+ }
108
+ function resolveEnvVarStatus(keys, credentialSetId, envMap, env) {
109
+ return keys.map((key) => {
110
+ const envVar = resolveEnvVarName(credentialSetId, key, envMap);
111
+ const value = env[envVar];
112
+ return {
113
+ key,
114
+ envVar,
115
+ present: !!value && value.trim().length > 0
116
+ };
117
+ });
118
+ }
119
+ async function handleCredentialsUpload(options, ctx) {
120
+ const client = requireClient(ctx);
121
+ const isExplicitCredentialSetMode = !!options.credentialSet;
122
+ const isExplicitIntegrationMode = !!options.integration;
123
+ const isExplicitMode = isExplicitCredentialSetMode || isExplicitIntegrationMode;
124
+ const hasKeys = !!options.keys;
125
+ if (isExplicitCredentialSetMode && isExplicitIntegrationMode) {
126
+ ui.error("--integration cannot be combined with --credential-set");
127
+ throwReportedCliExit("--integration cannot be combined with --credential-set");
128
+ }
129
+ if (isExplicitCredentialSetMode && !hasKeys) {
130
+ ui.error("--credential-set requires --keys (comma-separated credential keys)");
131
+ throwReportedCliExit("--credential-set requires --keys (comma-separated credential keys)");
132
+ }
133
+ if (hasKeys && !isExplicitCredentialSetMode) {
134
+ ui.error("--keys requires --credential-set");
135
+ throwReportedCliExit("--keys requires --credential-set");
136
+ }
137
+ if (!isExplicitMode && options.name) {
138
+ ui.error("--name can only be used when specifying --integration or --credential-set");
139
+ throwReportedCliExit("--name can only be used when specifying --integration or --credential-set");
140
+ }
141
+ const scope = options.scope;
142
+ const projectRoot = isExplicitMode && hasKeys ? options.path ? path$1.resolve(options.path) : process.cwd() : await requireWorkflowsDir(options.path);
143
+ const { organizationId, projectId } = await resolveUploadScopeContext({
144
+ client,
145
+ scope,
146
+ projectRoot
147
+ });
148
+ const envMap = await readCredentialEnvMap(projectRoot);
149
+ const catalog = await getIntegrationCatalog(ctx);
150
+ const fingerprintByCredentialSetId = isExplicitIntegrationMode ? /* @__PURE__ */ new Map() : await collectCredentialFingerprintMapFromProjectDist(projectRoot);
151
+ let toUpload = [];
152
+ const skipped = [];
153
+ if (isExplicitCredentialSetMode && hasKeys) {
154
+ const credentialSetId = options.credentialSet;
155
+ const keysArg = options.keys;
156
+ if (!credentialSetId || !keysArg) {
157
+ ui.error("--credential-set and --keys are required for explicit upload");
158
+ throwReportedCliExit("--credential-set and --keys are required for explicit upload");
159
+ }
160
+ const keys = keysArg.split(",").map((k) => k.trim()).filter(Boolean);
161
+ const keyToEnv = envMap?.[credentialSetId];
162
+ const values = resolveCredentialValuesFromEnv(keys, getProcessEnv(), keyToEnv);
163
+ if (!values) {
164
+ const expectedEnvVars = resolveExpectedEnvVarNames(credentialSetId, keys, envMap);
165
+ ui.error(`Missing env vars for ${credentialSetId}. Set: ${expectedEnvVars.join(", ")}`);
166
+ throwReportedCliExit(`Missing env vars for ${credentialSetId}. Set: ${expectedEnvVars.join(", ")}`);
167
+ }
168
+ const info = catalog.byResolvedCredentialSetId.get(credentialSetId);
169
+ toUpload = [{
170
+ credentialSetId,
171
+ displayName: getCredentialDisplayName(catalog, credentialSetId),
172
+ groupScope: null,
173
+ keys,
174
+ values,
175
+ ...fingerprintByCredentialSetId.get(credentialSetId) ? { schemaFingerprint: fingerprintByCredentialSetId.get(credentialSetId) } : {},
176
+ ...info?.connectionKind ? { connectionKind: info.connectionKind } : {}
177
+ }];
178
+ } else if (isExplicitIntegrationMode) {
179
+ const integrationId = options.integration?.trim().toLowerCase();
180
+ const entry = catalog.lookupByPublicId(integrationId);
181
+ if (!integrationId || !entry) {
182
+ ui.error(integrationId ? `Official integration "${integrationId}" is not supported for direct upload.` : "--integration is required for official integration upload");
183
+ throwReportedCliExit(integrationId ? `Official integration "${integrationId}" is not supported for direct upload.` : "--integration is required for official integration upload");
184
+ }
185
+ const publicId = entry.publicId;
186
+ const credentialSetId = entry.credentialSet.resolvedCredentialSetId;
187
+ const storedKeys = entry.credentialSet.storedKeys;
188
+ const authKeys = entry.credentialSet.authKeys;
189
+ const keyToEnv = envMap?.[credentialSetId];
190
+ const values = resolveCredentialValuesFromEnv(storedKeys, getProcessEnv(), keyToEnv);
191
+ if (!values) {
192
+ const expectedEnvVars = resolveExpectedEnvVarNames(credentialSetId, storedKeys, envMap);
193
+ ui.error(`Missing env vars for ${publicId}. Set: ${expectedEnvVars.join(", ")}`);
194
+ throwReportedCliExit(`Missing env vars for ${publicId}. Set: ${expectedEnvVars.join(", ")}`);
195
+ }
196
+ toUpload = [{
197
+ credentialSetId,
198
+ displayName: publicId,
199
+ groupScope: null,
200
+ keys: [...storedKeys],
201
+ verifyKeys: [...authKeys],
202
+ values,
203
+ connectionKind: entry.connectionKind
204
+ }];
205
+ } else {
206
+ const manifests = await readManifestsFromOutDir(projectRoot);
207
+ if (manifests.length === 0) {
208
+ ui.warn("No built manifests found. Run `keystroke workflows build` first.");
209
+ return;
210
+ }
211
+ const seen = /* @__PURE__ */ new Set();
212
+ const env = getProcessEnv();
213
+ for (const { manifest } of manifests) {
214
+ const groups = groupCredentialRequirements(manifest);
215
+ for (const group of groups) {
216
+ const groupKey = `${group.credentialSetId}:${group.scope ?? "__default__"}`;
217
+ if (seen.has(groupKey)) continue;
218
+ seen.add(groupKey);
219
+ const keyToEnv = envMap?.[group.credentialSetId];
220
+ const values = resolveCredentialValuesFromEnv(group.keys, env, keyToEnv);
221
+ if (values) {
222
+ const info = catalog.byResolvedCredentialSetId.get(group.credentialSetId);
223
+ toUpload.push({
224
+ credentialSetId: group.credentialSetId,
225
+ displayName: getCredentialDisplayName(catalog, group.credentialSetId),
226
+ groupScope: group.scope,
227
+ keys: group.keys,
228
+ values,
229
+ ...fingerprintByCredentialSetId.get(group.credentialSetId) ? { schemaFingerprint: fingerprintByCredentialSetId.get(group.credentialSetId) } : {},
230
+ ...info?.connectionKind ? { connectionKind: info.connectionKind } : {}
231
+ });
232
+ } else {
233
+ const missingEnvVars = resolveExpectedEnvVarNames(group.credentialSetId, group.keys, envMap);
234
+ skipped.push({
235
+ credentialSetId: group.credentialSetId,
236
+ displayName: getCredentialDisplayName(catalog, group.credentialSetId),
237
+ missingEnvVars
238
+ });
239
+ }
240
+ }
241
+ }
242
+ if (toUpload.length === 0) {
243
+ ui.warn("No credential requirements had matching env vars.");
244
+ renderSkippedCredentials(skipped);
245
+ ui.hint("Set the missing env vars, then rerun: keystroke credentials upload");
246
+ return;
247
+ }
248
+ }
249
+ const jsonOut = ctx.jsonMode;
250
+ if (options.update && !jsonOut && !options.dryRun && toUpload.length > 0) {
251
+ const shouldContinue = await confirm({ message: `Update ${toUpload.length} existing credential set(s) from current env vars?` });
252
+ if (isCancel(shouldContinue) || !shouldContinue) {
253
+ ui.text("Cancelled.");
254
+ return;
255
+ }
256
+ }
257
+ if (options.dryRun) {
258
+ const env = getProcessEnv();
259
+ if (jsonOut) {
260
+ writeJson({
261
+ dryRun: true,
262
+ update: options.update,
263
+ items: toUpload.map((item) => ({
264
+ credentialSetId: item.credentialSetId,
265
+ displayName: item.displayName,
266
+ scope,
267
+ keys: item.keys,
268
+ envVars: Object.fromEntries(resolveEnvVarStatus(item.keys, item.credentialSetId, envMap, env).map((s) => [s.key, {
269
+ envVar: s.envVar,
270
+ present: s.present
271
+ }]))
272
+ })),
273
+ ...skipped.length > 0 ? { skipped } : {}
274
+ });
275
+ return;
276
+ }
277
+ ui.text(options.update ? `Would create or update ${toUpload.length} credential set(s) with scope ${scope}:` : `Would ensure ${toUpload.length} credential set(s) exist with scope ${scope}:`);
278
+ for (const item of toUpload) {
279
+ const envDetails = resolveEnvVarStatus(item.keys, item.credentialSetId, envMap, env).map((s) => `${s.envVar} (${s.present ? "set" : "missing"})`).join(", ");
280
+ ui.text(` - ${item.displayName} (${item.keys.length} key(s)): ${envDetails}`);
281
+ }
282
+ renderSkippedCredentials(skipped);
283
+ return;
284
+ }
285
+ const results = [];
286
+ let unchangedCount = 0;
287
+ for (const item of toUpload) {
288
+ const credName = options.name ?? `[CLI] ${item.displayName}`;
289
+ if (item.connectionKind === "credentials-exchange") {
290
+ try {
291
+ const exchangeResponse = await client.credentials.exchange({
292
+ credentialSetId: item.credentialSetId,
293
+ input: item.values,
294
+ scope,
295
+ ...projectId ? { projectId } : {},
296
+ name: credName,
297
+ isDefault: true
298
+ });
299
+ if (exchangeResponse.status === "needs-reinput") {
300
+ const msg = exchangeResponse.message ? `Exchange rejected for ${item.displayName}: ${exchangeResponse.message}` : `Exchange for ${item.displayName} returned needs-reinput; re-run after correcting your input.`;
301
+ if (jsonOut) writeJsonError(msg, { code: "EXCHANGE_NEEDS_REINPUT" });
302
+ else {
303
+ ui.warn(msg);
304
+ unchangedCount += 1;
305
+ }
306
+ continue;
307
+ }
308
+ results.push({
309
+ requestedCredentialSetId: item.displayName,
310
+ uploadedCredentialSetId: exchangeResponse.credentialSetId,
311
+ action: "created",
312
+ scope,
313
+ verified: true,
314
+ valuesUpdated: true
315
+ });
316
+ if (!jsonOut) ui.success(`${item.displayName}: exchanged credentials and persisted ${exchangeResponse.keys.length} key(s) (scope: ${scope}).`);
317
+ } catch (e) {
318
+ const msg = `Exchange failed for ${item.displayName}: ${toErrorMessage(e)}`;
319
+ if (jsonOut) writeJsonError(msg, { code: "EXCHANGE_FAILED" });
320
+ else {
321
+ ui.error(msg);
322
+ throwReportedCliExit(msg, { cause: e });
323
+ }
324
+ }
325
+ continue;
326
+ }
327
+ const validation = await validateManualCredentialWithHook({
328
+ credentialSetId: item.credentialSetId,
329
+ values: item.values
330
+ });
331
+ if (validation.status === "failed") {
332
+ const msg = `Validation failed for ${item.displayName}: ${validation.error}`;
333
+ if (jsonOut) {
334
+ writeJsonError(msg, { code: "VALIDATE_FAILED" });
335
+ continue;
336
+ }
337
+ ui.error(msg);
338
+ throwReportedCliExit(msg);
339
+ }
340
+ if (validation.status === "ok" && !jsonOut) ui.text(`Validated credentials against ${item.displayName}.`);
341
+ try {
342
+ if (!item.schemaFingerprint && !isCatalogCredentialSet(catalog, item.credentialSetId)) {
343
+ const message = buildMissingSchemaFingerprintMessage({
344
+ credentialSetId: item.credentialSetId,
345
+ projectRoot
346
+ });
347
+ if (jsonOut) writeJsonError(message, { code: "SCHEMA_FINGERPRINT_REQUIRED" });
348
+ else {
349
+ ui.error(message);
350
+ throwReportedCliExit(message);
351
+ }
352
+ continue;
353
+ }
354
+ const result = await uploadCredential({
355
+ client,
356
+ scope,
357
+ organizationId,
358
+ projectId,
359
+ credentialSetId: item.credentialSetId,
360
+ name: credName,
361
+ values: item.values,
362
+ updateExisting: options.update,
363
+ ...item.schemaFingerprint ? { schemaFingerprint: item.schemaFingerprint } : {}
364
+ });
365
+ let verified = true;
366
+ const verifyKeys = item.verifyKeys ?? item.keys;
367
+ const verify = await verifyCredentialResolvable({
368
+ client,
369
+ credentialSetId: item.credentialSetId,
370
+ keys: verifyKeys,
371
+ scope,
372
+ projectId
373
+ });
374
+ if (!verify.success) {
375
+ verified = false;
376
+ const missing = verifyKeys.filter((k) => !verify.resolvedKeys.includes(k));
377
+ const msg = `Verify failed for ${item.displayName}: missing keys [${missing.join(", ")}]`;
378
+ if (jsonOut) writeJsonError(msg, { code: "VERIFY_FAILED" });
379
+ else {
380
+ ui.error(msg);
381
+ throwReportedCliExit(msg);
382
+ }
383
+ }
384
+ results.push({
385
+ requestedCredentialSetId: item.displayName,
386
+ uploadedCredentialSetId: result.credentialSetId,
387
+ action: result.action,
388
+ scope,
389
+ verified,
390
+ valuesUpdated: result.action === "created" || result.action === "updated-values"
391
+ });
392
+ if (!jsonOut) {
393
+ const outcome = formatUploadOutcomeMessage({
394
+ credentialSetId: item.displayName,
395
+ uploadedCredentialSetId: result.credentialSetId,
396
+ action: result.action,
397
+ scope,
398
+ keyCount: item.keys.length
399
+ });
400
+ if (outcome.level === "success") ui.success(outcome.message);
401
+ else {
402
+ unchangedCount += 1;
403
+ ui.warn(outcome.message);
404
+ }
405
+ }
406
+ } catch (e) {
407
+ if (isCredentialSchemaMismatchErrorLike(e)) {
408
+ if (jsonOut) {
409
+ writeCredentialSchemaMismatchJson(e);
410
+ throwReportedCliExit(e.message ?? `Credential schema mismatch for "${e.manifestId}"`, { cause: e });
411
+ }
412
+ renderCredentialSchemaMismatchText(ui, e);
413
+ throwReportedCliExit(e.message ?? `Credential schema mismatch for "${e.manifestId}"`, { cause: e });
414
+ }
415
+ const msg = `Failed for ${item.displayName}: ${toErrorMessage(e)}`;
416
+ if (jsonOut) writeJsonError(msg, { code: "UPLOAD_FAILED" });
417
+ else {
418
+ ui.error(msg);
419
+ throwReportedCliExit(msg, { cause: e });
420
+ }
421
+ }
422
+ }
423
+ if (jsonOut) {
424
+ writeJson({
425
+ results,
426
+ ...skipped.length > 0 ? { skipped } : {}
427
+ });
428
+ return;
429
+ }
430
+ renderSkippedCredentials(skipped);
431
+ renderSummary(results);
432
+ if (unchangedCount > 0) {
433
+ const updateCommand = buildRerunCommand({
434
+ ...options,
435
+ update: true
436
+ });
437
+ ui.hint(`To update values from your current env vars, rerun with --update: \`${updateCommand}\`.`);
438
+ }
439
+ }
440
+ //#endregion
441
+ export { handleCredentialsUpload };
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { i as readProjectConfig } from "./project-config-D1qsQlO7.mjs";
4
+ import { h as resolveBuildOutputDir } from "./layout-CbMtQ2tm.mjs";
5
+ import path from "node:path";
6
+ //#region ../../packages/project-config/src/utils.ts
7
+ function resolveConfiguredBuildOutputDir(projectRoot, buildConfig) {
8
+ return buildConfig?.outDir ? path.resolve(projectRoot, buildConfig.outDir) : resolveBuildOutputDir(projectRoot);
9
+ }
10
+ async function resolveProjectBuildOutputDir(projectRoot) {
11
+ return resolveConfiguredBuildOutputDir(projectRoot, (await readProjectConfig(projectRoot))?.build);
12
+ }
13
+ //#endregion
14
+ export { resolveProjectBuildOutputDir as n, resolveConfiguredBuildOutputDir as t };