@somewhere-tech/cli 0.22.1 → 0.23.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 (40) hide show
  1. package/README.md +16 -1
  2. package/dist/commands/api.js +8 -3
  3. package/dist/commands/api.js.map +1 -1
  4. package/dist/commands/check.js +9 -7
  5. package/dist/commands/check.js.map +1 -1
  6. package/dist/commands/deploy.js +261 -16
  7. package/dist/commands/deploy.js.map +1 -1
  8. package/dist/commands/docs.js +28 -5
  9. package/dist/commands/docs.js.map +1 -1
  10. package/dist/commands/env.js +0 -1
  11. package/dist/commands/env.js.map +1 -1
  12. package/dist/commands/init.js +81 -22
  13. package/dist/commands/init.js.map +1 -1
  14. package/dist/commands/logs.js +9 -6
  15. package/dist/commands/logs.js.map +1 -1
  16. package/dist/commands/project.js +71 -26
  17. package/dist/commands/project.js.map +1 -1
  18. package/dist/commands/promote.js +12 -4
  19. package/dist/commands/promote.js.map +1 -1
  20. package/dist/commands/pull.js +77 -15
  21. package/dist/commands/pull.js.map +1 -1
  22. package/dist/commands/rollback.js +12 -4
  23. package/dist/commands/rollback.js.map +1 -1
  24. package/dist/commands/status.js +2 -1
  25. package/dist/commands/status.js.map +1 -1
  26. package/dist/index.js +23 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/lib/client.js +3 -1
  29. package/dist/lib/client.js.map +1 -1
  30. package/dist/lib/config.js +39 -2
  31. package/dist/lib/config.js.map +1 -1
  32. package/dist/lib/files.js +124 -13
  33. package/dist/lib/files.js.map +1 -1
  34. package/dist/lib/output.js +15 -0
  35. package/dist/lib/output.js.map +1 -1
  36. package/dist/lib/typecheck.js +8 -2
  37. package/dist/lib/typecheck.js.map +1 -1
  38. package/dist/swpx/check.js +22 -0
  39. package/dist/swpx/check.js.map +1 -1
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -11,9 +11,14 @@ npm install -g @somewhere-tech/cli
11
11
  Or run directly:
12
12
 
13
13
  ```bash
14
- npx @somewhere-tech/cli init
14
+ npx -y -p @somewhere-tech/cli@latest somewhere init
15
15
  ```
16
16
 
17
+ The explicit `-p` form is required because this package intentionally ships
18
+ multiple executables (`somewhere`, `sw`, `swpx`, and `swpm`). The shorthand
19
+ `npx @somewhere-tech/cli ...` cannot choose between them. The equivalent npm
20
+ form is `npm exec --yes --package=@somewhere-tech/cli@latest -- somewhere init`.
21
+
17
22
  ## Quick start
18
23
 
19
24
  ```bash
@@ -43,6 +48,7 @@ After `somewhere init`, Claude Code and Codex auto-connect via the `.mcp.json` i
43
48
  | `somewhere deploy` | Deploy current directory to linked project |
44
49
  | `somewhere deploy --dry-run` | Preview the deploy diff without shipping |
45
50
  | `somewhere deploy --scope functions` | Deploy backend only (leave the site untouched) |
51
+ | `somewhere deploy --force` | Intentionally overwrite remote changes made since this machine last deployed |
46
52
  | `somewhere pull` | Download a project's deployed source + scaffold tsconfig/package.json for local typechecking |
47
53
  | `somewhere typecheck` | `tsc --noEmit` over a pulled tree — the "safe to deploy?" gate; catches a dropped import (TS2304) with file:line |
48
54
  | `somewhere logs` | Show recent logs |
@@ -146,6 +152,12 @@ After init, `claude "build me a booking app"` works immediately.
146
152
 
147
153
  Files under `functions/` (and root-level `api/` and `_lib/`) are deployed as server-side functions.
148
154
 
155
+ Files under `public/` deploy at the site root, matching Vite's convention: `public/images/logo.png` serves as `/images/logo.png`.
156
+
157
+ To exclude local-only files from deploy, add gitignore-style patterns to `.somewhereignore` in the project root. The CLI also respects the root `.gitignore`. `.somewhereignore` is applied after `.gitignore`, so it can add deploy-only excludes or `!` re-includes. Built-in safety excludes such as `node_modules`, `.git`, `.env`, `dist`, and dotfiles still apply.
158
+
159
+ After each successful linked deploy, promote, or pull, the CLI records the current deployed version in `.somewhere.json`. If the project changed elsewhere since that version, the next deploy refuses before overwriting anything and names the changed files. Run `somewhere pull` to bring remote source back locally, or `somewhere deploy --force --yes` to overwrite intentionally.
160
+
149
161
  ### Deploy options
150
162
 
151
163
  | Flag | What it does |
@@ -155,12 +167,15 @@ Files under `functions/` (and root-level `api/` and `_lib/`) are deployed as ser
155
167
  | `--dry-run` | Show what would change (added / modified / removed) without deploying |
156
168
  | `--replace-functions` | Drop deployed functions not present locally (repo-as-truth; default keeps them) |
157
169
  | `--project <id>` | Deploy to a specific project instead of the linked one |
170
+ | `--force` | Overwrite remote changes even when this machine has an older deployed version |
171
+ | `--yes` | Skip the `--force` confirmation prompt |
158
172
 
159
173
  After a successful deploy the CLI prints a **build log** — the entry chunk, each compiled chunk with its size, each function with its size, and any compiler warnings.
160
174
 
161
175
  ```bash
162
176
  somewhere deploy --dry-run # preview the diff first
163
177
  somewhere deploy --scope functions # ship a backend fix without touching the site
178
+ somewhere deploy --force --yes # overwrite remote edits intentionally
164
179
  ```
165
180
 
166
181
  ## Hot reload: `somewhere dev`
@@ -1,13 +1,18 @@
1
1
  import { ApiClient } from '../lib/client.js';
2
2
  import { getToken } from '../lib/config.js';
3
- import { error } from '../lib/output.js';
3
+ import { error, printJson } from '../lib/output.js';
4
4
  export function registerApi(program) {
5
5
  program
6
6
  .command('api <method> <path>')
7
7
  .description('Make a raw API call (adds auth automatically)')
8
8
  .option('-d, --data <json>', 'JSON body')
9
9
  .option('--raw', 'Print the response body as-is without JSON-parsing — for non-JSON endpoints (e.g. a SQL db dump); a 200 non-JSON body is not treated as an error')
10
+ .option('--json', 'Print parsed JSON (the default; accepted for automation consistency)')
10
11
  .action(async (method, path, opts) => {
12
+ if (opts.raw && opts.json) {
13
+ error('--raw and --json cannot be used together.');
14
+ process.exit(1);
15
+ }
11
16
  const client = new ApiClient(getToken());
12
17
  let body;
13
18
  if (opts.data) {
@@ -37,12 +42,12 @@ export function registerApi(program) {
37
42
  }
38
43
  try {
39
44
  const result = await client.call(method.toUpperCase(), apiPath, body);
40
- console.log(JSON.stringify(result, null, 2));
45
+ printJson(result);
41
46
  }
42
47
  catch (err) {
43
48
  if (err instanceof Error && 'code' in err) {
44
49
  const apiErr = err;
45
- console.error(JSON.stringify({ error: apiErr.code, message: apiErr.message, status: apiErr.statusCode }, null, 2));
50
+ printJson({ ok: false, error: apiErr.code, message: apiErr.message, status: apiErr.statusCode });
46
51
  }
47
52
  else {
48
53
  error(String(err));
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"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"}
@@ -101,9 +101,11 @@ export function registerCheck(program) {
101
101
  Object.keys(collected.functions).length +
102
102
  Object.keys(collected.binaryFiles).length;
103
103
  const isRun = opts.run !== undefined;
104
- const spinner = ora(isRun
105
- ? `Compiling ${totalFiles} files + running ${opts.run} (server-side)...`
106
- : `Dry-compiling ${totalFiles} files on the platform...`).start();
104
+ const spinner = opts.json
105
+ ? null
106
+ : ora(isRun
107
+ ? `Compiling ${totalFiles} files + running ${opts.run} (server-side)...`
108
+ : `Dry-compiling ${totalFiles} files on the platform...`).start();
107
109
  try {
108
110
  if (isRun) {
109
111
  const target = {
@@ -115,7 +117,7 @@ export function registerCheck(program) {
115
117
  if (opts.query !== undefined)
116
118
  target.query = opts.query;
117
119
  const r = await client.call('POST', '/deploy/check/run', buildCheckRunBody(collected, projectId, target), undefined, { timeoutMs: LONG_CALL_TIMEOUT_MS });
118
- spinner.stop();
120
+ spinner?.stop();
119
121
  if (opts.json) {
120
122
  console.log(JSON.stringify(r, null, 2));
121
123
  process.exit(r.ok === false || r.error ? 1 : 0);
@@ -132,7 +134,7 @@ export function registerCheck(program) {
132
134
  process.exit(r.error || (r.status ?? 0) >= 500 ? 1 : 0);
133
135
  }
134
136
  const r = await client.call('POST', '/deploy/check', buildCheckBody(collected, projectId), undefined, { timeoutMs: LONG_CALL_TIMEOUT_MS });
135
- spinner.stop();
137
+ spinner?.stop();
136
138
  if (opts.json) {
137
139
  console.log(JSON.stringify(r, null, 2));
138
140
  process.exit(r.ok === false ? 1 : 0);
@@ -156,11 +158,11 @@ export function registerCheck(program) {
156
158
  success(`Server-side check clean (real platform compiler) — safe to deploy. ${dim(`(${totalFiles} files, ${formatBytes(sourceBytes(collected))})`)}`);
157
159
  }
158
160
  catch (err) {
159
- spinner.fail(isRun ? 'Check run failed' : 'Check failed');
161
+ spinner?.fail(isRun ? 'Check run failed' : 'Check failed');
160
162
  // The server may answer a compile failure with a thrown BUILD_ERROR
161
163
  // (same payload as /deploy) instead of errors-as-data — render it the
162
164
  // same way, with a local code frame.
163
- if (isBuildError(err) && renderBuildError(err, targetDir)) {
165
+ if (!opts.json && isBuildError(err) && renderBuildError(err, targetDir)) {
164
166
  process.exit(1);
165
167
  }
166
168
  if (err instanceof CliApiError) {
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  import { basename, resolve } from 'node:path';
2
+ import prompts from 'prompts';
2
3
  import ora from '../lib/spinner.js';
3
4
  import { ApiClient, CliApiError, LONG_CALL_TIMEOUT_MS } from '../lib/client.js';
4
5
  import { isBuildError, renderBuildError } from '../lib/build-errors.js';
5
- import { getToken, loadConfig, loadProjectConfig, saveConfig, saveProjectConfig } from '../lib/config.js';
6
+ import { getToken, loadConfig, loadProjectConfigEntry, projectConfigMatchesRef, readProjectDeployState, saveConfig, saveProjectConfig, saveProjectDeployState, } from '../lib/config.js';
6
7
  import { collectFiles, formatBytes } from '../lib/files.js';
7
8
  import { mintTempAccount } from '../lib/temp-auth.js';
8
- import { dim, error, green, info, printJson, red, success, teal, warn, yellow } from '../lib/output.js';
9
+ import { dim, error, green, info, printJson, printJsonError, red, success, teal, warn, yellow } from '../lib/output.js';
9
10
  // Resolve the deploy target directory. `resolve` (not `join`) so an absolute
10
11
  // `dir` is honored as-is — `join(cwd, '/abs/path')` produced `/cwd/abs/path`
11
12
  // → ENOENT (tsk_c616fe5d). `resolve` also normalizes `..` segments.
@@ -35,6 +36,9 @@ const NEXT_CONFIG_PATTERN = /^next\.config\.(js|ts|mjs)$/;
35
36
  const NEXT_ROUTER_FILE_PATTERN = /^(?:src\/)?(?:app\/(?:.*\/)?(?:page|layout|route|loading|error|not-found)\.(?:js|jsx|ts|tsx|mdx)|pages\/.+\.(?:js|jsx|ts|tsx|mdx))$/;
36
37
  const NEXT_APP_WARNING = "somewhere.tech serves static files + serverless functions, not SSR — Next.js apps don't run here. " +
37
38
  'Port API routes to functions/ handlers, or start from a Vite React app; the platform compiles raw JSX/TSX on deploy.';
39
+ const DEPLOY_HEARTBEAT_MS = 30_000;
40
+ const DEPLOY_MAX_ATTEMPTS = 2;
41
+ const RETRYABLE_DEPLOY_CODES = new Set(['TIMEOUT', 'SERVER_SLOW', 'NETWORK_ERROR']);
38
42
  export function isNextAppShapeSignal(signal) {
39
43
  return signal.startsWith(`${NEXT_APP_SIGNAL_PREFIX} (`);
40
44
  }
@@ -117,6 +121,93 @@ export function formatRemainingTempTime(expiresAt, nowMs = Date.now()) {
117
121
  const minutes = totalMinutes % 60;
118
122
  return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
119
123
  }
124
+ function plural(count, singular, pluralWord = `${singular}s`) {
125
+ return `${count} ${count === 1 ? singular : pluralWord}`;
126
+ }
127
+ function formatElapsed(at, nowMs = Date.now()) {
128
+ if (!at)
129
+ return '';
130
+ const then = new Date(at).getTime();
131
+ if (!Number.isFinite(then))
132
+ return '';
133
+ const minutes = Math.max(0, Math.floor((nowMs - then) / 60_000));
134
+ if (minutes < 1)
135
+ return ' just now';
136
+ if (minutes < 60)
137
+ return ` ${plural(minutes, 'minute')} ago`;
138
+ const hours = Math.floor(minutes / 60);
139
+ if (hours < 24)
140
+ return ` ${plural(hours, 'hour')} ago`;
141
+ const days = Math.floor(hours / 24);
142
+ if (days < 30)
143
+ return ` ${plural(days, 'day')} ago`;
144
+ const months = Math.floor(days / 30);
145
+ return ` ${plural(months, 'month')} ago`;
146
+ }
147
+ function formatChangeSource(source) {
148
+ const normalized = source?.trim().toLowerCase();
149
+ if (!normalized)
150
+ return '';
151
+ if (['dashboard', 'dashboard-editor', 'editor', 'visual-editor'].includes(normalized)) {
152
+ return ' via the dashboard editor';
153
+ }
154
+ if (['cli', 'somewhere-cli', 'command-line'].includes(normalized))
155
+ return ' via the CLI';
156
+ if (['mcp', 'agent', 'mcp-agent', 'codex', 'claude'].includes(normalized))
157
+ return ' via an MCP agent';
158
+ if (['api', 'public-api', 'rest-api', 'worker', 'd1', 'system', 'internal', 'cron'].includes(normalized)) {
159
+ return ' via the platform';
160
+ }
161
+ return ' via the platform';
162
+ }
163
+ function readString(value) {
164
+ return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
165
+ }
166
+ function readStringList(value) {
167
+ if (!Array.isArray(value))
168
+ return [];
169
+ return value.filter((item) => typeof item === 'string' && item.length > 0);
170
+ }
171
+ export function readStaleBaseDetails(data) {
172
+ const current = data?.current_version;
173
+ const base = data?.base_version;
174
+ return {
175
+ current_version: typeof current === 'number' ? current : undefined,
176
+ base_version: typeof base === 'number' ? base : undefined,
177
+ changed_files: readStringList(data?.changed_files),
178
+ last_change_source: readString(data?.last_change_source),
179
+ last_change_at: readString(data?.last_change_at),
180
+ };
181
+ }
182
+ export function formatStaleBaseExplanation(details, nowMs = Date.now()) {
183
+ const files = details.changed_files;
184
+ const source = formatChangeSource(details.last_change_source);
185
+ const elapsed = formatElapsed(details.last_change_at, nowMs);
186
+ const fileList = files.slice(0, 10).join(', ');
187
+ const more = files.length > 10 ? `, and ${files.length - 10} more` : '';
188
+ const changeSummary = files.length > 0
189
+ ? `${plural(files.length, 'file')} edited${source}${elapsed}: ${fileList}${more}`
190
+ : `remote edits${source}${elapsed}`;
191
+ const versionSummary = details.current_version !== undefined && details.base_version !== undefined
192
+ ? `Remote is now v${details.current_version}; this machine last deployed v${details.base_version}.`
193
+ : null;
194
+ return [
195
+ `This project changed since your last deploy from this machine — ${changeSummary}. Your deploy was NOT applied.`,
196
+ versionSummary,
197
+ '',
198
+ 'Next steps:',
199
+ ' Run `somewhere pull` to bring the latest deployed source into this directory, review it, then deploy again.',
200
+ ' Run `somewhere deploy --force` to overwrite those remote changes intentionally.',
201
+ ].filter((line) => line !== null).join('\n');
202
+ }
203
+ function findProjectConfigEntry(targetDir) {
204
+ const targetEntry = loadProjectConfigEntry(targetDir);
205
+ if (targetEntry)
206
+ return targetEntry;
207
+ if (targetDir === process.cwd())
208
+ return null;
209
+ return loadProjectConfigEntry();
210
+ }
120
211
  function hasReusableTempCredential(config, nowMs = Date.now()) {
121
212
  if (!config?.token || !config.temporary)
122
213
  return false;
@@ -140,6 +231,8 @@ export function registerDeploy(program) {
140
231
  'for the bundled files. Use it only when you need full control of your own build.')
141
232
  .option('--allow-bundled', 'Alias for --prebuilt.')
142
233
  .option('--temporary', 'Deploy without an account — creates a temporary 3-hour workspace you can claim later')
234
+ .option('--force', 'Overwrite remote changes even when this machine last deployed an older version')
235
+ .option('--yes', 'Skip confirmation prompts (for --force)')
143
236
  .option('--json', 'Print the raw deploy response as JSON')
144
237
  .action(async (dir, opts) => {
145
238
  const targetDir = resolveTargetDir(dir);
@@ -229,11 +322,13 @@ export function registerDeploy(program) {
229
322
  }
230
323
  scope = opts.scope;
231
324
  }
325
+ const linkedProjectEntry = findProjectConfigEntry(targetDir);
326
+ let deployStateEntry = null;
232
327
  let projectId = opts.project;
233
328
  if (!projectId) {
234
- const projConfig = loadProjectConfig(targetDir) ?? loadProjectConfig();
235
- if (projConfig) {
236
- projectId = projConfig.project_id;
329
+ if (linkedProjectEntry) {
330
+ projectId = linkedProjectEntry.config.project_id;
331
+ deployStateEntry = linkedProjectEntry;
237
332
  }
238
333
  else if (tempSession) {
239
334
  // No `.somewhere.json` and no account to run `somewhere init` —
@@ -261,6 +356,36 @@ export function registerDeploy(program) {
261
356
  process.exit(1);
262
357
  }
263
358
  }
359
+ else if (linkedProjectEntry && projectConfigMatchesRef(linkedProjectEntry.config, projectId)) {
360
+ deployStateEntry = linkedProjectEntry;
361
+ }
362
+ if (opts.force && !opts.yes) {
363
+ if (!process.stdin.isTTY) {
364
+ const message = 'Refusing to force deploy without confirmation in a non-interactive shell. Run `somewhere deploy --force --yes` to overwrite remote changes intentionally.';
365
+ if (opts.json) {
366
+ printJsonError('CONFIRMATION_REQUIRED', message);
367
+ }
368
+ else {
369
+ error(message);
370
+ }
371
+ process.exit(1);
372
+ }
373
+ const { ok } = await prompts({
374
+ type: 'confirm',
375
+ name: 'ok',
376
+ message: `Overwrite remote changes for ${teal(projectId)}? This discards edits made outside this machine.`,
377
+ initial: false,
378
+ stdout: opts.json ? process.stderr : undefined,
379
+ });
380
+ if (!ok) {
381
+ if (opts.json) {
382
+ printJsonError('ABORTED', 'Aborted.');
383
+ process.exit(1);
384
+ }
385
+ warn('Aborted.');
386
+ process.exit(1);
387
+ }
388
+ }
264
389
  const spinner = opts.json ? null : ora('Collecting files...').start();
265
390
  const { files, binaryFiles, functions, skipped } = collectFiles(targetDir);
266
391
  // A deploy replaces the whole project, so a file we skip is DELETED from
@@ -334,9 +459,24 @@ export function registerDeploy(program) {
334
459
  const prebuilt = prebuiltOptIn(opts);
335
460
  if (prebuilt)
336
461
  body.allow_bundled = true;
462
+ const deployState = !tempSession && !opts.dryRun && deployStateEntry
463
+ ? readProjectDeployState(deployStateEntry.config, deployStateEntry.config.project_id)
464
+ : null;
465
+ if (deployState) {
466
+ body.base_version = deployState.last_deployed_version;
467
+ body.source = 'cli';
468
+ }
469
+ if (opts.force) {
470
+ body.force = true;
471
+ if (!tempSession)
472
+ body.source = 'cli';
473
+ }
337
474
  if (opts.dryRun) {
338
- const plan = await client.call('POST', '/deploy', body, undefined, {
339
- timeoutMs: LONG_CALL_TIMEOUT_MS,
475
+ const plan = await callDeployWithRetry(client, body, {
476
+ spinner,
477
+ json: Boolean(opts.json),
478
+ dryRun: true,
479
+ baseText: spinner?.text ?? 'Checking deploy...',
340
480
  });
341
481
  spinner?.stop();
342
482
  if (opts.json) {
@@ -347,15 +487,23 @@ export function registerDeploy(program) {
347
487
  }
348
488
  return;
349
489
  }
350
- const result = await client.call('POST', '/deploy', body, undefined, {
351
- timeoutMs: LONG_CALL_TIMEOUT_MS,
490
+ const result = await callDeployWithRetry(client, body, {
491
+ spinner,
492
+ json: Boolean(opts.json),
493
+ dryRun: false,
494
+ baseText: spinner?.text ?? 'Deploying...',
352
495
  });
353
496
  spinner?.stop();
497
+ const functionErrors = result.function_errors ?? [];
498
+ const hasFunctionErrors = functionErrors.length > 0;
354
499
  if (opts.json) {
355
500
  printJson(result);
356
- if (result.function_errors && result.function_errors.length > 0) {
501
+ if (hasFunctionErrors) {
357
502
  process.exit(1);
358
503
  }
504
+ if (!tempSession && typeof result.version === 'number' && deployStateEntry) {
505
+ saveProjectDeployState(deployStateEntry.dir, deployStateEntry.config.project_id, result.version);
506
+ }
359
507
  return;
360
508
  }
361
509
  const staticCount = typeof result.files === 'number'
@@ -392,16 +540,19 @@ export function registerDeploy(program) {
392
540
  }
393
541
  // Warnings + function errors must be loud — never let a "success"
394
542
  // line hide a partial failure (fail-loudly principle).
395
- if (result.function_errors && result.function_errors.length > 0) {
396
- for (const fe of result.function_errors) {
543
+ if (hasFunctionErrors) {
544
+ for (const fe of functionErrors) {
397
545
  const label = typeof fe === 'string' ? fe : (fe.route ?? JSON.stringify(fe));
398
546
  const detail = typeof fe === 'string' ? '' : fe.error ? ` — ${fe.error}` : '';
399
547
  error(`Function failed: ${label}${detail}`);
400
548
  }
401
549
  }
402
550
  if (result.warnings && result.warnings.length > 0) {
403
- for (const w of result.warnings)
404
- warn(w);
551
+ const buildWarnings = warningsInBuildLog(result.build_log);
552
+ for (const w of result.warnings) {
553
+ if (!buildWarnings.has(normalizeWarning(w)))
554
+ warn(w);
555
+ }
405
556
  }
406
557
  if (tempSession) {
407
558
  // Agent-relay success message (tsk_35674c33): every temp deploy,
@@ -439,17 +590,32 @@ export function registerDeploy(program) {
439
590
  }
440
591
  // Exit non-zero if any function failed to deploy — a CI step that
441
592
  // shells out to `somewhere deploy` should fail, not pass green.
442
- if (result.function_errors && result.function_errors.length > 0) {
593
+ if (hasFunctionErrors) {
443
594
  process.exit(1);
444
595
  }
596
+ if (!tempSession && typeof result.version === 'number' && deployStateEntry) {
597
+ saveProjectDeployState(deployStateEntry.dir, deployStateEntry.config.project_id, result.version);
598
+ }
445
599
  }
446
600
  catch (err) {
601
+ if (err instanceof CliApiError && err.code === 'STALE_BASE') {
602
+ spinner?.stop();
603
+ const details = readStaleBaseDetails(err.data);
604
+ const message = formatStaleBaseExplanation(details);
605
+ if (opts.json) {
606
+ printJson({ ok: false, error: 'STALE_BASE', message, ...(err.data ?? {}) });
607
+ }
608
+ else {
609
+ console.error(message);
610
+ }
611
+ process.exit(1);
612
+ }
447
613
  spinner?.fail(opts.dryRun ? 'Dry run failed' : 'Deploy failed');
448
614
  // Structured build failures get the full treatment: file:line
449
615
  // heading + a code frame rebuilt from the local source (we have the
450
616
  // files the server compiled — this is where the CLI beats a remote
451
617
  // log dump).
452
- if (isBuildError(err) && renderBuildError(err, targetDir)) {
618
+ if (!opts.json && isBuildError(err) && renderBuildError(err, targetDir)) {
453
619
  process.exit(1);
454
620
  }
455
621
  // Always show the error code + HTTP status — "Project not found"
@@ -465,6 +631,85 @@ export function registerDeploy(program) {
465
631
  }
466
632
  });
467
633
  }
634
+ function normalizeWarning(value) {
635
+ return value.replace(/^warning:\s*/i, '').trim();
636
+ }
637
+ function warningsInBuildLog(buildLog) {
638
+ const warnings = new Set();
639
+ for (const line of buildLog ?? []) {
640
+ if (/^warning:\s*/i.test(line.trim()))
641
+ warnings.add(normalizeWarning(line));
642
+ }
643
+ return warnings;
644
+ }
645
+ async function callDeployWithRetry(client, body, opts) {
646
+ for (let attempt = 1; attempt <= DEPLOY_MAX_ATTEMPTS; attempt++) {
647
+ const startedAt = Date.now();
648
+ const stopHeartbeat = startDeployHeartbeat(opts, attempt, startedAt);
649
+ try {
650
+ return await client.call('POST', '/deploy', body, undefined, {
651
+ timeoutMs: deployTimeoutMs(),
652
+ });
653
+ }
654
+ catch (err) {
655
+ if (attempt >= DEPLOY_MAX_ATTEMPTS || !isRetryableDeployError(err))
656
+ throw err;
657
+ if (!opts.json) {
658
+ opts.spinner?.stop();
659
+ warn(`${opts.dryRun ? 'Deploy check' : 'Deploy'} ${retryReason(err)} after ${formatDeployElapsed(Date.now() - startedAt)}; retrying once.`);
660
+ opts.spinner?.start(`${opts.baseText} (retry 2/2)`);
661
+ }
662
+ }
663
+ finally {
664
+ stopHeartbeat();
665
+ }
666
+ }
667
+ throw new CliApiError('DEPLOY_RETRY_EXHAUSTED', 'Deploy retry exhausted.', 0);
668
+ }
669
+ function deployTimeoutMs() {
670
+ const raw = process.env.SOMEWHERE_DEPLOY_TIMEOUT_MS;
671
+ if (!raw)
672
+ return LONG_CALL_TIMEOUT_MS;
673
+ const parsed = Number(raw);
674
+ return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : LONG_CALL_TIMEOUT_MS;
675
+ }
676
+ function isRetryableDeployError(err) {
677
+ return err instanceof CliApiError && RETRYABLE_DEPLOY_CODES.has(err.code);
678
+ }
679
+ function retryReason(err) {
680
+ if (!(err instanceof CliApiError))
681
+ return 'failed';
682
+ if (err.code === 'TIMEOUT')
683
+ return 'timed out';
684
+ if (err.code === 'SERVER_SLOW')
685
+ return 'stalled waiting for the server';
686
+ if (err.code === 'NETWORK_ERROR')
687
+ return 'lost the connection';
688
+ return 'failed';
689
+ }
690
+ function startDeployHeartbeat(opts, attempt, startedAt) {
691
+ if (opts.json)
692
+ return () => { };
693
+ const timer = setInterval(() => {
694
+ const elapsed = formatDeployElapsed(Date.now() - startedAt);
695
+ const retry = attempt > 1 ? ' (retry 2/2)' : '';
696
+ if (process.stderr.isTTY && opts.spinner) {
697
+ opts.spinner.text = `${opts.baseText}${retry} — still running after ${elapsed}`;
698
+ }
699
+ else {
700
+ console.error(`${opts.dryRun ? 'Deploy check' : 'Deploy'} still running after ${elapsed}${retry}...`);
701
+ }
702
+ }, DEPLOY_HEARTBEAT_MS);
703
+ return () => clearInterval(timer);
704
+ }
705
+ function formatDeployElapsed(ms) {
706
+ const totalSeconds = Math.max(1, Math.round(ms / 1000));
707
+ if (totalSeconds < 60)
708
+ return `${totalSeconds}s`;
709
+ const minutes = Math.floor(totalSeconds / 60);
710
+ const seconds = totalSeconds % 60;
711
+ return seconds === 0 ? `${minutes}m` : `${minutes}m ${seconds}s`;
712
+ }
468
713
  // Platform-generated slot artifacts. They live in the deployed slot but are
469
714
  // never part of a user's source dir (the CLI collector never emits them and
470
715
  // `somewhere pull` returns clean source), so the server's raw-vs-slot diff