@fixprompt/cli 0.2.1 → 0.3.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.
- package/dist/cli.js +82 -50
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -91,7 +91,14 @@ import { readFileSync, readdirSync, statSync } from "fs";
|
|
|
91
91
|
import { join } from "path";
|
|
92
92
|
import { spawnSync } from "child_process";
|
|
93
93
|
var DEFAULT_ENDPOINT = "https://geosloghub-production.up.railway.app";
|
|
94
|
-
var
|
|
94
|
+
var ENV_VAR_BY_SCOPE = {
|
|
95
|
+
deploy: "FIXPROMPT_DEPLOY_TOKEN",
|
|
96
|
+
read: "FIXPROMPT_READ_TOKEN"
|
|
97
|
+
};
|
|
98
|
+
var ENDPOINT_BY_SCOPE = {
|
|
99
|
+
deploy: "deploy-tokens",
|
|
100
|
+
read: "read-tokens"
|
|
101
|
+
};
|
|
95
102
|
function fileExists(p) {
|
|
96
103
|
try {
|
|
97
104
|
return statSync(p).isFile();
|
|
@@ -123,8 +130,9 @@ function detectProvider(cwd) {
|
|
|
123
130
|
}
|
|
124
131
|
return null;
|
|
125
132
|
}
|
|
126
|
-
async function
|
|
127
|
-
const
|
|
133
|
+
async function mintToken(opts) {
|
|
134
|
+
const path = ENDPOINT_BY_SCOPE[opts.scope];
|
|
135
|
+
const url = `${opts.endpoint.replace(/\/$/, "")}/admin/projects/${opts.projectId}/${path}`;
|
|
128
136
|
const res = await fetch(url, {
|
|
129
137
|
method: "POST",
|
|
130
138
|
headers: {
|
|
@@ -135,20 +143,21 @@ async function mintDeployToken(opts) {
|
|
|
135
143
|
});
|
|
136
144
|
const text = await res.text();
|
|
137
145
|
if (!res.ok) {
|
|
138
|
-
throw new Error(
|
|
146
|
+
throw new Error(
|
|
147
|
+
`broker /admin/projects/${opts.projectId}/${path} responded ${res.status}: ${text.slice(0, 200)}`
|
|
148
|
+
);
|
|
139
149
|
}
|
|
140
150
|
return JSON.parse(text);
|
|
141
151
|
}
|
|
142
|
-
function writeEas(token, env, force) {
|
|
143
|
-
console.log(`
|
|
144
|
-
\u2022 Writing ${TOKEN_ENV_VAR_NAME} to EAS env '${env}'\u2026`);
|
|
152
|
+
function writeEas(envVar, token, env, force) {
|
|
153
|
+
console.log(` \xB7 writing ${envVar} to EAS env '${env}'\u2026`);
|
|
145
154
|
const useShell = process.platform === "win32";
|
|
146
155
|
const args = [
|
|
147
156
|
"eas-cli",
|
|
148
157
|
"env:create",
|
|
149
158
|
env,
|
|
150
159
|
"--name",
|
|
151
|
-
|
|
160
|
+
envVar,
|
|
152
161
|
"--value",
|
|
153
162
|
token,
|
|
154
163
|
"--type",
|
|
@@ -171,11 +180,10 @@ function writeEas(token, env, force) {
|
|
|
171
180
|
);
|
|
172
181
|
}
|
|
173
182
|
}
|
|
174
|
-
function writeGitHubActions(token, cwd) {
|
|
175
|
-
console.log(`
|
|
176
|
-
\u2022 Writing ${TOKEN_ENV_VAR_NAME} to GitHub Actions repo secrets\u2026`);
|
|
183
|
+
function writeGitHubActions(envVar, token, cwd) {
|
|
184
|
+
console.log(` \xB7 writing ${envVar} to GitHub Actions repo secrets\u2026`);
|
|
177
185
|
const useShell = process.platform === "win32";
|
|
178
|
-
const args = ["secret", "set",
|
|
186
|
+
const args = ["secret", "set", envVar, "--body", "-"];
|
|
179
187
|
const r = spawnSync("gh", useShell ? args.map((a) => `"${a.replace(/"/g, '\\"')}"`) : args, {
|
|
180
188
|
input: token,
|
|
181
189
|
cwd,
|
|
@@ -190,7 +198,7 @@ function writeGitHubActions(token, cwd) {
|
|
|
190
198
|
);
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
|
-
async function writeVercel(token, target) {
|
|
201
|
+
async function writeVercel(envVar, token, target) {
|
|
194
202
|
const vt = process.env.VERCEL_TOKEN;
|
|
195
203
|
if (!vt) {
|
|
196
204
|
throw new Error(
|
|
@@ -216,8 +224,7 @@ directory or pass --vercel-project-id <prj_\u2026>.`
|
|
|
216
224
|
}
|
|
217
225
|
}
|
|
218
226
|
const targets = target.vercelTargets ?? ["production", "preview"];
|
|
219
|
-
console.log(`
|
|
220
|
-
\u2022 Writing ${TOKEN_ENV_VAR_NAME} to Vercel project ${projectId} (${targets.join(", ")})\u2026`);
|
|
227
|
+
console.log(` \xB7 writing ${envVar} to Vercel project ${projectId} (${targets.join(", ")})\u2026`);
|
|
221
228
|
const res = await fetch(`https://api.vercel.com/v10/projects/${projectId}/env`, {
|
|
222
229
|
method: "POST",
|
|
223
230
|
headers: {
|
|
@@ -225,7 +232,7 @@ directory or pass --vercel-project-id <prj_\u2026>.`
|
|
|
225
232
|
"Content-Type": "application/json"
|
|
226
233
|
},
|
|
227
234
|
body: JSON.stringify({
|
|
228
|
-
key:
|
|
235
|
+
key: envVar,
|
|
229
236
|
value: token,
|
|
230
237
|
type: "plain",
|
|
231
238
|
target: targets
|
|
@@ -236,8 +243,26 @@ directory or pass --vercel-project-id <prj_\u2026>.`
|
|
|
236
243
|
throw new Error(`Vercel /env responded ${res.status}: ${text.slice(0, 200)}`);
|
|
237
244
|
}
|
|
238
245
|
}
|
|
246
|
+
function writeToProvider(envVar, token, provider, target, force, cwd) {
|
|
247
|
+
switch (provider) {
|
|
248
|
+
case "eas":
|
|
249
|
+
writeEas(envVar, token, target.easEnv, force);
|
|
250
|
+
return;
|
|
251
|
+
case "github-actions":
|
|
252
|
+
writeGitHubActions(envVar, token, cwd);
|
|
253
|
+
return;
|
|
254
|
+
case "vercel":
|
|
255
|
+
return writeVercel(envVar, token, target);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
239
258
|
async function connect(args) {
|
|
240
259
|
const cwd = process.cwd();
|
|
260
|
+
const scopeRaw = (args.flags.scope ?? "deploy").toLowerCase();
|
|
261
|
+
if (scopeRaw !== "deploy" && scopeRaw !== "read" && scopeRaw !== "both") {
|
|
262
|
+
console.error(`Invalid --scope '${scopeRaw}'. Allowed: deploy | read | both.`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
const scope = scopeRaw;
|
|
241
266
|
const adminToken = args.flags["admin-token"] ?? process.env.FIXPROMPT_ADMIN_TOKEN ?? process.env.INTERNAL_ADMIN_TOKEN;
|
|
242
267
|
if (!adminToken) {
|
|
243
268
|
console.error(
|
|
@@ -283,51 +308,52 @@ async function connect(args) {
|
|
|
283
308
|
vercelProjectId: args.flags["vercel-project-id"] ?? void 0,
|
|
284
309
|
vercelTargets: typeof args.flags["vercel-targets"] === "string" ? args.flags["vercel-targets"].split(",").map((t) => t.trim()) : void 0
|
|
285
310
|
};
|
|
286
|
-
const
|
|
311
|
+
const labelBase = args.flags.label ?? `${provider}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}`;
|
|
287
312
|
console.log(`fixprompt connect`);
|
|
313
|
+
console.log(` scope : ${scope}`);
|
|
288
314
|
console.log(` provider : ${provider}`);
|
|
289
315
|
console.log(` project_id : ${projectId}`);
|
|
290
316
|
console.log(` endpoint : ${endpoint}`);
|
|
291
|
-
console.log(` label : ${
|
|
317
|
+
console.log(` label : ${labelBase}`);
|
|
292
318
|
if (provider === "eas") console.log(` eas-env : ${target.easEnv}`);
|
|
293
|
-
console.log(`
|
|
294
|
-
\u2022 Minting deploy token via broker\u2026`);
|
|
295
|
-
const minted = await mintDeployToken({
|
|
296
|
-
endpoint,
|
|
297
|
-
adminToken,
|
|
298
|
-
projectId,
|
|
299
|
-
label
|
|
300
|
-
});
|
|
301
|
-
console.log(` \u2713 token_id ${minted.token_id} (value hidden \u2014 written to CI store only)`);
|
|
302
319
|
const force = args.flags.force === true;
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
320
|
+
const scopes = scope === "both" ? ["deploy", "read"] : [scope];
|
|
321
|
+
const mintedTokens = [];
|
|
322
|
+
for (const s of scopes) {
|
|
323
|
+
const envVar = ENV_VAR_BY_SCOPE[s];
|
|
324
|
+
const label = scope === "both" ? `${labelBase}-${s}` : labelBase;
|
|
325
|
+
console.log(`
|
|
326
|
+
\u2022 Minting ${s} token via broker\u2026`);
|
|
327
|
+
const minted = await mintToken({ endpoint, adminToken, projectId, label, scope: s });
|
|
328
|
+
console.log(` \u2713 token_id ${minted.token_id}`);
|
|
329
|
+
await writeToProvider(envVar, minted.token, provider, target, force, cwd);
|
|
330
|
+
mintedTokens.push({ scope: s, token_id: minted.token_id, envVar });
|
|
313
331
|
}
|
|
314
332
|
console.log(`
|
|
315
|
-
\u2713 ${
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
333
|
+
\u2713 ${mintedTokens.map((m) => m.envVar).join(" + ")} now set on ${provider}.`);
|
|
334
|
+
if (mintedTokens.some((m) => m.scope === "deploy")) {
|
|
335
|
+
if (provider === "eas") {
|
|
336
|
+
console.log(` Next OTA: npm run release:ota --branch=production --message="..."`);
|
|
337
|
+
} else if (provider === "github-actions") {
|
|
338
|
+
console.log(` Reference \${{ secrets.FIXPROMPT_DEPLOY_TOKEN }} in your workflow.`);
|
|
339
|
+
} else {
|
|
340
|
+
console.log(` The deploy token is in your Vercel project env.`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (mintedTokens.some((m) => m.scope === "read")) {
|
|
344
|
+
console.log(` Customer-side agents can now fetch logs via FIXPROMPT_READ_TOKEN \u2014`);
|
|
345
|
+
console.log(` see the fixprompt-debug skill at fixloop-dashboard.vercel.app/claude-skill.md.`);
|
|
323
346
|
}
|
|
324
347
|
console.log(`
|
|
325
|
-
|
|
348
|
+
Revoke any of these from the dashboard \u2192 Integrations.`);
|
|
349
|
+
for (const m of mintedTokens) {
|
|
350
|
+
console.log(` ${m.scope}: ${m.token_id}`);
|
|
351
|
+
}
|
|
326
352
|
}
|
|
327
353
|
|
|
328
354
|
// src/version.ts
|
|
329
355
|
var CLI_NAME = "@fixprompt/cli";
|
|
330
|
-
var CLI_VERSION = "0.
|
|
356
|
+
var CLI_VERSION = "0.3.0";
|
|
331
357
|
|
|
332
358
|
// src/cli.ts
|
|
333
359
|
var DEFAULT_ENDPOINT2 = "https://geosloghub-production.up.railway.app";
|
|
@@ -366,15 +392,21 @@ Usage:
|
|
|
366
392
|
fixprompt help
|
|
367
393
|
|
|
368
394
|
connect options:
|
|
369
|
-
--
|
|
395
|
+
--scope <s> deploy | read | both (default: deploy)
|
|
396
|
+
deploy \u2192 mints fpd_\u2026, writes FIXPROMPT_DEPLOY_TOKEN
|
|
397
|
+
read \u2192 mints fpr_\u2026, writes FIXPROMPT_READ_TOKEN
|
|
398
|
+
(lets a customer's coding agent fetch
|
|
399
|
+
production logs from FixLoop directly)
|
|
400
|
+
both \u2192 does both in one pass
|
|
401
|
+
--project-id <uuid> FixLoop project id (or $FIXPROMPT_PROJECT_ID)
|
|
402
|
+
--project-slug <slug> Look up project_id by slug (no UUID needed)
|
|
370
403
|
--admin-token <fpa_\u2026> Broker admin token (or $FIXPROMPT_ADMIN_TOKEN)
|
|
371
404
|
--provider <name> eas | vercel | github-actions (auto-detected from cwd)
|
|
372
405
|
--eas-env <env> EAS env to write to (default: production)
|
|
373
406
|
--vercel-project-id <id> Override Vercel project id (default: .vercel/project.json)
|
|
374
407
|
--vercel-targets <list> Comma-separated (default: production,preview)
|
|
375
408
|
--label <text> Token label (default: <provider>-<timestamp>)
|
|
376
|
-
--force Overwrite an existing
|
|
377
|
-
--project-slug <slug> Look up project_id by slug (no UUID needed)
|
|
409
|
+
--force Overwrite an existing env var value
|
|
378
410
|
|
|
379
411
|
deploy-start auth (pick one):
|
|
380
412
|
--deploy-token <fpd_...> Deploy-only token from dashboard (recommended for CI)
|
package/package.json
CHANGED