@productbrain/cli 0.1.0-beta.30 → 0.1.0-beta.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -178
- package/dist/__tests__/capture.test.js +2 -11
- package/dist/__tests__/capture.test.js.map +1 -1
- package/dist/__tests__/config.test.d.ts +8 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +166 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/constants.test.js +1 -1
- package/dist/__tests__/constants.test.js.map +1 -1
- package/dist/__tests__/constellation.test.js +2 -8
- package/dist/__tests__/constellation.test.js.map +1 -1
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +117 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/fields.test.js +14 -14
- package/dist/__tests__/fields.test.js.map +1 -1
- package/dist/__tests__/glossary.test.d.ts +2 -0
- package/dist/__tests__/glossary.test.d.ts.map +1 -0
- package/dist/__tests__/glossary.test.js +32 -0
- package/dist/__tests__/glossary.test.js.map +1 -0
- package/dist/__tests__/handshake.test.js +9 -17
- package/dist/__tests__/handshake.test.js.map +1 -1
- package/dist/__tests__/init.test.d.ts +7 -0
- package/dist/__tests__/init.test.d.ts.map +1 -0
- package/dist/__tests__/init.test.js +146 -0
- package/dist/__tests__/init.test.js.map +1 -0
- package/dist/__tests__/login.test.js +29 -30
- package/dist/__tests__/login.test.js.map +1 -1
- package/dist/__tests__/onboarding.test.d.ts +6 -0
- package/dist/__tests__/onboarding.test.d.ts.map +1 -0
- package/dist/__tests__/onboarding.test.js +199 -0
- package/dist/__tests__/onboarding.test.js.map +1 -0
- package/dist/__tests__/profiles.test.d.ts +2 -0
- package/dist/__tests__/profiles.test.d.ts.map +1 -0
- package/dist/__tests__/profiles.test.js +168 -0
- package/dist/__tests__/profiles.test.js.map +1 -0
- package/dist/__tests__/promote.test.js +4 -16
- package/dist/__tests__/promote.test.js.map +1 -1
- package/dist/__tests__/prompts.test.d.ts +6 -0
- package/dist/__tests__/prompts.test.d.ts.map +1 -0
- package/dist/__tests__/prompts.test.js +146 -0
- package/dist/__tests__/prompts.test.js.map +1 -0
- package/dist/__tests__/proposals.test.js +6 -29
- package/dist/__tests__/proposals.test.js.map +1 -1
- package/dist/__tests__/relate.test.js +6 -23
- package/dist/__tests__/relate.test.js.map +1 -1
- package/dist/__tests__/runner.test.js +19 -15
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/session.test.js +2 -8
- package/dist/__tests__/session.test.js.map +1 -1
- package/dist/__tests__/setup.test.js +39 -25
- package/dist/__tests__/setup.test.js.map +1 -1
- package/dist/__tests__/spinner-labels.test.d.ts +2 -0
- package/dist/__tests__/spinner-labels.test.d.ts.map +1 -0
- package/dist/__tests__/spinner-labels.test.js +23 -0
- package/dist/__tests__/spinner-labels.test.js.map +1 -0
- package/dist/__tests__/update.test.js +27 -61
- package/dist/__tests__/update.test.js.map +1 -1
- package/dist/__tests__/workspace.test.d.ts +2 -0
- package/dist/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/__tests__/workspace.test.js +308 -0
- package/dist/__tests__/workspace.test.js.map +1 -0
- package/dist/commands/accept.d.ts.map +1 -1
- package/dist/commands/accept.js +6 -2
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/brief.d.ts.map +1 -1
- package/dist/commands/brief.js +6 -1
- package/dist/commands/brief.js.map +1 -1
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +20 -12
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/chain-walk.d.ts.map +1 -1
- package/dist/commands/chain-walk.js +6 -1
- package/dist/commands/chain-walk.js.map +1 -1
- package/dist/commands/changes.d.ts.map +1 -1
- package/dist/commands/changes.js +6 -1
- package/dist/commands/changes.js.map +1 -1
- package/dist/commands/codex-prep.d.ts.map +1 -1
- package/dist/commands/codex-prep.js +6 -2
- package/dist/commands/codex-prep.js.map +1 -1
- package/dist/commands/collections.d.ts.map +1 -1
- package/dist/commands/collections.js +6 -2
- package/dist/commands/collections.js.map +1 -1
- package/dist/commands/constellation.d.ts.map +1 -1
- package/dist/commands/constellation.js +6 -1
- package/dist/commands/constellation.js.map +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +6 -1
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/doctor.d.ts +9 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +125 -28
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.d.ts +3 -1
- package/dist/commands/doctor.test.d.ts.map +1 -1
- package/dist/commands/doctor.test.js +206 -10
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/fields.d.ts.map +1 -1
- package/dist/commands/fields.js +6 -2
- package/dist/commands/fields.js.map +1 -1
- package/dist/commands/get.d.ts.map +1 -1
- package/dist/commands/get.js +11 -3
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +21 -22
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +11 -3
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +117 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +32 -20
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/profile.d.ts +24 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +82 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/promote.d.ts.map +1 -1
- package/dist/commands/promote.js +22 -7
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/reject.d.ts.map +1 -1
- package/dist/commands/reject.js +11 -5
- package/dist/commands/reject.js.map +1 -1
- package/dist/commands/relate.d.ts.map +1 -1
- package/dist/commands/relate.js +21 -10
- package/dist/commands/relate.js.map +1 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +16 -6
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/setup.d.ts +1 -2
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +17 -38
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +45 -27
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +11 -5
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/workspace.d.ts +41 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +239 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/formatters/promote.d.ts +1 -0
- package/dist/formatters/promote.d.ts.map +1 -1
- package/dist/formatters/promote.js +1 -0
- package/dist/formatters/promote.js.map +1 -1
- package/dist/index.js +328 -299
- package/dist/index.js.map +1 -1
- package/dist/lib/client.d.ts +4 -2
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +143 -68
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/config.d.ts +63 -4
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +230 -36
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +1 -1
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/errors.d.ts +58 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +67 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/format.d.ts +10 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +27 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/glossary.d.ts +19 -0
- package/dist/lib/glossary.d.ts.map +1 -0
- package/dist/lib/glossary.js +53 -0
- package/dist/lib/glossary.js.map +1 -0
- package/dist/lib/onboarding.d.ts +19 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +373 -0
- package/dist/lib/onboarding.js.map +1 -0
- package/dist/lib/profiles.d.ts +34 -0
- package/dist/lib/profiles.d.ts.map +1 -0
- package/dist/lib/profiles.js +173 -0
- package/dist/lib/profiles.js.map +1 -0
- package/dist/lib/prompts.d.ts +38 -0
- package/dist/lib/prompts.d.ts.map +1 -0
- package/dist/lib/prompts.js +90 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/runner.d.ts +2 -0
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +21 -7
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/spinner.d.ts +27 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +76 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/spinner.test.d.ts +2 -0
- package/dist/lib/spinner.test.d.ts.map +1 -0
- package/dist/lib/spinner.test.js +39 -0
- package/dist/lib/spinner.test.js.map +1 -0
- package/dist/lib/style.d.ts +65 -0
- package/dist/lib/style.d.ts.map +1 -0
- package/dist/lib/style.js +108 -0
- package/dist/lib/style.js.map +1 -0
- package/dist/lib/style.test.d.ts +7 -0
- package/dist/lib/style.test.d.ts.map +1 -0
- package/dist/lib/style.test.js +195 -0
- package/dist/lib/style.test.js.map +1 -0
- package/dist/lib/workspace-probe.d.ts +16 -0
- package/dist/lib/workspace-probe.d.ts.map +1 -0
- package/dist/lib/workspace-probe.js +33 -0
- package/dist/lib/workspace-probe.js.map +1 -0
- package/package.json +2 -1
package/dist/lib/config.js
CHANGED
|
@@ -1,21 +1,143 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI config — reads PRODUCTBRAIN_API_KEY + CONVEX_SITE_URL from:
|
|
3
|
-
* 1. Environment variables
|
|
4
|
-
* 2.
|
|
5
|
-
* 3.
|
|
3
|
+
* 1. Environment variables (always highest priority)
|
|
4
|
+
* 2. Project config: .productbrain/config.json in CWD (WP-303 S0)
|
|
5
|
+
* 3. Profile system (~/.config/productbrain/profiles/{name}.env)
|
|
6
|
+
* 4. Legacy ~/.config/productbrain/.env (auto-migrated to profiles on first use)
|
|
7
|
+
* 5. CWD .env.mcp / packages/mcp-server/.env.mcp / .env
|
|
8
|
+
*
|
|
9
|
+
* Config loading is lazy — loadEnv() runs on first getConfig()/getConfigOrGuide() call.
|
|
10
|
+
* This enables profile switching without import-time side effects (TEN-1276).
|
|
6
11
|
*
|
|
7
12
|
* When key is missing and retry is provided (TTY), runs guided flow per docs/cli-unauthenticated-user-journey.md.
|
|
8
13
|
*/
|
|
9
14
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
10
15
|
import { resolve } from 'path';
|
|
11
16
|
import { homedir } from 'os';
|
|
12
|
-
import { createInterface } from 'readline';
|
|
13
17
|
import { DEFAULT_SITE_URL, isDevMode } from './constants.js';
|
|
18
|
+
import { resolveProfileConfig } from './profiles.js';
|
|
19
|
+
import { CLIError, ErrorCode } from './errors.js';
|
|
20
|
+
import { confirm as promptConfirm, password as promptPassword } from './prompts.js';
|
|
14
21
|
const HOME_CONFIG_DIR = resolve(homedir(), '.config', 'productbrain');
|
|
15
22
|
const HOME_ENV_PATH = resolve(HOME_CONFIG_DIR, '.env');
|
|
16
23
|
const CWD_ENV_PATHS = ['.env.mcp', 'packages/mcp-server/.env.mcp', '.env'];
|
|
17
24
|
// Short error when not TTY (scripts/pipes must not hang)
|
|
18
25
|
const NON_TTY_MESSAGE = 'No API key. Set PRODUCTBRAIN_API_KEY or run pb login.';
|
|
26
|
+
/** Track whether env has been loaded to avoid redundant file reads. */
|
|
27
|
+
let envLoaded = false;
|
|
28
|
+
/**
|
|
29
|
+
* Read .productbrain/config.json from CWD.
|
|
30
|
+
* Returns null if file missing. Warns to stderr on invalid JSON but does not throw.
|
|
31
|
+
*/
|
|
32
|
+
function readProjectConfig() {
|
|
33
|
+
const configPath = resolve(process.cwd(), '.productbrain', 'config.json');
|
|
34
|
+
if (!existsSync(configPath))
|
|
35
|
+
return null;
|
|
36
|
+
try {
|
|
37
|
+
const raw = readFileSync(configPath, 'utf8');
|
|
38
|
+
const parsed = JSON.parse(raw);
|
|
39
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
40
|
+
process.stderr.write('Warning: .productbrain/config.json is not a JSON object, skipping.\n');
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const result = {};
|
|
44
|
+
if (typeof parsed.apiKey === 'string' && parsed.apiKey) {
|
|
45
|
+
result.apiKey = parsed.apiKey;
|
|
46
|
+
}
|
|
47
|
+
if (typeof parsed.siteUrl === 'string' && parsed.siteUrl) {
|
|
48
|
+
result.siteUrl = parsed.siteUrl;
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
process.stderr.write('Warning: .productbrain/config.json contains invalid JSON, skipping.\n');
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Run the full config resolution cascade and return a typed result.
|
|
59
|
+
* Resolution order:
|
|
60
|
+
* 1. Environment variables (highest priority)
|
|
61
|
+
* 2. Project config (.productbrain/config.json in CWD)
|
|
62
|
+
* 3. Profile system (~/.config/productbrain/profiles/{name}.env)
|
|
63
|
+
* 4. Legacy home config (~/.config/productbrain/.env)
|
|
64
|
+
* 5. CWD .env files (.env.mcp, packages/mcp-server/.env.mcp, .env)
|
|
65
|
+
*
|
|
66
|
+
* siteUrl always has a value (falls back to DEFAULT_SITE_URL).
|
|
67
|
+
*/
|
|
68
|
+
export function resolveConfig() {
|
|
69
|
+
// 1. Env vars — check directly, don't mutate process.env
|
|
70
|
+
const envKey = process.env.PRODUCTBRAIN_API_KEY;
|
|
71
|
+
const envSite = process.env.CONVEX_SITE_URL;
|
|
72
|
+
if (envKey) {
|
|
73
|
+
return {
|
|
74
|
+
apiKey: envKey,
|
|
75
|
+
siteUrl: (envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
76
|
+
source: 'env',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// 2. Project config
|
|
80
|
+
const projectConfig = readProjectConfig();
|
|
81
|
+
if (projectConfig?.apiKey) {
|
|
82
|
+
return {
|
|
83
|
+
apiKey: projectConfig.apiKey,
|
|
84
|
+
siteUrl: (projectConfig.siteUrl || envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
85
|
+
source: 'project',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// 3. Profile system
|
|
89
|
+
const profileConfig = resolveProfileConfig();
|
|
90
|
+
if (profileConfig?.apiKey) {
|
|
91
|
+
return {
|
|
92
|
+
apiKey: profileConfig.apiKey,
|
|
93
|
+
siteUrl: (profileConfig.siteUrl || envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
94
|
+
source: 'profile',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// 4. Legacy home config
|
|
98
|
+
if (existsSync(HOME_ENV_PATH)) {
|
|
99
|
+
const vars = parseEnvVars(readFileSync(HOME_ENV_PATH, 'utf8'));
|
|
100
|
+
if (vars['PRODUCTBRAIN_API_KEY']) {
|
|
101
|
+
return {
|
|
102
|
+
apiKey: vars['PRODUCTBRAIN_API_KEY'],
|
|
103
|
+
siteUrl: (vars['CONVEX_SITE_URL'] || envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
104
|
+
source: 'profile',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// 5. CWD .env files
|
|
109
|
+
for (const p of CWD_ENV_PATHS) {
|
|
110
|
+
const full = resolve(process.cwd(), p);
|
|
111
|
+
if (existsSync(full)) {
|
|
112
|
+
const vars = parseEnvVars(readFileSync(full, 'utf8'));
|
|
113
|
+
if (vars['PRODUCTBRAIN_API_KEY']) {
|
|
114
|
+
return {
|
|
115
|
+
apiKey: vars['PRODUCTBRAIN_API_KEY'],
|
|
116
|
+
siteUrl: (vars['CONVEX_SITE_URL'] || envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
117
|
+
source: 'cwd',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// 6. No API key found anywhere — return with siteUrl default
|
|
124
|
+
return {
|
|
125
|
+
apiKey: undefined,
|
|
126
|
+
siteUrl: (envSite || DEFAULT_SITE_URL).replace(/\/$/, ''),
|
|
127
|
+
source: 'default',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** Parse env file content and return key-value pairs (without mutating process.env). */
|
|
131
|
+
function parseEnvVars(content) {
|
|
132
|
+
const vars = {};
|
|
133
|
+
for (const line of content.split('\n')) {
|
|
134
|
+
const m = line.match(/^([^#=]+)=(.*)$/);
|
|
135
|
+
if (m) {
|
|
136
|
+
vars[m[1].trim()] = m[2].trim().replace(/^["']|["']$/g, '');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return vars;
|
|
140
|
+
}
|
|
19
141
|
function parseEnvContent(content) {
|
|
20
142
|
for (const line of content.split('\n')) {
|
|
21
143
|
const m = line.match(/^([^#=]+)=(.*)$/);
|
|
@@ -25,9 +147,35 @@ function parseEnvContent(content) {
|
|
|
25
147
|
}
|
|
26
148
|
}
|
|
27
149
|
function loadEnv() {
|
|
150
|
+
if (envLoaded)
|
|
151
|
+
return;
|
|
152
|
+
envLoaded = true;
|
|
153
|
+
// 1. Try project config first (WP-303 S0)
|
|
154
|
+
const projectConfig = readProjectConfig();
|
|
155
|
+
if (projectConfig) {
|
|
156
|
+
if (!process.env.PRODUCTBRAIN_API_KEY && projectConfig.apiKey) {
|
|
157
|
+
process.env.PRODUCTBRAIN_API_KEY = projectConfig.apiKey;
|
|
158
|
+
}
|
|
159
|
+
if (!process.env.CONVEX_SITE_URL && projectConfig.siteUrl) {
|
|
160
|
+
process.env.CONVEX_SITE_URL = projectConfig.siteUrl;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// 2. Try profile system (handles auto-migration from legacy .env)
|
|
164
|
+
const profileConfig = resolveProfileConfig();
|
|
165
|
+
if (profileConfig) {
|
|
166
|
+
// Only set if not already set by env vars or project config
|
|
167
|
+
if (!process.env.PRODUCTBRAIN_API_KEY) {
|
|
168
|
+
process.env.PRODUCTBRAIN_API_KEY = profileConfig.apiKey;
|
|
169
|
+
}
|
|
170
|
+
if (!process.env.CONVEX_SITE_URL && profileConfig.siteUrl) {
|
|
171
|
+
process.env.CONVEX_SITE_URL = profileConfig.siteUrl;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// 3. Legacy home config (in case profiles didn't find it)
|
|
28
175
|
if (existsSync(HOME_ENV_PATH)) {
|
|
29
176
|
parseEnvContent(readFileSync(HOME_ENV_PATH, 'utf8'));
|
|
30
177
|
}
|
|
178
|
+
// 4. CWD env files
|
|
31
179
|
for (const p of CWD_ENV_PATHS) {
|
|
32
180
|
const full = resolve(process.cwd(), p);
|
|
33
181
|
if (existsSync(full)) {
|
|
@@ -36,49 +184,55 @@ function loadEnv() {
|
|
|
36
184
|
}
|
|
37
185
|
}
|
|
38
186
|
}
|
|
39
|
-
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
rl.question(prompt, (answer) => resolve((answer ?? '').trim().toLowerCase()));
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
function questionRaw(rl, prompt) {
|
|
46
|
-
return new Promise((resolve) => {
|
|
47
|
-
rl.question(prompt, (answer) => resolve((answer ?? '').trim()));
|
|
48
|
-
});
|
|
187
|
+
/** Reset env loaded state — used for profile switching. */
|
|
188
|
+
export function resetConfigCache() {
|
|
189
|
+
envLoaded = false;
|
|
49
190
|
}
|
|
50
191
|
/**
|
|
51
192
|
* Guided flow when key is missing (TTY only). Per docs/cli-unauthenticated-user-journey.md.
|
|
52
193
|
* Returns true if we saved and ran retry; false if user said No (caller should exit).
|
|
53
194
|
*/
|
|
54
195
|
async function runGuidedFlow(retry) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (hasKey
|
|
196
|
+
const hasKey = await promptConfirm({
|
|
197
|
+
message: 'Do you have an API key from Product Brain?',
|
|
198
|
+
initialValue: false,
|
|
199
|
+
});
|
|
200
|
+
if (!hasKey) {
|
|
60
201
|
console.log('Get your key: Product Brain app → Settings → API Keys. Then run: pb login');
|
|
61
|
-
rl.close();
|
|
62
202
|
process.exit(0);
|
|
63
203
|
}
|
|
64
|
-
let apiKey = await
|
|
65
|
-
|
|
204
|
+
let apiKey = await promptPassword({
|
|
205
|
+
message: 'Paste your API key (pb_sk_...)',
|
|
206
|
+
validate: (v) => (!v ? 'Key is required' : undefined),
|
|
207
|
+
});
|
|
208
|
+
if (!apiKey.startsWith('pb_sk_')) {
|
|
66
209
|
console.log('Key must start with pb_sk_. Try again or run pb login.');
|
|
67
|
-
apiKey = await
|
|
210
|
+
apiKey = await promptPassword({
|
|
211
|
+
message: 'Paste your API key (pb_sk_...)',
|
|
212
|
+
validate: (v) => (!v || !v.startsWith('pb_sk_') ? 'Key must start with pb_sk_' : undefined),
|
|
213
|
+
});
|
|
68
214
|
}
|
|
69
|
-
rl.close();
|
|
70
215
|
if (!apiKey || !apiKey.startsWith('pb_sk_')) {
|
|
71
216
|
console.log('Get your key: Product Brain app → Settings → API Keys. Then run: pb login');
|
|
72
217
|
process.exit(0);
|
|
73
218
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
''
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
219
|
+
// Save as a named profile via the profile system
|
|
220
|
+
const { createProfile, getActiveProfile } = await import('./profiles.js');
|
|
221
|
+
const profileName = getActiveProfile() || 'default';
|
|
222
|
+
try {
|
|
223
|
+
createProfile(profileName, apiKey, DEFAULT_SITE_URL.replace(/\/$/, ''));
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Profile already exists — fall back to legacy path
|
|
227
|
+
const content = [
|
|
228
|
+
`# Product Brain CLI — saved by guided setup`,
|
|
229
|
+
`PRODUCTBRAIN_API_KEY=${apiKey}`,
|
|
230
|
+
`CONVEX_SITE_URL=${DEFAULT_SITE_URL.replace(/\/$/, '')}`,
|
|
231
|
+
'',
|
|
232
|
+
].join('\n');
|
|
233
|
+
mkdirSync(HOME_CONFIG_DIR, { recursive: true });
|
|
234
|
+
writeFileSync(HOME_ENV_PATH, content, { mode: 0o600 });
|
|
235
|
+
}
|
|
82
236
|
process.env.PRODUCTBRAIN_API_KEY = apiKey;
|
|
83
237
|
process.env.CONVEX_SITE_URL = DEFAULT_SITE_URL.replace(/\/$/, '');
|
|
84
238
|
console.log('Saved your key. Running your command…\n');
|
|
@@ -86,23 +240,59 @@ async function runGuidedFlow(retry) {
|
|
|
86
240
|
return true;
|
|
87
241
|
}
|
|
88
242
|
export function getConfig() {
|
|
243
|
+
loadEnv();
|
|
89
244
|
const apiKey = process.env.PRODUCTBRAIN_API_KEY ?? '';
|
|
90
245
|
const siteUrl = (process.env.CONVEX_SITE_URL ?? DEFAULT_SITE_URL).replace(/\/$/, '');
|
|
91
246
|
if (!apiKey || !apiKey.startsWith('pb_sk_')) {
|
|
92
|
-
throw new
|
|
247
|
+
throw new CLIError(NON_TTY_MESSAGE, {
|
|
248
|
+
code: ErrorCode.AUTH_MISSING,
|
|
249
|
+
category: 'auth',
|
|
250
|
+
guidance: 'Set PRODUCTBRAIN_API_KEY or run `pb login`.',
|
|
251
|
+
});
|
|
93
252
|
}
|
|
94
253
|
const allowHttp = isDevMode() && siteUrl.startsWith('http://localhost');
|
|
95
254
|
if (!siteUrl.startsWith('https://') && !allowHttp) {
|
|
96
|
-
throw new
|
|
255
|
+
throw new CLIError(`CONVEX_SITE_URL must use HTTPS (got "${siteUrl.slice(0, 30)}…"). API keys must not be sent over unencrypted connections.`, {
|
|
256
|
+
code: ErrorCode.CONFIG_INVALID,
|
|
257
|
+
category: 'config',
|
|
258
|
+
guidance: 'Set CONVEX_SITE_URL to an https:// URL.',
|
|
259
|
+
});
|
|
97
260
|
}
|
|
98
261
|
return { apiKey, siteUrl };
|
|
99
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Non-throwing alternative to getConfig().
|
|
265
|
+
*
|
|
266
|
+
* Architecture: getConfig() is the primary path for commands that require auth — it
|
|
267
|
+
* throws CLIError when the key is missing, which is correct for API call paths.
|
|
268
|
+
* getConfigSafe() is for status/probe surfaces (no-args dashboard, init) that need
|
|
269
|
+
* to check config availability without crashing. Both paths are intentional and
|
|
270
|
+
* coexist by design — see WP-303 review (DW#5).
|
|
271
|
+
*
|
|
272
|
+
* Uses resolveConfig() directly (no loadEnv) to avoid env var pollution affecting source attribution.
|
|
273
|
+
*/
|
|
274
|
+
export function getConfigSafe() {
|
|
275
|
+
const resolved = resolveConfig();
|
|
276
|
+
if (!resolved.apiKey || !resolved.apiKey.startsWith('pb_sk_')) {
|
|
277
|
+
return { ok: false, reason: 'No API key. Run pb login or set PRODUCTBRAIN_API_KEY.' };
|
|
278
|
+
}
|
|
279
|
+
const siteUrl = resolved.siteUrl;
|
|
280
|
+
const allowHttp = isDevMode() && siteUrl.startsWith('http://localhost');
|
|
281
|
+
if (!siteUrl.startsWith('https://') && !allowHttp) {
|
|
282
|
+
return {
|
|
283
|
+
ok: false,
|
|
284
|
+
reason: `CONVEX_SITE_URL must use HTTPS (got "${siteUrl.slice(0, 30)}…"). API keys must not be sent over unencrypted connections.`,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
return { ok: true, apiKey: resolved.apiKey, siteUrl, source: resolved.source };
|
|
288
|
+
}
|
|
100
289
|
/**
|
|
101
290
|
* Get config; if key is missing and stdin is a TTY, run guided flow (y/n → paste key → save → retry).
|
|
102
291
|
* @param retry Called after saving key so the original command runs in-process.
|
|
103
292
|
* @returns Config, or null if we ran retry (caller should return without running again).
|
|
104
293
|
*/
|
|
105
294
|
export async function getConfigOrGuide(retry) {
|
|
295
|
+
loadEnv();
|
|
106
296
|
const apiKey = process.env.PRODUCTBRAIN_API_KEY ?? '';
|
|
107
297
|
const siteUrl = (process.env.CONVEX_SITE_URL ?? DEFAULT_SITE_URL).replace(/\/$/, '');
|
|
108
298
|
const allowHttp = isDevMode() && siteUrl.startsWith('http://localhost');
|
|
@@ -110,10 +300,14 @@ export async function getConfigOrGuide(retry) {
|
|
|
110
300
|
return { apiKey, siteUrl };
|
|
111
301
|
}
|
|
112
302
|
if (!process.stdin.isTTY) {
|
|
113
|
-
throw new
|
|
303
|
+
throw new CLIError(NON_TTY_MESSAGE, {
|
|
304
|
+
code: ErrorCode.AUTH_MISSING,
|
|
305
|
+
category: 'auth',
|
|
306
|
+
guidance: 'Set PRODUCTBRAIN_API_KEY or run `pb login`.',
|
|
307
|
+
});
|
|
114
308
|
}
|
|
115
309
|
const didRetry = await runGuidedFlow(retry);
|
|
116
310
|
return didRetry ? null : null;
|
|
117
311
|
}
|
|
118
|
-
export { HOME_CONFIG_DIR, HOME_ENV_PATH };
|
|
312
|
+
export { HOME_CONFIG_DIR, HOME_ENV_PATH, readProjectConfig };
|
|
119
313
|
//# sourceMappingURL=config.js.map
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* WP-301 Slice 0: Extract hardcoded URLs, add PB_ENV awareness.
|
|
4
4
|
*/
|
|
5
5
|
/** Production Convex HTTP Actions endpoint. */
|
|
6
|
-
export declare const DEFAULT_SITE_URL = "https://
|
|
6
|
+
export declare const DEFAULT_SITE_URL = "https://gateway.productbrain.io";
|
|
7
7
|
/**
|
|
8
8
|
* Resolve the Convex site URL based on PB_ENV.
|
|
9
9
|
* - PB_ENV=dev → local Convex dev server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,gBAAgB,oCAAoC,CAAC;AAWlE;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAIvC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
|
package/dist/lib/constants.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* WP-301 Slice 0: Extract hardcoded URLs, add PB_ENV awareness.
|
|
4
4
|
*/
|
|
5
5
|
/** Production Convex HTTP Actions endpoint. */
|
|
6
|
-
export const DEFAULT_SITE_URL = 'https://
|
|
6
|
+
export const DEFAULT_SITE_URL = 'https://gateway.productbrain.io';
|
|
7
7
|
/** Production web app URL. */
|
|
8
8
|
const PROD_APP_URL = 'https://work.productbrain.io';
|
|
9
9
|
/** Local Convex dev server URL. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,iCAAiC,CAAC;AAElE,8BAA8B;AAC9B,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAEpD,mCAAmC;AACnC,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAE7C,yBAAyB;AACzB,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAC9C,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,YAAY,CAAC;IACvC,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAC9C,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,WAAW,CAAC;IACtC,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,KAAK,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLIError — structured error taxonomy for the Product Brain CLI.
|
|
3
|
+
*
|
|
4
|
+
* WP-302 Slice 0: Error Taxonomy + Commander Migration.
|
|
5
|
+
* WP-302 Slice 2: Profile error codes added.
|
|
6
|
+
* Every CLI error carries a machine-readable code, category, and actionable guidance.
|
|
7
|
+
* The global error handler in index.ts formats these for JSON or human output.
|
|
8
|
+
*/
|
|
9
|
+
/** Error categories — groups of related failure modes. */
|
|
10
|
+
export type ErrorCategory = 'auth' | 'network' | 'config' | 'validation' | 'session' | 'profile' | 'internal';
|
|
11
|
+
/** Known error codes — extend as new failure modes are discovered. */
|
|
12
|
+
export declare const ErrorCode: {
|
|
13
|
+
readonly AUTH_MISSING: "AUTH_MISSING";
|
|
14
|
+
readonly AUTH_INVALID: "AUTH_INVALID";
|
|
15
|
+
readonly AUTH_DENIED: "AUTH_DENIED";
|
|
16
|
+
readonly NETWORK_UNREACHABLE: "NETWORK_UNREACHABLE";
|
|
17
|
+
readonly NETWORK_TIMEOUT: "NETWORK_TIMEOUT";
|
|
18
|
+
readonly CONFIG_MISSING: "CONFIG_MISSING";
|
|
19
|
+
readonly CONFIG_INVALID: "CONFIG_INVALID";
|
|
20
|
+
readonly SESSION_REQUIRED: "SESSION_REQUIRED";
|
|
21
|
+
readonly VALIDATION_FAILED: "VALIDATION_FAILED";
|
|
22
|
+
readonly PROFILE_NOT_FOUND: "PROFILE_NOT_FOUND";
|
|
23
|
+
readonly PROFILE_ALREADY_EXISTS: "PROFILE_ALREADY_EXISTS";
|
|
24
|
+
readonly PROFILE_IS_ACTIVE: "PROFILE_IS_ACTIVE";
|
|
25
|
+
readonly PROFILE_IS_LAST: "PROFILE_IS_LAST";
|
|
26
|
+
readonly PROFILE_NAME_INVALID: "PROFILE_NAME_INVALID";
|
|
27
|
+
readonly NON_INTERACTIVE: "NON_INTERACTIVE";
|
|
28
|
+
readonly INTERNAL: "INTERNAL";
|
|
29
|
+
};
|
|
30
|
+
export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
31
|
+
/**
|
|
32
|
+
* Structured CLI error with machine-readable fields.
|
|
33
|
+
*
|
|
34
|
+
* Usage:
|
|
35
|
+
* throw new CLIError('No API key configured', {
|
|
36
|
+
* code: ErrorCode.AUTH_MISSING,
|
|
37
|
+
* category: 'auth',
|
|
38
|
+
* guidance: 'Run `pb login` to configure your API key.',
|
|
39
|
+
* });
|
|
40
|
+
*/
|
|
41
|
+
export declare class CLIError extends Error {
|
|
42
|
+
readonly code: ErrorCodeValue;
|
|
43
|
+
readonly category: ErrorCategory;
|
|
44
|
+
readonly guidance?: string;
|
|
45
|
+
constructor(message: string, options?: {
|
|
46
|
+
code?: ErrorCodeValue;
|
|
47
|
+
category?: ErrorCategory;
|
|
48
|
+
guidance?: string;
|
|
49
|
+
});
|
|
50
|
+
/** Serialize for JSON error output. */
|
|
51
|
+
toJSON(): {
|
|
52
|
+
error: string;
|
|
53
|
+
code: string;
|
|
54
|
+
category: string;
|
|
55
|
+
guidance?: string;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAE9G,sEAAsE;AACtE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;CAyBZ,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAGzB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,cAAc,CAAC;QACtB,QAAQ,CAAC,EAAE,aAAa,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IASH,uCAAuC;IACvC,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAQ/E"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLIError — structured error taxonomy for the Product Brain CLI.
|
|
3
|
+
*
|
|
4
|
+
* WP-302 Slice 0: Error Taxonomy + Commander Migration.
|
|
5
|
+
* WP-302 Slice 2: Profile error codes added.
|
|
6
|
+
* Every CLI error carries a machine-readable code, category, and actionable guidance.
|
|
7
|
+
* The global error handler in index.ts formats these for JSON or human output.
|
|
8
|
+
*/
|
|
9
|
+
/** Known error codes — extend as new failure modes are discovered. */
|
|
10
|
+
export const ErrorCode = {
|
|
11
|
+
// Auth
|
|
12
|
+
AUTH_MISSING: 'AUTH_MISSING',
|
|
13
|
+
AUTH_INVALID: 'AUTH_INVALID',
|
|
14
|
+
AUTH_DENIED: 'AUTH_DENIED',
|
|
15
|
+
// Network
|
|
16
|
+
NETWORK_UNREACHABLE: 'NETWORK_UNREACHABLE',
|
|
17
|
+
NETWORK_TIMEOUT: 'NETWORK_TIMEOUT',
|
|
18
|
+
// Config
|
|
19
|
+
CONFIG_MISSING: 'CONFIG_MISSING',
|
|
20
|
+
CONFIG_INVALID: 'CONFIG_INVALID',
|
|
21
|
+
// Session
|
|
22
|
+
SESSION_REQUIRED: 'SESSION_REQUIRED',
|
|
23
|
+
// Validation
|
|
24
|
+
VALIDATION_FAILED: 'VALIDATION_FAILED',
|
|
25
|
+
// Profile (WP-302 S2)
|
|
26
|
+
PROFILE_NOT_FOUND: 'PROFILE_NOT_FOUND',
|
|
27
|
+
PROFILE_ALREADY_EXISTS: 'PROFILE_ALREADY_EXISTS',
|
|
28
|
+
PROFILE_IS_ACTIVE: 'PROFILE_IS_ACTIVE',
|
|
29
|
+
PROFILE_IS_LAST: 'PROFILE_IS_LAST',
|
|
30
|
+
PROFILE_NAME_INVALID: 'PROFILE_NAME_INVALID',
|
|
31
|
+
// Interactive
|
|
32
|
+
NON_INTERACTIVE: 'NON_INTERACTIVE',
|
|
33
|
+
// Internal
|
|
34
|
+
INTERNAL: 'INTERNAL',
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Structured CLI error with machine-readable fields.
|
|
38
|
+
*
|
|
39
|
+
* Usage:
|
|
40
|
+
* throw new CLIError('No API key configured', {
|
|
41
|
+
* code: ErrorCode.AUTH_MISSING,
|
|
42
|
+
* category: 'auth',
|
|
43
|
+
* guidance: 'Run `pb login` to configure your API key.',
|
|
44
|
+
* });
|
|
45
|
+
*/
|
|
46
|
+
export class CLIError extends Error {
|
|
47
|
+
code;
|
|
48
|
+
category;
|
|
49
|
+
guidance;
|
|
50
|
+
constructor(message, options) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'CLIError';
|
|
53
|
+
this.code = options?.code ?? ErrorCode.INTERNAL;
|
|
54
|
+
this.category = options?.category ?? 'internal';
|
|
55
|
+
this.guidance = options?.guidance;
|
|
56
|
+
}
|
|
57
|
+
/** Serialize for JSON error output. */
|
|
58
|
+
toJSON() {
|
|
59
|
+
return {
|
|
60
|
+
error: this.message,
|
|
61
|
+
code: this.code,
|
|
62
|
+
category: this.category,
|
|
63
|
+
...(this.guidance ? { guidance: this.guidance } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,sEAAsE;AACtE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,OAAO;IACP,YAAY,EAAE,cAAc;IAC5B,YAAY,EAAE,cAAc;IAC5B,WAAW,EAAE,aAAa;IAC1B,UAAU;IACV,mBAAmB,EAAE,qBAAqB;IAC1C,eAAe,EAAE,iBAAiB;IAClC,SAAS;IACT,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,UAAU;IACV,gBAAgB,EAAE,kBAAkB;IACpC,aAAa;IACb,iBAAiB,EAAE,mBAAmB;IACtC,sBAAsB;IACtB,iBAAiB,EAAE,mBAAmB;IACtC,sBAAsB,EAAE,wBAAwB;IAChD,iBAAiB,EAAE,mBAAmB;IACtC,eAAe,EAAE,iBAAiB;IAClC,oBAAoB,EAAE,sBAAsB;IAC5C,cAAc;IACd,eAAe,EAAE,iBAAiB;IAClC,WAAW;IACX,QAAQ,EAAE,UAAU;CACZ,CAAC;AAIX;;;;;;;;;GASG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAiB;IACrB,QAAQ,CAAgB;IACxB,QAAQ,CAAU;IAE3B,YACE,OAAe,EACf,OAIC;QAED,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC;QAChD,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,UAAU,CAAC;QAChD,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IACpC,CAAC;IAED,uCAAuC;IACvC,MAAM;QACJ,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,OAAO;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared formatting utilities for the CLI.
|
|
3
|
+
* Single source of truth for display helpers used across commands.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Format an ISO timestamp into a human-friendly elapsed string.
|
|
7
|
+
* e.g. "just now", "5m ago", "3h ago", "2d ago"
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatElapsed(isoDate: string): string;
|
|
10
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAarD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared formatting utilities for the CLI.
|
|
3
|
+
* Single source of truth for display helpers used across commands.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Format an ISO timestamp into a human-friendly elapsed string.
|
|
7
|
+
* e.g. "just now", "5m ago", "3h ago", "2d ago"
|
|
8
|
+
*/
|
|
9
|
+
export function formatElapsed(isoDate) {
|
|
10
|
+
try {
|
|
11
|
+
const ms = Date.now() - new Date(isoDate).getTime();
|
|
12
|
+
const minutes = Math.floor(ms / 60000);
|
|
13
|
+
if (minutes < 1)
|
|
14
|
+
return 'just now';
|
|
15
|
+
if (minutes < 60)
|
|
16
|
+
return `${minutes}m ago`;
|
|
17
|
+
const hours = Math.floor(minutes / 60);
|
|
18
|
+
if (hours < 24)
|
|
19
|
+
return `${hours}h ago`;
|
|
20
|
+
const days = Math.floor(hours / 24);
|
|
21
|
+
return `${days}d ago`;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return 'unknown';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;QACvC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACpC,OAAO,GAAG,IAAI,OAAO,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* glossary.ts — Key CLI terms and their definitions.
|
|
3
|
+
*
|
|
4
|
+
* Provides a static glossary of Product Brain CLI terminology,
|
|
5
|
+
* plus a formatter for TTY output.
|
|
6
|
+
*
|
|
7
|
+
* WP-302 Slice 4.
|
|
8
|
+
*/
|
|
9
|
+
export interface GlossaryEntry {
|
|
10
|
+
term: string;
|
|
11
|
+
definition: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const GLOSSARY: GlossaryEntry[];
|
|
14
|
+
/**
|
|
15
|
+
* Format the glossary for TTY output.
|
|
16
|
+
* Returns a multi-line string with bold terms and dimmed definitions.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatGlossary(): string;
|
|
19
|
+
//# sourceMappingURL=glossary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.d.ts","sourceRoot":"","sources":["../../src/lib/glossary.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,QAAQ,EAAE,aAAa,EA6BnC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAUvC"}
|