@somewhere-tech/cli 0.12.3 → 0.12.6
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 +9 -1
- package/dist/commands/deploy.js +8 -2
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +47 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/env.js +51 -1
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/errors.js +65 -0
- package/dist/commands/errors.js.map +1 -0
- package/dist/commands/promote.js +22 -7
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/pull.js +35 -2
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/rollback.js +58 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/run.js +114 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/typecheck.js +58 -0
- package/dist/commands/typecheck.js.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/client.js +17 -1
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/envfile-write.js +24 -0
- package/dist/lib/envfile-write.js.map +1 -0
- package/dist/lib/scaffold.js +100 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/typecheck.js +127 -0
- package/dist/lib/typecheck.js.map +1 -0
- package/dist/local/server.js +5 -0
- package/dist/local/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import prompts from 'prompts';
|
|
3
|
+
import { ApiClient, CliApiError } from '../lib/client.js';
|
|
4
|
+
import { getToken, loadProjectConfig } from '../lib/config.js';
|
|
5
|
+
import { dim, error, info, success, teal, warn } from '../lib/output.js';
|
|
6
|
+
export function registerRollback(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('rollback [project]')
|
|
9
|
+
.description('Revert production to the previous deployed version. Use this when a ' +
|
|
10
|
+
'promote shipped a bad build — it restores the version that was live ' +
|
|
11
|
+
'before, including its functions. (Requires at least two promotes.)')
|
|
12
|
+
.option('-y, --yes', 'Skip the confirmation prompt')
|
|
13
|
+
.action(async (projectArg, opts) => {
|
|
14
|
+
const client = new ApiClient(getToken());
|
|
15
|
+
let projectId = projectArg;
|
|
16
|
+
if (!projectId) {
|
|
17
|
+
const config = loadProjectConfig();
|
|
18
|
+
if (!config) {
|
|
19
|
+
error('No project specified and no .somewhere.json found.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
projectId = config.project_id;
|
|
23
|
+
}
|
|
24
|
+
if (!opts.yes) {
|
|
25
|
+
const { ok } = await prompts({
|
|
26
|
+
type: 'confirm',
|
|
27
|
+
name: 'ok',
|
|
28
|
+
message: `Roll ${teal(projectId)} production back to the previous version?`,
|
|
29
|
+
initial: true,
|
|
30
|
+
});
|
|
31
|
+
if (!ok) {
|
|
32
|
+
warn('Aborted.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const spinner = ora('Rolling back...').start();
|
|
37
|
+
try {
|
|
38
|
+
const r = await client.call('POST', '/promote/rollback', {
|
|
39
|
+
project_id: projectId,
|
|
40
|
+
});
|
|
41
|
+
spinner.stop();
|
|
42
|
+
success(`Rolled back to v${r.version} (${r.files_restored} file${r.files_restored === 1 ? '' : 's'} restored)`);
|
|
43
|
+
if (r.message)
|
|
44
|
+
info(dim(`Version notes: ${r.message}`));
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
spinner.fail('Rollback failed');
|
|
48
|
+
if (err instanceof CliApiError) {
|
|
49
|
+
error(`${err.message} ${dim(`[${err.code}${err.statusCode ? `, HTTP ${err.statusCode}` : ''}]`)}`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
error(err instanceof Error ? err.message : String(err));
|
|
53
|
+
}
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=rollback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/commands/rollback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
3
|
+
import { ApiClient, CliApiError } from '../lib/client.js';
|
|
4
|
+
import { getToken, loadProjectConfig } from '../lib/config.js';
|
|
5
|
+
import { bold, dim, error, red, teal } from '../lib/output.js';
|
|
6
|
+
/** The runner clamps to [1, 30000]; default 10000 (mirrors run_code). */
|
|
7
|
+
const MAX_TIMEOUT_MS = 30_000;
|
|
8
|
+
export function registerRun(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('run <script>')
|
|
11
|
+
.description("Run a one-off script once against your project's live dev bindings " +
|
|
12
|
+
'(sw.db / sw.fs / sw.ai / sw.search …) without deploying, and print its ' +
|
|
13
|
+
'return value + console logs. The script is an ES module: ' +
|
|
14
|
+
'export default async function (sw) { ...; return value }. ' +
|
|
15
|
+
"Example: somewhere run seed.js")
|
|
16
|
+
.option('--project <id>', 'Project ID (defaults to the linked project)')
|
|
17
|
+
.option('--timeout <ms>', 'Abort the script after N ms (default 10000, max 30000)')
|
|
18
|
+
.option('--include-env', 'Expose the project env vars as sw.env (off by default)')
|
|
19
|
+
.option('--json', 'Print the raw { result, logs, duration_ms } envelope as JSON')
|
|
20
|
+
.action(async (script, opts) => {
|
|
21
|
+
const client = new ApiClient(getToken());
|
|
22
|
+
let projectId = opts.project;
|
|
23
|
+
if (!projectId) {
|
|
24
|
+
const config = loadProjectConfig();
|
|
25
|
+
if (!config) {
|
|
26
|
+
error('No project. Pass --project <id> or run from a linked directory.');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
projectId = config.project_id;
|
|
30
|
+
}
|
|
31
|
+
const absPath = isAbsolute(script) ? script : resolve(process.cwd(), script);
|
|
32
|
+
if (!existsSync(absPath)) {
|
|
33
|
+
error(`File not found: ${script}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const code = readFileSync(absPath, 'utf-8');
|
|
37
|
+
if (!code.trim()) {
|
|
38
|
+
error(`${script} is empty — nothing to run.`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
let timeoutMs;
|
|
42
|
+
if (opts.timeout !== undefined) {
|
|
43
|
+
timeoutMs = parseInt(String(opts.timeout), 10);
|
|
44
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
45
|
+
error('--timeout must be a positive number of milliseconds.');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
if (timeoutMs > MAX_TIMEOUT_MS)
|
|
49
|
+
timeoutMs = MAX_TIMEOUT_MS;
|
|
50
|
+
}
|
|
51
|
+
let r;
|
|
52
|
+
try {
|
|
53
|
+
r = await client.callRunner({
|
|
54
|
+
project_id: projectId,
|
|
55
|
+
code,
|
|
56
|
+
timeout_ms: timeoutMs,
|
|
57
|
+
include_env: opts.includeEnv === true,
|
|
58
|
+
},
|
|
59
|
+
// Give the network budget a little headroom over the runner's own
|
|
60
|
+
// 30s script cap so a slow run reports its real error, not a timeout.
|
|
61
|
+
{ timeoutMs: MAX_TIMEOUT_MS + 30_000 });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (err instanceof CliApiError) {
|
|
65
|
+
error(`${err.message} ${dim(`[${err.code}${err.statusCode ? `, HTTP ${err.statusCode}` : ''}]`)}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
error(err instanceof Error ? err.message : String(err));
|
|
69
|
+
}
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
if (opts.json) {
|
|
73
|
+
console.log(JSON.stringify(r, null, 2));
|
|
74
|
+
process.exit(r.error ? 1 : 0);
|
|
75
|
+
}
|
|
76
|
+
// Logs first (chronological context for the result), then the result.
|
|
77
|
+
const logs = r.logs ?? [];
|
|
78
|
+
if (logs.length) {
|
|
79
|
+
console.log(bold('Logs'));
|
|
80
|
+
for (const entry of logs) {
|
|
81
|
+
if (typeof entry === 'string') {
|
|
82
|
+
console.log(` ${dim(entry)}`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const level = entry.level ? dim(`[${entry.level}] `) : '';
|
|
86
|
+
console.log(` ${level}${entry.message ?? ''}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (r.logs_truncated)
|
|
90
|
+
console.log(` ${dim('… logs truncated')}`);
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
if (r.error) {
|
|
94
|
+
const e = r.error;
|
|
95
|
+
const msg = typeof e === 'string' ? e : `${e.name ? `${e.name}: ` : ''}${e.message ?? ''}`;
|
|
96
|
+
error(red(`Script threw: ${msg}`));
|
|
97
|
+
if (typeof e !== 'string' && e.stack)
|
|
98
|
+
console.error(dim(e.stack));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
console.log(bold('Result'));
|
|
102
|
+
try {
|
|
103
|
+
console.log(JSON.stringify(r.result, null, 2));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
console.log(String(r.result));
|
|
107
|
+
}
|
|
108
|
+
if (r.truncated)
|
|
109
|
+
console.log(dim(r.notice ?? 'Result truncated.'));
|
|
110
|
+
if (r.duration_ms !== undefined)
|
|
111
|
+
console.log(dim(`\n${teal('✓')} ran in ${r.duration_ms}ms`));
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { bold, dim, error, info, red, success, teal, warn } from '../lib/output.js';
|
|
5
|
+
import { runTypecheck } from '../lib/typecheck.js';
|
|
6
|
+
export function registerTypecheck(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('typecheck [dir]')
|
|
9
|
+
.description('Typecheck a pulled project with `tsc --noEmit` — the "is this safe to deploy?" gate. ' +
|
|
10
|
+
'Catches undefined symbols (a dropped import) and type errors with file:line BEFORE they 500 in production. ' +
|
|
11
|
+
'Run after `somewhere pull`, which scaffolds the tsconfig this uses.')
|
|
12
|
+
.action(async (dirArg) => {
|
|
13
|
+
const dir = resolve(process.cwd(), dirArg ?? '.');
|
|
14
|
+
if (!existsSync(join(dir, 'tsconfig.json'))) {
|
|
15
|
+
error('No tsconfig.json here to typecheck against.');
|
|
16
|
+
info(dim('Run `somewhere pull` in this directory first — it scaffolds the tsconfig + package.json that this gate needs.'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const spinner = ora('Typechecking (tsc --noEmit)...').start();
|
|
20
|
+
const result = await runTypecheck(dir);
|
|
21
|
+
spinner.stop();
|
|
22
|
+
reportTypecheck(result);
|
|
23
|
+
process.exit(result.ok ? 0 : 1);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Print a typecheck verdict. Shared so `dev --local`/`--check` render identically. */
|
|
27
|
+
export function reportTypecheck(result) {
|
|
28
|
+
if (result.spawnError) {
|
|
29
|
+
error(`Could not run the typechecker: ${result.spawnError}`);
|
|
30
|
+
info(dim('Install TypeScript (`npm i -D typescript`) or ensure `npx` is on PATH.'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (result.ok) {
|
|
34
|
+
success(`Typecheck clean ${dim(`(via ${result.via} tsc)`)} — safe to deploy.`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (result.errors.length === 0) {
|
|
38
|
+
// tsc failed but we couldn't parse structured diagnostics — show raw.
|
|
39
|
+
error('Typecheck failed.');
|
|
40
|
+
if (result.raw.trim())
|
|
41
|
+
console.error(result.raw.trim());
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const undefinedSymbols = result.errors.filter((e) => e.code === 'TS2304');
|
|
45
|
+
const n = result.errors.length;
|
|
46
|
+
error(`${bold(String(n))} type error${n === 1 ? '' : 's'} ${dim(`(via ${result.via} tsc)`)} — DO NOT deploy until fixed.`);
|
|
47
|
+
if (undefinedSymbols.length) {
|
|
48
|
+
warn(`${undefinedSymbols.length} undefined symbol${undefinedSymbols.length === 1 ? '' : 's'} (likely a dropped import) — exactly the bug that 500s production.`);
|
|
49
|
+
}
|
|
50
|
+
console.log('');
|
|
51
|
+
for (const e of result.errors) {
|
|
52
|
+
const loc = `${teal(e.file)}:${e.line}:${e.column}`;
|
|
53
|
+
const tag = e.code === 'TS2304' ? red(e.code) : dim(e.code);
|
|
54
|
+
console.log(` ${loc} ${tag} ${e.message}`);
|
|
55
|
+
}
|
|
56
|
+
console.log('');
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=typecheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typecheck.js","sourceRoot":"","sources":["../../src/commands/typecheck.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,14 @@ import { registerInit } from './commands/init.js';
|
|
|
7
7
|
import { registerProject } from './commands/project.js';
|
|
8
8
|
import { registerDeploy } from './commands/deploy.js';
|
|
9
9
|
import { registerPull } from './commands/pull.js';
|
|
10
|
+
import { registerTypecheck } from './commands/typecheck.js';
|
|
10
11
|
import { registerPromote } from './commands/promote.js';
|
|
12
|
+
import { registerRollback } from './commands/rollback.js';
|
|
11
13
|
import { registerDb } from './commands/db.js';
|
|
12
14
|
import { registerLogs } from './commands/logs.js';
|
|
15
|
+
import { registerErrors } from './commands/errors.js';
|
|
13
16
|
import { registerEnv } from './commands/env.js';
|
|
17
|
+
import { registerRun } from './commands/run.js';
|
|
14
18
|
import { registerStatus } from './commands/status.js';
|
|
15
19
|
import { registerOpen } from './commands/open.js';
|
|
16
20
|
import { registerDev } from './commands/dev.js';
|
|
@@ -27,10 +31,14 @@ registerInit(program);
|
|
|
27
31
|
registerProject(program);
|
|
28
32
|
registerDeploy(program);
|
|
29
33
|
registerPull(program);
|
|
34
|
+
registerTypecheck(program);
|
|
30
35
|
registerPromote(program);
|
|
36
|
+
registerRollback(program);
|
|
31
37
|
registerDb(program);
|
|
32
38
|
registerLogs(program);
|
|
39
|
+
registerErrors(program);
|
|
33
40
|
registerEnv(program);
|
|
41
|
+
registerRun(program);
|
|
34
42
|
registerStatus(program);
|
|
35
43
|
registerOpen(program);
|
|
36
44
|
registerDev(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACnE,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wBAAwB,CAAC;KACrC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACnE,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wBAAwB,CAAC;KACrC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAC3B,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/lib/client.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { Agent, fetch as undiciFetch } from 'undici';
|
|
2
2
|
const BASE_URL = 'https://api.somewhere.tech/v1';
|
|
3
|
+
/** The dedicated run_code runner worker (somewhere-tech-runner). `somewhere run`
|
|
4
|
+
* MUST hit this host, NOT the /v1 API: the runner is the request ROOT — it
|
|
5
|
+
* invokes the sandbox, the sandbox fetches the API worker as a LEAF, so there's
|
|
6
|
+
* no self-loop (CF returns 522 when a worker re-enters itself). There is
|
|
7
|
+
* deliberately no /v1/code/run proxy. The runner accepts the SAME `smt_`
|
|
8
|
+
* developer key the rest of the CLI uses. Override for staging via
|
|
9
|
+
* SOMEWHERE_RUNNER_URL. */
|
|
10
|
+
const RUNNER_BASE_URL = process.env.SOMEWHERE_RUNNER_URL?.replace(/\/$/, '') || 'https://runner.somewhere.tech';
|
|
3
11
|
/** Default request timeout. Long-running calls (deploy compiles, pulls)
|
|
4
12
|
* pass an explicit budget via opts.timeoutMs instead. */
|
|
5
13
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
@@ -11,8 +19,16 @@ export class ApiClient {
|
|
|
11
19
|
constructor(token) {
|
|
12
20
|
this.token = token;
|
|
13
21
|
}
|
|
22
|
+
/** Run a one-off script against the project's live DEV bindings via the
|
|
23
|
+
* dedicated runner worker. Same auth + `{ ok, data }` envelope as call(), but
|
|
24
|
+
* rooted at RUNNER_BASE_URL instead of the /v1 API (see that constant for the
|
|
25
|
+
* loop-protection reason). Body: { project_id, code, timeout_ms?, include_env? };
|
|
26
|
+
* resolves to { result, logs, duration_ms, error? }. */
|
|
27
|
+
async callRunner(body, opts) {
|
|
28
|
+
return this.call('POST', '/run', body, undefined, { ...opts, baseUrl: RUNNER_BASE_URL });
|
|
29
|
+
}
|
|
14
30
|
async call(method, path, body, query, opts) {
|
|
15
|
-
let url = `${BASE_URL}${path}`;
|
|
31
|
+
let url = `${opts?.baseUrl ?? BASE_URL}${path}`;
|
|
16
32
|
if (query) {
|
|
17
33
|
const params = new URLSearchParams();
|
|
18
34
|
for (const [k, v] of Object.entries(query)) {
|
package/dist/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD;0DAC0D;AAC1D,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC;8DAC8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,MAAM,CAAC;AAEhD,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAE9C,KAAK,CAAC,IAAI,CACR,MAAc,EACd,IAAY,EACZ,IAAc,EACd,KAAmD,EACnD,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD;;;;;;4BAM4B;AAC5B,MAAM,eAAe,GACnB,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,+BAA+B,CAAC;AAE1F;0DAC0D;AAC1D,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC;8DAC8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,MAAM,CAAC;AAEhD,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAE9C;;;;6DAIyD;IACzD,KAAK,CAAC,UAAU,CACd,IAAa,EACb,IAA6B;QAE7B,OAAO,IAAI,CAAC,IAAI,CAAI,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,KAAK,CAAC,IAAI,CACR,MAAc,EACd,IAAY,EACZ,IAAc,EACd,KAAmD,EACnD,IAA+C;QAE/C,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,OAAO,IAAI,QAAQ,GAAG,IAAI,EAAE,CAAC;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACrC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,KAAK,SAAS;oBAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC7B,IAAI,EAAE;gBAAE,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;YACrC,MAAM,EAAE,kBAAkB;SAC3B,CAAC;QAEF,IAAI,OAA2B,CAAC;QAChC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,kBAAkB,CAAC;QACxD,IAAI,GAA4C,CAAC;QACjD,IAAI,CAAC;YACH,2EAA2E;YAC3E,sEAAsE;YACtE,sEAAsE;YACtE,0EAA0E;YAC1E,sEAAsE;YACtE,iEAAiE;YACjE,GAAG,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;gBACtC,UAAU,EAAE,IAAI,KAAK,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;aAC7E,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,qEAAqE;YACrE,6DAA6D;YAC7D,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,CAAC;gBACvF,MAAM,IAAI,WAAW,CACnB,SAAS,EACT,oBAAoB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK;oBACxF,sGAAsG,EACxG,CAAC,CACF,CAAC;YACJ,CAAC;YACD,0DAA0D;YAC1D,wDAAwD;YACxD,+DAA+D;YAC/D,6DAA6D;YAC7D,0DAA0D;YAC1D,qCAAqC;YACrC,MAAM,KAAK,GAAI,GAAuD,CAAC,KAAK,CAAC;YAC7E,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC;YACzB,4EAA4E;YAC5E,yEAAyE;YACzE,4EAA4E;YAC5E,2EAA2E;YAC3E,qDAAqD;YACrD,IAAI,IAAI,KAAK,yBAAyB,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;gBAC1E,MAAM,IAAI,WAAW,CACnB,aAAa,EACb,GAAG,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,+DAA+D;oBAC3F,2FAA2F;oBAC3F,4EAA4E;oBAC5E,oEAAoE,EACtE,CAAC,CACF,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GACV,IAAI;gBACJ,KAAK,EAAE,OAAO;gBACd,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrD,MAAM,IAAI,WAAW,CACnB,eAAe,EACf,mBAAmB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,IAAI;gBAC5D,wFAAwF;gBACxF,qGAAqG,EACvG,CAAC,CACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,MAAsB,CAAC;QAE3B,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,WAAW,CACnB,kBAAkB,EAClB,sBAAsB,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAC1D,GAAG,CAAC,MAAM,CACX,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC;QAE3C,MAAM,OAAO,GAAG,MAKf,CAAC;QACF,MAAM,IAAI,WAAW,CACnB,OAAO,CAAC,KAAK,IAAI,SAAS,EAC1B,OAAO,CAAC,OAAO,IAAI,eAAe,EAClC,GAAG,CAAC,MAAM,EACV,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,CACb,CAAC;IACJ,CAAC;IAED;;;;qDAIiD;IACjD,KAAK,CAAC,OAAO,CACX,MAAc,EACd,IAAY,EACZ,IAAc,EACd,IAA6B;QAE7B,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;QACjC,MAAM,OAAO,GAA2B,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAClF,IAAI,OAA2B,CAAC;QAChC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,kBAAkB,CAAC;QACxD,IAAI,GAA4C,CAAC;QACjD,IAAI,CAAC;YACH,uEAAuE;YACvE,GAAG,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;gBACtC,UAAU,EAAE,IAAI,KAAK,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;aAC7E,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAI,GAAuD,CAAC,KAAK,CAAC;YAC7E,MAAM,MAAM,GAAG,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,OAAO,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACnG,MAAM,IAAI,WAAW,CACnB,eAAe,EACf,mBAAmB,MAAM,IAAI,GAAG,MAAM,MAAM,kCAAkC,EAC9E,CAAC,CACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9E,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,KAAK;IAElB;IAEA;IAEA;IACA;IANlB,YACkB,IAAY,EAC5B,OAAe,EACC,UAAkB;IAClC,+EAA+E;IAC/D,IAA8B,EAC9B,IAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAPC,SAAI,GAAJ,IAAI,CAAQ;QAEZ,eAAU,GAAV,UAAU,CAAQ;QAElB,SAAI,GAAJ,IAAI,CAA0B;QAC9B,SAAI,GAAJ,IAAI,CAAS;QAG7B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function buildEnvTemplate(keys, opts = {}) {
|
|
2
|
+
const header = [
|
|
3
|
+
'# Generated by `somewhere env pull`.',
|
|
4
|
+
'# These are the env vars your project expects. Values are NOT included —',
|
|
5
|
+
'# the platform never returns secret values. Fill them in below for local',
|
|
6
|
+
'# runs (somewhere dev --local / somewhere exec). This file is git/deploy',
|
|
7
|
+
'# ignored and never leaves your machine.',
|
|
8
|
+
];
|
|
9
|
+
if (opts.projectId)
|
|
10
|
+
header.push(`# project: ${opts.projectId}`);
|
|
11
|
+
const lines = [...header, ''];
|
|
12
|
+
// Preserve incoming order but keep keys with the same name once. The list
|
|
13
|
+
// endpoint already sorts by key_name, so the output is stable + diffable.
|
|
14
|
+
const seen = new Set();
|
|
15
|
+
for (const k of keys) {
|
|
16
|
+
if (!k.key || seen.has(k.key))
|
|
17
|
+
continue;
|
|
18
|
+
seen.add(k.key);
|
|
19
|
+
const scopeNote = k.scope && k.scope !== 'all' ? ` # scope: ${k.scope}` : '';
|
|
20
|
+
lines.push(`${k.key}=${scopeNote}`);
|
|
21
|
+
}
|
|
22
|
+
return lines.join('\n') + '\n';
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=envfile-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envfile-write.js","sourceRoot":"","sources":["../../src/lib/envfile-write.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,gBAAgB,CAAC,IAAc,EAAE,OAA+B,EAAE;IAChF,MAAM,MAAM,GAAG;QACb,sCAAsC;QACtC,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,0CAA0C;KAC3C,CAAC;IACF,IAAI,IAAI,CAAC,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAEhE,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,CAAC;IAE9B,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-typecheck scaffolding for a pulled project tree.
|
|
3
|
+
*
|
|
4
|
+
* `somewhere pull` brings down raw source but no tsconfig.json / package.json,
|
|
5
|
+
* so a local `tsc --noEmit` has nothing to run against — a dropped import
|
|
6
|
+
* (TS2304 "X is not defined") sails through and only 500s in production. This
|
|
7
|
+
* writes the two files a typecheck needs, lenient enough that untyped esm.sh
|
|
8
|
+
* deps don't drown the real "undefined symbol" signal:
|
|
9
|
+
* - skipLibCheck — don't typecheck dep .d.ts (and most deps ship none)
|
|
10
|
+
* - noImplicitAny: false — untyped imports become `any`, not errors
|
|
11
|
+
* - moduleResolution bundler + jsx react-jsx — match the deploy compiler
|
|
12
|
+
*
|
|
13
|
+
* Both files are written ONLY when absent. A project that ships its own
|
|
14
|
+
* tsconfig.json / package.json keeps it untouched.
|
|
15
|
+
*/
|
|
16
|
+
export const SCAFFOLD_TSCONFIG_FILENAME = 'tsconfig.json';
|
|
17
|
+
export const SCAFFOLD_PACKAGE_FILENAME = 'package.json';
|
|
18
|
+
/**
|
|
19
|
+
* The lenient tsconfig that catches undefined symbols (TS2304) without
|
|
20
|
+
* flagging every untyped dependency import. Returned as a pretty JSON string.
|
|
21
|
+
*/
|
|
22
|
+
export function buildScaffoldTsconfig() {
|
|
23
|
+
const config = {
|
|
24
|
+
// Written by `somewhere pull` so `tsc --noEmit` / `somewhere typecheck`
|
|
25
|
+
// can catch undefined symbols before deploy. Edit freely — it's yours now.
|
|
26
|
+
compilerOptions: {
|
|
27
|
+
target: 'ES2022',
|
|
28
|
+
module: 'ESNext',
|
|
29
|
+
moduleResolution: 'bundler',
|
|
30
|
+
lib: ['ES2022', 'DOM', 'DOM.Iterable'],
|
|
31
|
+
jsx: 'react-jsx',
|
|
32
|
+
strict: true,
|
|
33
|
+
// Lenient where untyped esm.sh deps would otherwise create noise that
|
|
34
|
+
// buries the real "undefined symbol" errors we care about.
|
|
35
|
+
noImplicitAny: false,
|
|
36
|
+
skipLibCheck: true,
|
|
37
|
+
allowJs: true,
|
|
38
|
+
checkJs: false,
|
|
39
|
+
esModuleInterop: true,
|
|
40
|
+
resolveJsonModule: true,
|
|
41
|
+
forceConsistentCasingInFileNames: true,
|
|
42
|
+
noEmit: true,
|
|
43
|
+
},
|
|
44
|
+
include: ['.'],
|
|
45
|
+
exclude: ['node_modules', 'dist', 'build'],
|
|
46
|
+
};
|
|
47
|
+
return JSON.stringify(config, null, 2) + '\n';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A minimal package.json carrying whatever deps we could recover. `deps` comes
|
|
51
|
+
* from a pulled package.json if the project shipped one; otherwise empty (the
|
|
52
|
+
* lenient tsconfig treats unresolved imports as `any`, so a typecheck still
|
|
53
|
+
* runs and still catches local undefined-symbol bugs).
|
|
54
|
+
*/
|
|
55
|
+
export function buildScaffoldPackageJson(projectName, deps) {
|
|
56
|
+
const pkg = {
|
|
57
|
+
name: sanitizePackageName(projectName),
|
|
58
|
+
private: true,
|
|
59
|
+
version: '0.0.0',
|
|
60
|
+
type: 'module',
|
|
61
|
+
// Scaffolded by `somewhere pull` for local typechecking. Your deployed
|
|
62
|
+
// dependency versions live on the platform; this mirrors them when known.
|
|
63
|
+
dependencies: deps,
|
|
64
|
+
};
|
|
65
|
+
return JSON.stringify(pkg, null, 2) + '\n';
|
|
66
|
+
}
|
|
67
|
+
/** npm package names: lowercase, no spaces, safe charset. */
|
|
68
|
+
export function sanitizePackageName(name) {
|
|
69
|
+
const cleaned = String(name || 'somewhere-project')
|
|
70
|
+
.toLowerCase()
|
|
71
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
72
|
+
.replace(/^[-_.]+|[-_.]+$/g, '');
|
|
73
|
+
return cleaned || 'somewhere-project';
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pull a `dependencies` map out of a pulled package.json's raw text, if one
|
|
77
|
+
* was in the project source. Returns {} on anything unparseable — the
|
|
78
|
+
* scaffold stays lenient by design, so a missing/garbled deps map is fine.
|
|
79
|
+
*/
|
|
80
|
+
export function extractDeps(packageJsonText) {
|
|
81
|
+
if (!packageJsonText)
|
|
82
|
+
return {};
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(packageJsonText);
|
|
85
|
+
const deps = parsed.dependencies;
|
|
86
|
+
if (deps && typeof deps === 'object') {
|
|
87
|
+
const out = {};
|
|
88
|
+
for (const [k, v] of Object.entries(deps)) {
|
|
89
|
+
if (typeof v === 'string')
|
|
90
|
+
out[k] = v;
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// unparseable — fall through to empty
|
|
97
|
+
}
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/lib/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAC1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,cAAc,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,MAAM,GAAG;QACb,wEAAwE;QACxE,2EAA2E;QAC3E,eAAe,EAAE;YACf,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,QAAQ;YAChB,gBAAgB,EAAE,SAAS;YAC3B,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC;YACtC,GAAG,EAAE,WAAW;YAChB,MAAM,EAAE,IAAI;YACZ,sEAAsE;YACtE,2DAA2D;YAC3D,aAAa,EAAE,KAAK;YACpB,YAAY,EAAE,IAAI;YAClB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,KAAK;YACd,eAAe,EAAE,IAAI;YACrB,iBAAiB,EAAE,IAAI;YACvB,gCAAgC,EAAE,IAAI;YACtC,MAAM,EAAE,IAAI;SACb;QACD,OAAO,EAAE,CAAC,GAAG,CAAC;QACd,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC;KAC3C,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAAmB,EACnB,IAA4B;IAE5B,MAAM,GAAG,GAAG;QACV,IAAI,EAAE,mBAAmB,CAAC,WAAW,CAAC;QACtC,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,QAAQ;QACd,uEAAuE;QACvE,0EAA0E;QAC1E,YAAY,EAAE,IAAI;KACnB,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC7C,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,mBAAmB,CAAC;SAChD,WAAW,EAAE;SACb,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,OAAO,IAAI,mBAAmB,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,eAAmC;IAC7D,IAAI,CAAC,eAAe;QAAE,OAAO,EAAE,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAExC,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;QACjC,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,GAAG,GAA2B,EAAE,CAAC;YACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "is this safe to deploy?" gate: run `tsc --noEmit` over a pulled tree
|
|
3
|
+
* and surface file:line errors — especially TS2304 ("X is not defined"), the
|
|
4
|
+
* dropped-import class that 500s production when nothing typechecks it.
|
|
5
|
+
*
|
|
6
|
+
* tsc resolution order (first that exists wins):
|
|
7
|
+
* 1. the project's own node_modules/.bin/tsc (if they ran `npm install`)
|
|
8
|
+
* 2. the typescript shipped with this CLI (always present — it's our build dep)
|
|
9
|
+
* 3. `npx -y typescript` as a last resort
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from 'node:child_process';
|
|
12
|
+
import { existsSync } from 'node:fs';
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
/**
|
|
17
|
+
* Diagnostics about bare npm imports that can't be resolved LOCALLY but resolve
|
|
18
|
+
* fine on deploy (esm.sh pins them from package.json). Reporting them would
|
|
19
|
+
* drown the real "undefined symbol" signal and falsely fail clean code, so they
|
|
20
|
+
* are dropped from the verdict:
|
|
21
|
+
* TS2307 Cannot find module 'X' or its corresponding type declarations
|
|
22
|
+
* TS7016 Could not find a declaration file for module 'X' (implicit any)
|
|
23
|
+
* TS2306 File is not a module
|
|
24
|
+
* This is intentional and bounded: TS2304 (undefined name — the dropped-import
|
|
25
|
+
* bug we're chasing) is NOT in this set and is always reported.
|
|
26
|
+
*/
|
|
27
|
+
const UNRESOLVED_DEP_CODES = new Set(['TS2307', 'TS7016', 'TS2306']);
|
|
28
|
+
/** Locate a runnable tsc. Never throws — npx is the always-available fallback. */
|
|
29
|
+
function resolveTsc(projectDir) {
|
|
30
|
+
const projectBin = join(projectDir, 'node_modules', '.bin', process.platform === 'win32' ? 'tsc.cmd' : 'tsc');
|
|
31
|
+
if (existsSync(projectBin)) {
|
|
32
|
+
return { command: projectBin, args: [], via: 'project' };
|
|
33
|
+
}
|
|
34
|
+
// The typescript bundled with this CLI. createRequire from this module
|
|
35
|
+
// resolves the dependency we declare in our own package.json.
|
|
36
|
+
try {
|
|
37
|
+
const require = createRequire(import.meta.url);
|
|
38
|
+
// typescript ships bin/tsc (a Node script). Resolve its package dir.
|
|
39
|
+
const tscBin = require.resolve('typescript/bin/tsc');
|
|
40
|
+
if (existsSync(tscBin)) {
|
|
41
|
+
return { command: process.execPath, args: [tscBin], via: 'bundled' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// not resolvable from here — fall through to npx
|
|
46
|
+
}
|
|
47
|
+
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
48
|
+
return { command: npx, args: ['-y', 'typescript', 'tsc'], via: 'npx' };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse tsc's default (non-pretty) diagnostic lines:
|
|
52
|
+
* path/to/file.ts(12,5): error TS2304: Cannot find name 'sanitizeForSpeech'.
|
|
53
|
+
*/
|
|
54
|
+
export function parseTscOutput(output) {
|
|
55
|
+
const errors = [];
|
|
56
|
+
const re = /^(.+?)\((\d+),(\d+)\): error (TS\d+): (.+)$/;
|
|
57
|
+
for (const line of output.split(/\r?\n/)) {
|
|
58
|
+
const m = re.exec(line.trim());
|
|
59
|
+
if (!m)
|
|
60
|
+
continue;
|
|
61
|
+
errors.push({
|
|
62
|
+
file: m[1],
|
|
63
|
+
line: Number(m[2]),
|
|
64
|
+
column: Number(m[3]),
|
|
65
|
+
code: m[4],
|
|
66
|
+
message: m[5],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return errors;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run a typecheck against `projectDir`. Assumes a tsconfig.json is present
|
|
73
|
+
* (pull scaffolds one); without it, tsc errors loudly and we surface that.
|
|
74
|
+
*/
|
|
75
|
+
export function runTypecheck(projectDir) {
|
|
76
|
+
const { command, args, via } = resolveTsc(projectDir);
|
|
77
|
+
// --pretty false → stable, parseable one-line diagnostics regardless of TTY.
|
|
78
|
+
const fullArgs = [...args, '--noEmit', '--pretty', 'false'];
|
|
79
|
+
return new Promise((resolve) => {
|
|
80
|
+
let child;
|
|
81
|
+
try {
|
|
82
|
+
child = spawn(command, fullArgs, {
|
|
83
|
+
cwd: projectDir,
|
|
84
|
+
env: process.env,
|
|
85
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
resolve({
|
|
90
|
+
ok: false,
|
|
91
|
+
errors: [],
|
|
92
|
+
via,
|
|
93
|
+
raw: '',
|
|
94
|
+
spawnError: err instanceof Error ? err.message : String(err),
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let out = '';
|
|
99
|
+
child.stdout?.on('data', (d) => (out += d.toString()));
|
|
100
|
+
child.stderr?.on('data', (d) => (out += d.toString()));
|
|
101
|
+
child.on('error', (err) => {
|
|
102
|
+
resolve({ ok: false, errors: [], via, raw: out, spawnError: err.message });
|
|
103
|
+
});
|
|
104
|
+
child.on('close', (code) => {
|
|
105
|
+
const allErrors = parseTscOutput(out);
|
|
106
|
+
// Drop locally-unresolvable bare-import diagnostics (they resolve on
|
|
107
|
+
// deploy via esm.sh) so they don't bury the real bugs. Undefined symbols
|
|
108
|
+
// (TS2304) survive the filter.
|
|
109
|
+
const errors = allErrors.filter((e) => !UNRESOLVED_DEP_CODES.has(e.code));
|
|
110
|
+
// tsc exits non-zero whenever it emits diagnostics. If it failed but we
|
|
111
|
+
// parsed NONE (a config/crash failure, not type errors), don't claim
|
|
112
|
+
// "clean" — surface it via raw output so the user sees something's wrong.
|
|
113
|
+
const unexplainedFailure = code !== 0 && allErrors.length === 0;
|
|
114
|
+
resolve({
|
|
115
|
+
ok: errors.length === 0 && !unexplainedFailure,
|
|
116
|
+
errors,
|
|
117
|
+
via,
|
|
118
|
+
raw: out,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/** Where this module lives — used by tests that need the CLI package root. */
|
|
124
|
+
export function cliPackageRoot() {
|
|
125
|
+
return join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=typecheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typecheck.js","sourceRoot":"","sources":["../../src/lib/typecheck.ts"],"names":[],"mappings":"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"}
|
package/dist/local/server.js
CHANGED
|
@@ -133,6 +133,11 @@ export function startLocalServer(state, opts) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
console.log(`${dim(stamp())} ${teal(rel)} ${dim('reloaded')}`);
|
|
136
|
+
if (opts.onReloadTypecheck) {
|
|
137
|
+
void Promise.resolve(opts.onReloadTypecheck()).catch((err) => {
|
|
138
|
+
console.error(red(`Typecheck failed to run: ${err instanceof Error ? err.message : String(err)}`));
|
|
139
|
+
});
|
|
140
|
+
}
|
|
136
141
|
}, 150);
|
|
137
142
|
};
|
|
138
143
|
const watcher = chokidar.watch(state.cwd, {
|