carboncanvas-cli 0.1.1 → 0.1.2
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/CONTRACT.md +112 -0
- package/README.md +87 -6
- package/dist/canvasApi.js +102 -0
- package/dist/canvasApi.js.map +1 -0
- package/dist/canvasesCommand.js +25 -0
- package/dist/canvasesCommand.js.map +1 -0
- package/dist/constants.js +10 -4
- package/dist/constants.js.map +1 -1
- package/dist/deviceAuth.js +137 -0
- package/dist/deviceAuth.js.map +1 -0
- package/dist/envFiles.js +110 -0
- package/dist/envFiles.js.map +1 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/dist/initCommand.js +172 -0
- package/dist/initCommand.js.map +1 -0
- package/dist/loginCommand.js +66 -7
- package/dist/loginCommand.js.map +1 -1
- package/dist/prompt.js +18 -3
- package/dist/prompt.js.map +1 -1
- package/dist/session.js +52 -0
- package/dist/session.js.map +1 -0
- package/dist/tokenStore.js +22 -4
- package/dist/tokenStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envFiles.js","sourceRoot":"","sources":["../src/envFiles.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.js
CHANGED
|
@@ -8,4 +8,13 @@ export class UserError extends Error {
|
|
|
8
8
|
this.hint = hint;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
// The backend rejected the bearer token (HTTP 401). `init` catches this to run
|
|
12
|
+
// the device-code login inline ONCE and retry; anywhere it escapes to the shell
|
|
13
|
+
// it prints like any UserError (message + hint), so nothing gets worse.
|
|
14
|
+
export class AuthExpiredError extends UserError {
|
|
15
|
+
constructor() {
|
|
16
|
+
super('Your token is invalid or expired.', 'Run `carboncanvas login`, then re-run `carboncanvas init`.');
|
|
17
|
+
this.name = 'AuthExpiredError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
11
20
|
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAE1E,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,IAAI,CAAU;IACd,YAAY,OAAe,EAAE,IAAa;QACxC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAE1E,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,IAAI,CAAU;IACd,YAAY,OAAe,EAAE,IAAa;QACxC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,+EAA+E;AAC/E,gFAAgF;AAChF,wEAAwE;AACxE,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAC7C;QACE,KAAK,CACH,mCAAmC,EACnC,4DAA4D,CAC7D,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,8 @@ import { UserError } from './errors.js';
|
|
|
8
8
|
import { PublishError } from './upload.js';
|
|
9
9
|
import { DEFAULT_SERVICE_URL, BIN_NAME } from './constants.js';
|
|
10
10
|
import { loginCommand } from './loginCommand.js';
|
|
11
|
+
import { initCommand } from './initCommand.js';
|
|
12
|
+
import { canvasesCommand } from './canvasesCommand.js';
|
|
11
13
|
import { publishCommand } from './publishCommand.js';
|
|
12
14
|
import { clearToken, storedToken } from './tokenStore.js';
|
|
13
15
|
import { verifyToken } from './verify.js';
|
|
@@ -23,7 +25,9 @@ USAGE
|
|
|
23
25
|
${BIN_NAME} <command> [options]
|
|
24
26
|
|
|
25
27
|
COMMANDS
|
|
26
|
-
login
|
|
28
|
+
login Sign in via your browser (device code). --token pastes one instead.
|
|
29
|
+
init Register (or link) a canvas for this project and wire .env / .env.example.
|
|
30
|
+
canvases List your canvases — one "<id> <name>" per line ([archived] marked).
|
|
27
31
|
publish Build locally and upload the static output; prints a review link.
|
|
28
32
|
logout Remove the stored token for a backend.
|
|
29
33
|
whoami Show whether a stored/env token is valid.
|
|
@@ -36,6 +40,14 @@ COMMON OPTIONS
|
|
|
36
40
|
-h, --help Show help.
|
|
37
41
|
-v, --version Show version.
|
|
38
42
|
|
|
43
|
+
init OPTIONS
|
|
44
|
+
--name <name> Canvas name (default: package.json "name", else the directory name).
|
|
45
|
+
--dir <dir> Project directory whose .env to wire (default: cwd).
|
|
46
|
+
--canvas <id> Link an existing canvas (cnv_…) from your account instead of creating.
|
|
47
|
+
--new Always create a new canvas (skip the picker / existing-canvas stop).
|
|
48
|
+
With existing canvases, a TTY gets a picker; non-interactive runs
|
|
49
|
+
(agents, CI) get the list + exit 1 until --canvas or --new decides.
|
|
50
|
+
|
|
39
51
|
publish OPTIONS
|
|
40
52
|
--dir <dir> Project directory (default: cwd).
|
|
41
53
|
--dist <dir> Skip the build; publish this pre-built static directory.
|
|
@@ -46,6 +58,7 @@ publish OPTIONS
|
|
|
46
58
|
|
|
47
59
|
EXAMPLES
|
|
48
60
|
${BIN_NAME} login
|
|
61
|
+
${BIN_NAME} init
|
|
49
62
|
${BIN_NAME} publish
|
|
50
63
|
npx carboncanvas-cli publish --dist dist --name my-prototype
|
|
51
64
|
${BIN_NAME} publish --fresh --label redesign-empty-states
|
|
@@ -77,6 +90,7 @@ async function main(argv) {
|
|
|
77
90
|
dir: { type: 'string' },
|
|
78
91
|
dist: { type: 'string' },
|
|
79
92
|
canvas: { type: 'string' },
|
|
93
|
+
new: { type: 'boolean' },
|
|
80
94
|
fresh: { type: 'boolean' },
|
|
81
95
|
name: { type: 'string' },
|
|
82
96
|
label: { type: 'string' },
|
|
@@ -97,6 +111,22 @@ async function main(argv) {
|
|
|
97
111
|
case 'login':
|
|
98
112
|
await loginCommand({ serviceUrl, token: values.token });
|
|
99
113
|
return 0;
|
|
114
|
+
case 'canvases':
|
|
115
|
+
await canvasesCommand({
|
|
116
|
+
serviceUrl,
|
|
117
|
+
token: values.token,
|
|
118
|
+
});
|
|
119
|
+
return 0;
|
|
120
|
+
case 'init':
|
|
121
|
+
await initCommand({
|
|
122
|
+
serviceUrl,
|
|
123
|
+
token: values.token,
|
|
124
|
+
name: values.name,
|
|
125
|
+
dir: values.dir,
|
|
126
|
+
canvas: values.canvas,
|
|
127
|
+
forceNew: Boolean(values.new),
|
|
128
|
+
});
|
|
129
|
+
return 0;
|
|
100
130
|
case 'publish':
|
|
101
131
|
await publishCommand({
|
|
102
132
|
serviceUrl,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,2EAA2E;AAC3E,0CAA0C;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,gFAAgF;AAChF,MAAM,OAAO,GAAW,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC;AAElF,SAAS,iBAAiB,CAAC,IAAwB;IACjD,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,mBAAmB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,IAAI,GAAG,GAAG,QAAQ;;;IAGpB,QAAQ
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// `carboncanvas init` — register (or link) a canvas for this project and wire
|
|
2
|
+
// it into `.env` (see CONTRACT.md "carboncanvas init"). Thin orchestration:
|
|
3
|
+
//
|
|
4
|
+
// write-once guard → ensure login (inline device flow if needed) →
|
|
5
|
+
// pick the canvas:
|
|
6
|
+
// --canvas <cnv_…> link that existing canvas (must be in the account)
|
|
7
|
+
// --new always create; never lists, never prompts
|
|
8
|
+
// plain, 0 owned create (first-time fast path, TTY or not)
|
|
9
|
+
// plain, ≥1 owned TTY → interactive picker (Enter = create, n = link);
|
|
10
|
+
// non-TTY (agents/CI) → print the canvases + how to
|
|
11
|
+
// choose (--canvas / --new) and exit 1 — never guess,
|
|
12
|
+
// never mint a surprise duplicate
|
|
13
|
+
// → write .env / .env.example / .gitignore → hand off.
|
|
14
|
+
//
|
|
15
|
+
// The write-once guard runs FIRST so we never mint a server-side canvas we
|
|
16
|
+
// can't record locally (comments live on the id; overwriting it orphans them).
|
|
17
|
+
// Any 401 from the API triggers ONE inline re-login, then a single retry of
|
|
18
|
+
// the failed call (session.ts) — a second 401 surfaces the error.
|
|
19
|
+
import { promises as fs } from 'node:fs';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import * as log from './logger.js';
|
|
22
|
+
import { UserError } from './errors.js';
|
|
23
|
+
import { openSession } from './session.js';
|
|
24
|
+
import { promptLine } from './prompt.js';
|
|
25
|
+
import { createCanvas, listCanvases, } from './canvasApi.js';
|
|
26
|
+
import { ENV_BACKEND_KEY, ENV_CANVAS_KEY, existingCanvasId, writeEnvFiles, } from './envFiles.js';
|
|
27
|
+
/**
|
|
28
|
+
* Canvas name resolution: `--name` flag > nearest package.json `name` (walking
|
|
29
|
+
* up from the project dir) > the directory's basename. Exposed for tests.
|
|
30
|
+
*/
|
|
31
|
+
export async function resolveCanvasName(root, flag) {
|
|
32
|
+
if (flag && flag.trim())
|
|
33
|
+
return flag.trim();
|
|
34
|
+
let dir = root;
|
|
35
|
+
for (;;) {
|
|
36
|
+
try {
|
|
37
|
+
const raw = await fs.readFile(path.join(dir, 'package.json'), 'utf8');
|
|
38
|
+
const pkg = JSON.parse(raw);
|
|
39
|
+
if (typeof pkg.name === 'string' && pkg.name.trim())
|
|
40
|
+
return pkg.name.trim();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// No (or unparseable) package.json here — keep walking up.
|
|
44
|
+
}
|
|
45
|
+
const parent = path.dirname(dir);
|
|
46
|
+
if (parent === dir)
|
|
47
|
+
break;
|
|
48
|
+
dir = parent;
|
|
49
|
+
}
|
|
50
|
+
return path.basename(root);
|
|
51
|
+
}
|
|
52
|
+
function describeAction(action) {
|
|
53
|
+
switch (action) {
|
|
54
|
+
case 'created':
|
|
55
|
+
return 'created';
|
|
56
|
+
case 'appended':
|
|
57
|
+
return 'updated';
|
|
58
|
+
case 'unchanged':
|
|
59
|
+
return 'already set up';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Canvas ids are server-minted: `cnv_` + alphanumerics. Checked before any
|
|
63
|
+
// network call so a pasted dashboard URL or a truncated id fails fast.
|
|
64
|
+
const CANVAS_ID_RE = /^cnv_[A-Za-z0-9]+$/;
|
|
65
|
+
// Shared by the picker and the non-TTY stop: the numbered/plain canvas list.
|
|
66
|
+
function printOwnedList(owned, numbered) {
|
|
67
|
+
log.info('');
|
|
68
|
+
log.info(owned.length === 1
|
|
69
|
+
? 'This account already has a canvas:'
|
|
70
|
+
: `This account already has ${owned.length} canvases:`);
|
|
71
|
+
log.info('');
|
|
72
|
+
owned.forEach((c, i) => {
|
|
73
|
+
log.info(numbered ? ` ${i + 1}. ${c.name ?? '(unnamed)'} ${c.id}` : ` ${c.id} ${c.name ?? '(unnamed)'}`);
|
|
74
|
+
});
|
|
75
|
+
log.info('');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The interactive picker (TTY only; callers gate on that). Numbered list of the
|
|
79
|
+
* account's active canvases; Enter creates a new canvas named `newName`, a
|
|
80
|
+
* number links that existing one. Returns null for "create new".
|
|
81
|
+
*/
|
|
82
|
+
async function pickCanvas(owned, newName, ask) {
|
|
83
|
+
printOwnedList(owned, true);
|
|
84
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
85
|
+
const answer = (await ask(`Enter a number to link one, or press Enter to create "${newName}": `)).trim();
|
|
86
|
+
if (answer === '')
|
|
87
|
+
return null;
|
|
88
|
+
const n = Number(answer);
|
|
89
|
+
if (Number.isInteger(n) && n >= 1 && n <= owned.length)
|
|
90
|
+
return owned[n - 1];
|
|
91
|
+
log.warn(`Please enter a number between 1 and ${owned.length}, or press Enter.`);
|
|
92
|
+
}
|
|
93
|
+
throw new UserError('No valid choice made — nothing was created or linked.', 'Re-run `carboncanvas init` (use `--new` to create or `--canvas <id>` to link without the prompt).');
|
|
94
|
+
}
|
|
95
|
+
export async function initCommand(opts) {
|
|
96
|
+
const root = path.resolve(opts.dir ?? process.cwd());
|
|
97
|
+
// Flag sanity — before anything else.
|
|
98
|
+
if (opts.canvas !== undefined && opts.forceNew) {
|
|
99
|
+
throw new UserError('--canvas and --new can’t be combined.', 'Use --canvas <id> to link an existing canvas, or --new to create a fresh one.');
|
|
100
|
+
}
|
|
101
|
+
const wantedCanvas = opts.canvas?.trim();
|
|
102
|
+
if (opts.canvas !== undefined && (!wantedCanvas || !CANVAS_ID_RE.test(wantedCanvas))) {
|
|
103
|
+
throw new UserError(`"${opts.canvas}" doesn’t look like a canvas id.`, 'Canvas ids start with `cnv_` — copy the full id from your dashboard.');
|
|
104
|
+
}
|
|
105
|
+
// 0. Write-once guard — before any network call.
|
|
106
|
+
const existing = await existingCanvasId(root);
|
|
107
|
+
if (existing) {
|
|
108
|
+
throw new UserError(`This project is already connected to canvas ${existing} (${ENV_CANVAS_KEY} in .env).`, 'The canvas id is write-once — comments and review history live on it, so ' +
|
|
109
|
+
'`init` never replaces it. To connect a different canvas, edit .env yourself.');
|
|
110
|
+
}
|
|
111
|
+
// 1. Auth — inline sign-in when there's no stored token; one-shot relogin on 401.
|
|
112
|
+
const session = await openSession(opts, '`carboncanvas init`');
|
|
113
|
+
// 2. Name + 3. Pick or register the canvas.
|
|
114
|
+
const name = await resolveCanvasName(root, opts.name);
|
|
115
|
+
let canvas = null;
|
|
116
|
+
let linked = false;
|
|
117
|
+
if (wantedCanvas) {
|
|
118
|
+
// --canvas: link an existing canvas. Fetch WITH archived so we can tell
|
|
119
|
+
// "archived" apart from "not yours" (both refuse, different message).
|
|
120
|
+
const owned = await session.withRelogin((tok) => listCanvases(opts.serviceUrl, tok, opts.fetchImpl, true));
|
|
121
|
+
const match = owned.find((c) => c.id === wantedCanvas);
|
|
122
|
+
if (!match) {
|
|
123
|
+
throw new UserError(`Canvas ${wantedCanvas} isn’t in your account — check the ID in your dashboard.`, `Your canvases live at ${opts.serviceUrl}/dashboard (or run \`carboncanvas canvases\`).`);
|
|
124
|
+
}
|
|
125
|
+
if (match.archivedAt) {
|
|
126
|
+
throw new UserError(`Canvas ${wantedCanvas} is archived.`, 'Activate it from your dashboard first, then re-run `carboncanvas init --canvas`.');
|
|
127
|
+
}
|
|
128
|
+
canvas = { id: match.id, name: match.name };
|
|
129
|
+
linked = true;
|
|
130
|
+
}
|
|
131
|
+
else if (!opts.forceNew) {
|
|
132
|
+
// Plain `init`: look at what the account already owns before creating,
|
|
133
|
+
// so a second `init` never mints a surprise duplicate canvas.
|
|
134
|
+
const owned = (await session.withRelogin((tok) => listCanvases(opts.serviceUrl, tok, opts.fetchImpl))).filter((c) => !c.archivedAt);
|
|
135
|
+
if (owned.length > 0) {
|
|
136
|
+
const interactive = opts.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
137
|
+
if (interactive) {
|
|
138
|
+
const picked = await pickCanvas(owned, name, opts.promptImpl ?? promptLine);
|
|
139
|
+
if (picked) {
|
|
140
|
+
canvas = { id: picked.id, name: picked.name };
|
|
141
|
+
linked = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Non-interactive (coding agents, CI): the choice must be explicit.
|
|
146
|
+
printOwnedList(owned, false);
|
|
147
|
+
throw new UserError('No canvas was created or linked — this account already has canvases, and non-interactive `init` won’t pick one for you.', `Re-run \`carboncanvas init --canvas <id>\` to link one of the canvases above, or \`carboncanvas init --new\` to create a fresh canvas named "${name}".`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (!canvas) {
|
|
152
|
+
log.step(`Registering canvas "${name}" with ${opts.serviceUrl} …`);
|
|
153
|
+
canvas = await session.withRelogin((tok) => createCanvas(opts.serviceUrl, tok, name, opts.fetchImpl));
|
|
154
|
+
}
|
|
155
|
+
// 4. Wire the env files.
|
|
156
|
+
const written = await writeEnvFiles(root, canvas.id, opts.serviceUrl);
|
|
157
|
+
// 5. Report + hand off to the coding agent.
|
|
158
|
+
const displayName = canvas.name ?? (linked ? null : name);
|
|
159
|
+
const label = displayName ? `"${displayName}" (${canvas.id})` : canvas.id;
|
|
160
|
+
log.success(linked ? `Canvas linked: ${label}` : `Canvas registered: ${label}`);
|
|
161
|
+
log.info('');
|
|
162
|
+
log.info(` .env ${describeAction(written.env)} — ${ENV_CANVAS_KEY}=${canvas.id}`);
|
|
163
|
+
log.info(` ${' '.repeat(describeAction(written.env).length + 3)}${ENV_BACKEND_KEY}=${opts.serviceUrl}`);
|
|
164
|
+
log.info(` .env.example ${describeAction(written.envExample)}${written.envExample === 'unchanged' ? '' : ' — same keys with placeholder values'}`);
|
|
165
|
+
log.info(` .gitignore ${describeAction(written.gitignore)}${written.gitignore === 'unchanged' ? ' (already ignores .env)' : ' — now ignores .env'}`);
|
|
166
|
+
log.info('');
|
|
167
|
+
log.info('Next: tell your coding agent the canvas is registered — it wires the');
|
|
168
|
+
log.info('`comments` prop from these env vars. Instructions: ' + `${opts.serviceUrl}/skill.md`);
|
|
169
|
+
// The one machine-readable line on stdout (like publish's URL).
|
|
170
|
+
log.out(canvas.id);
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=initCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initCommand.js","sourceRoot":"","sources":["../src/initCommand.ts"],"names":[],"mappings":"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"}
|
package/dist/loginCommand.js
CHANGED
|
@@ -1,20 +1,79 @@
|
|
|
1
|
-
// `carboncanvas login` —
|
|
1
|
+
// `carboncanvas login` — browser approval by default (device-code flow, see
|
|
2
|
+
// CONTRACT.md "CLI auth contract"), paste-token as the explicit/fallback path.
|
|
2
3
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Default (no --token): POST /api/cli-auth/start, print the activation link +
|
|
5
|
+
// code PROMINENTLY (the user may be reading this through an agent's terminal
|
|
6
|
+
// relay), best-effort open the browser, poll until approved. On approval the
|
|
7
|
+
// minted session token is verified against GET /api/entitlements and stored in
|
|
8
|
+
// ~/.carboncanvas/config.json (0600) keyed by serviceUrl — exactly like the
|
|
9
|
+
// paste path always did.
|
|
10
|
+
//
|
|
11
|
+
// Paste-token stays reachable: `--token <token>` (non-interactive), and the
|
|
12
|
+
// interactive hidden prompt whenever the device flow is unavailable, expires,
|
|
13
|
+
// or is denied. CARBON_TOKEN still overrides the stored token at use time;
|
|
14
|
+
// --service-url / CARBON_SERVICE_URL selects the backend.
|
|
7
15
|
import * as log from './logger.js';
|
|
8
16
|
import { UserError } from './errors.js';
|
|
9
17
|
import { promptSecret } from './prompt.js';
|
|
10
18
|
import { verifyToken } from './verify.js';
|
|
11
19
|
import { writeToken } from './tokenStore.js';
|
|
20
|
+
import { openBrowser, pollForApproval, startDeviceGrant } from './deviceAuth.js';
|
|
12
21
|
export async function loginCommand(opts) {
|
|
13
|
-
|
|
22
|
+
// Explicit paste path: `carboncanvas login --token cc_xxx`.
|
|
23
|
+
if (opts.token?.trim()) {
|
|
24
|
+
await pasteTokenLogin(opts, opts.token.trim());
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Default: device-code flow (browser approval).
|
|
28
|
+
const grant = await startDeviceGrant(opts.serviceUrl, opts.fetchImpl);
|
|
29
|
+
if (!grant) {
|
|
30
|
+
log.info(`Browser sign-in isn't available on ${opts.serviceUrl} — falling back to paste-token.`);
|
|
31
|
+
await pasteTokenLogin(opts);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Unmissable + copy-friendly: link and code each on their own bare line.
|
|
35
|
+
log.info('');
|
|
36
|
+
log.info(' To finish signing in, open this link in your browser:');
|
|
37
|
+
log.info('');
|
|
38
|
+
log.info(` ${grant.verifyUrl}`);
|
|
39
|
+
log.info('');
|
|
40
|
+
log.info(' and enter this code:');
|
|
41
|
+
log.info('');
|
|
42
|
+
log.info(` ${grant.userCode}`);
|
|
43
|
+
log.info('');
|
|
44
|
+
(opts.openBrowserImpl ?? openBrowser)(grant.verifyUrl);
|
|
45
|
+
log.step('Waiting for approval in the browser … (Ctrl-C to abort)');
|
|
46
|
+
const result = await pollForApproval(opts.serviceUrl, grant, {
|
|
47
|
+
fetchImpl: opts.fetchImpl,
|
|
48
|
+
sleep: opts.sleep,
|
|
49
|
+
heartbeat: (msg) => log.info(msg),
|
|
50
|
+
});
|
|
51
|
+
if (result.status === 'approved') {
|
|
52
|
+
log.step(`Verifying token against ${opts.serviceUrl} …`);
|
|
53
|
+
const verified = await verifyToken(opts.serviceUrl, result.token, opts.fetchImpl);
|
|
54
|
+
if (!verified.ok) {
|
|
55
|
+
throw new UserError(`Sign-in was approved but the token failed verification (HTTP ${verified.status}). Try again.`);
|
|
56
|
+
}
|
|
57
|
+
await writeToken(opts.serviceUrl, result.token);
|
|
58
|
+
log.success(`Logged in. Token saved for ${opts.serviceUrl}.`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (result.status === 'expired') {
|
|
62
|
+
log.warn('That sign-in code expired or was denied.');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
log.warn(`Browser sign-in didn't complete${result.detail ? ` (${result.detail})` : ''}.`);
|
|
66
|
+
}
|
|
67
|
+
log.info('You can paste a creator API token instead.');
|
|
68
|
+
await pasteTokenLogin(opts);
|
|
69
|
+
}
|
|
70
|
+
// The original paste-token path, unchanged in behavior: prompt (hidden input)
|
|
71
|
+
// unless a token was supplied, verify against /api/entitlements, store, greet.
|
|
72
|
+
async function pasteTokenLogin(opts, token) {
|
|
14
73
|
if (!token) {
|
|
15
74
|
log.info(`Paste a creator API token from the dashboard (${opts.serviceUrl}).`);
|
|
16
75
|
log.info('Find it under Settings → API tokens. Input is hidden.');
|
|
17
|
-
token = await promptSecret('Token: ');
|
|
76
|
+
token = await (opts.promptImpl ?? promptSecret)('Token: ');
|
|
18
77
|
}
|
|
19
78
|
if (!token) {
|
|
20
79
|
throw new UserError('No token provided.');
|
package/dist/loginCommand.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loginCommand.js","sourceRoot":"","sources":["../src/loginCommand.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"loginCommand.js","sourceRoot":"","sources":["../src/loginCommand.ts"],"names":[],"mappings":"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"}
|
package/dist/prompt.js
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
// Minimal interactive
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Minimal interactive prompts. promptSecret: one line with echo muted (pasted
|
|
2
|
+
// tokens aren't left on screen), used by `carboncanvas login`. promptLine: one
|
|
3
|
+
// plain visible line, used by `carboncanvas init`'s canvas picker. Both write
|
|
4
|
+
// the question to stderr, keeping stdout clean for the machine-readable line.
|
|
4
5
|
import * as readline from 'node:readline';
|
|
6
|
+
/** Read one visible line from stdin (the init picker — answers aren't secret). */
|
|
7
|
+
export async function promptLine(question) {
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stderr,
|
|
11
|
+
terminal: process.stdin.isTTY === true,
|
|
12
|
+
});
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
rl.question(question, (answer) => {
|
|
15
|
+
rl.close();
|
|
16
|
+
resolve(answer.trim());
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
5
20
|
export async function promptSecret(question) {
|
|
6
21
|
const input = process.stdin;
|
|
7
22
|
const output = process.stderr; // prompt goes to stderr, keeping stdout clean
|
package/dist/prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAE9E,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI;KACvC,CAAC,CAAC;IACH,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,8CAA8C;IAE7E,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,sDAAsD;QACtD,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACrC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;gBAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,6EAA6E;QAC7E,MAAM,KAAK,GAAG,EAAwD,CAAC;QACvE,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,KAAK,CAAC,cAAc,GAAG,CAAC,CAAS,EAAE,EAAE;YACnC,IAAI,CAAC,KAAK;gBAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvB,KAAK,GAAG,IAAI,CAAC;QACb,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;YACzB,KAAK,GAAG,KAAK,CAAC;YACd,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Shared auth plumbing for commands that hit the API with the stored token
|
|
2
|
+
// (`init`, `canvases`): make sure a token exists — running the device-code
|
|
3
|
+
// login inline when there is none — and retry a failed call ONCE through a
|
|
4
|
+
// fresh login when the backend answers 401 (AuthExpiredError). One relogin per
|
|
5
|
+
// command run, never a loop; a second 401 surfaces as-is.
|
|
6
|
+
import * as log from './logger.js';
|
|
7
|
+
import { AuthExpiredError, UserError } from './errors.js';
|
|
8
|
+
import { loginCommand } from './loginCommand.js';
|
|
9
|
+
import { resolveToken } from './tokenStore.js';
|
|
10
|
+
async function runLogin(opts, rerun) {
|
|
11
|
+
await (opts.loginImpl ?? loginCommand)({
|
|
12
|
+
serviceUrl: opts.serviceUrl,
|
|
13
|
+
fetchImpl: opts.fetchImpl,
|
|
14
|
+
});
|
|
15
|
+
const token = await resolveToken(opts.serviceUrl, undefined);
|
|
16
|
+
if (!token) {
|
|
17
|
+
throw new UserError('Sign-in did not complete.', `Run \`carboncanvas login\`, then re-run ${rerun}.`);
|
|
18
|
+
}
|
|
19
|
+
return token;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the token (inline sign-in when none is stored) and hand back the
|
|
23
|
+
* relogin-once wrapper. `rerun` names the command for hints, e.g.
|
|
24
|
+
* '`carboncanvas init`'.
|
|
25
|
+
*/
|
|
26
|
+
export async function openSession(opts, rerun) {
|
|
27
|
+
const stored = await resolveToken(opts.serviceUrl, opts.token);
|
|
28
|
+
let token;
|
|
29
|
+
if (stored) {
|
|
30
|
+
token = stored;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
log.info(`You're not signed in to ${opts.serviceUrl} yet — let's fix that first.`);
|
|
34
|
+
token = await runLogin(opts, rerun);
|
|
35
|
+
}
|
|
36
|
+
let reloginUsed = false;
|
|
37
|
+
const withRelogin = async (call) => {
|
|
38
|
+
try {
|
|
39
|
+
return await call(token);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (!(err instanceof AuthExpiredError) || reloginUsed)
|
|
43
|
+
throw err;
|
|
44
|
+
reloginUsed = true;
|
|
45
|
+
log.info('Your sign-in expired — let’s renew it.');
|
|
46
|
+
token = await runLogin(opts, rerun);
|
|
47
|
+
return call(token); // a second 401 here surfaces to the caller
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return { withRelogin };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E;AAC/E,0DAA0D;AAE1D,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAgB/C,KAAK,UAAU,QAAQ,CAAC,IAAiB,EAAE,KAAa;IACtD,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC;QACrC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CACjB,2BAA2B,EAC3B,2CAA2C,KAAK,GAAG,CACpD,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAiB,EAAE,KAAa;IAChE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,KAAa,CAAC;IAClB,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,IAAI,CAAC,2BAA2B,IAAI,CAAC,UAAU,8BAA8B,CAAC,CAAC;QACnF,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,MAAM,WAAW,GAAG,KAAK,EAAK,IAAiC,EAAc,EAAE;QAC7E,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,gBAAgB,CAAC,IAAI,WAAW;gBAAE,MAAM,GAAG,CAAC;YACjE,WAAW,GAAG,IAAI,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YACnD,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,2CAA2C;QACjE,CAAC;IACH,CAAC,CAAC;IACF,OAAO,EAAE,WAAW,EAAE,CAAC;AACzB,CAAC"}
|
package/dist/tokenStore.js
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
// Stored at ~/.carboncanvas/config.json (mode 0600), keyed by serviceUrl so an
|
|
4
4
|
// author can hold tokens for prod and a self-hosted backend at once:
|
|
5
5
|
//
|
|
6
|
-
// { "tokens": { "https://
|
|
6
|
+
// { "tokens": { "https://app.carboncanvas.design": "cc_..." } }
|
|
7
7
|
//
|
|
8
8
|
// Resolution order for the active token (see resolveToken):
|
|
9
9
|
// 1. --token flag (handled by the caller)
|
|
10
10
|
// 2. CARBON_TOKEN env var
|
|
11
11
|
// 3. the stored token for the active serviceUrl
|
|
12
|
+
// (with a legacy-key fallback for the canonical URL — see storedToken)
|
|
12
13
|
import { promises as fs } from 'node:fs';
|
|
13
14
|
import * as os from 'node:os';
|
|
14
15
|
import * as path from 'node:path';
|
|
15
|
-
import { CONFIG_DIR_NAME, CONFIG_FILE_NAME } from './constants.js';
|
|
16
|
+
import { CONFIG_DIR_NAME, CONFIG_FILE_NAME, DEFAULT_SERVICE_URL, LEGACY_SERVICE_URL, } from './constants.js';
|
|
16
17
|
export function configDir() {
|
|
17
18
|
return path.join(os.homedir(), CONFIG_DIR_NAME);
|
|
18
19
|
}
|
|
@@ -43,7 +44,12 @@ export async function writeToken(serviceUrl, token) {
|
|
|
43
44
|
}
|
|
44
45
|
export async function clearToken(serviceUrl) {
|
|
45
46
|
const cfg = await readConfig();
|
|
46
|
-
|
|
47
|
+
let key = normalizeUrl(serviceUrl);
|
|
48
|
+
// Mirror the storedToken legacy fallback: logging out of the canonical URL
|
|
49
|
+
// must also clear a token an older CLI stored under the legacy Railway key.
|
|
50
|
+
if (!(key in cfg.tokens) && key === normalizeUrl(DEFAULT_SERVICE_URL)) {
|
|
51
|
+
key = normalizeUrl(LEGACY_SERVICE_URL);
|
|
52
|
+
}
|
|
47
53
|
if (!(key in cfg.tokens))
|
|
48
54
|
return false;
|
|
49
55
|
delete cfg.tokens[key];
|
|
@@ -52,7 +58,19 @@ export async function clearToken(serviceUrl) {
|
|
|
52
58
|
}
|
|
53
59
|
export async function storedToken(serviceUrl) {
|
|
54
60
|
const cfg = await readConfig();
|
|
55
|
-
|
|
61
|
+
const key = normalizeUrl(serviceUrl);
|
|
62
|
+
const direct = cfg.tokens[key];
|
|
63
|
+
if (direct !== undefined)
|
|
64
|
+
return direct;
|
|
65
|
+
// Backward compat: CLIs released before the app.carboncanvas.design cutover
|
|
66
|
+
// stored tokens keyed by the legacy Railway URL. A lookup for the canonical
|
|
67
|
+
// URL falls back to that legacy key so existing logins keep working. Writes
|
|
68
|
+
// (writeToken) always use the key they're given — i.e. the new canonical key
|
|
69
|
+
// by default — never the legacy one.
|
|
70
|
+
if (key === normalizeUrl(DEFAULT_SERVICE_URL)) {
|
|
71
|
+
return cfg.tokens[normalizeUrl(LEGACY_SERVICE_URL)];
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
56
74
|
}
|
|
57
75
|
// Resolve the token to use for a request. Explicit `--token` wins, then env, then
|
|
58
76
|
// the stored token. Returns undefined when none is available (caller errors out).
|
package/dist/tokenStore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenStore.js","sourceRoot":"","sources":["../src/tokenStore.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,+EAA+E;AAC/E,qEAAqE;AACrE,EAAE;AACF
|
|
1
|
+
{"version":3,"file":"tokenStore.js","sourceRoot":"","sources":["../src/tokenStore.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "carboncanvas-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Carbon Canvas CLI \u2014 build your prototype locally and publish the static output to a hosted, commentable review link. Bin name: `carboncanvas`.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|