@somewhere-tech/cli 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/commands/auth.js +15 -7
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/deploy.js +25 -5
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +70 -4
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/exec.js +109 -0
- package/dist/commands/exec.js.map +1 -0
- package/dist/commands/mcp.js +266 -63
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/pull.js +8 -6
- package/dist/commands/pull.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/build-errors.js +147 -0
- package/dist/lib/build-errors.js.map +1 -0
- package/dist/lib/client.js +48 -4
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/config.js +34 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/local/envfile.js +40 -0
- package/dist/local/envfile.js.map +1 -0
- package/dist/local/loader.js +103 -0
- package/dist/local/loader.js.map +1 -0
- package/dist/local/router.js +114 -0
- package/dist/local/router.js.map +1 -0
- package/dist/local/runtime.js +268 -0
- package/dist/local/runtime.js.map +1 -0
- package/dist/local/server.js +169 -0
- package/dist/local/server.js.map +1 -0
- package/package.json +8 -4
- package/runtime/platform-context.mjs +3678 -0
- package/runtime/sw-init.mjs +237 -0
package/dist/lib/client.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
const BASE_URL = 'https://api.somewhere.tech/v1';
|
|
2
|
+
/** Default request timeout. Long-running calls (deploy compiles, pulls)
|
|
3
|
+
* pass an explicit budget via opts.timeoutMs instead. */
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
5
|
+
/** Budget for calls that run a real build server-side (npm install alone
|
|
6
|
+
* can take minutes): /deploy, /deploy/patch, pull/export. */
|
|
7
|
+
export const LONG_CALL_TIMEOUT_MS = 10 * 60_000;
|
|
2
8
|
export class ApiClient {
|
|
3
9
|
token;
|
|
4
10
|
constructor(token) {
|
|
5
11
|
this.token = token;
|
|
6
12
|
}
|
|
7
|
-
async call(method, path, body, query) {
|
|
13
|
+
async call(method, path, body, query, opts) {
|
|
8
14
|
let url = `${BASE_URL}${path}`;
|
|
9
15
|
if (query) {
|
|
10
16
|
const params = new URLSearchParams();
|
|
@@ -25,7 +31,38 @@ export class ApiClient {
|
|
|
25
31
|
headers['Content-Type'] = 'application/json';
|
|
26
32
|
reqBody = JSON.stringify(body);
|
|
27
33
|
}
|
|
28
|
-
const
|
|
34
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
35
|
+
let res;
|
|
36
|
+
try {
|
|
37
|
+
res = await fetch(url, {
|
|
38
|
+
method,
|
|
39
|
+
headers,
|
|
40
|
+
body: reqBody,
|
|
41
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
// AbortSignal.timeout fired — no bytes back within the budget. Name it
|
|
46
|
+
// so the user can tell a hang from a rejection (review F8/Q5: a bare
|
|
47
|
+
// fetch hung `somewhere deploy` forever on network silence).
|
|
48
|
+
if (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
|
|
49
|
+
throw new CliApiError('TIMEOUT', `No response from ${method} ${url.split('?')[0]} after ${Math.round(timeoutMs / 1000)}s. ` +
|
|
50
|
+
'The request may still be processing server-side — check `somewhere status` before retrying a deploy.', 0);
|
|
51
|
+
}
|
|
52
|
+
// Node's fetch rejects network-level failures with a bare
|
|
53
|
+
// "fetch failed" and buries the real reason (ENOTFOUND,
|
|
54
|
+
// ECONNRESET, UND_ERR_*) in err.cause. Surfacing only the bare
|
|
55
|
+
// message cost a customer an hour of guessing whether it was
|
|
56
|
+
// auth, payload, or network (pfb_70e9d140c5a0) — name the
|
|
57
|
+
// endpoint and the underlying cause.
|
|
58
|
+
const cause = err.cause;
|
|
59
|
+
const detail = cause?.code ??
|
|
60
|
+
cause?.message ??
|
|
61
|
+
(err instanceof Error ? err.message : String(err));
|
|
62
|
+
throw new CliApiError('NETWORK_ERROR', `Could not reach ${method} ${url.split('?')[0]} — ${detail}. ` +
|
|
63
|
+
'No HTTP response was received (this is a connection problem, not a server rejection). ' +
|
|
64
|
+
'Check your network and retry; for large deploys a flaky connection can drop the upload mid-request.', 0);
|
|
65
|
+
}
|
|
29
66
|
const text = await res.text();
|
|
30
67
|
let parsed;
|
|
31
68
|
try {
|
|
@@ -36,16 +73,23 @@ export class ApiClient {
|
|
|
36
73
|
}
|
|
37
74
|
if (parsed.ok === true)
|
|
38
75
|
return parsed.data;
|
|
39
|
-
|
|
76
|
+
const errBody = parsed;
|
|
77
|
+
throw new CliApiError(errBody.error ?? 'UNKNOWN', errBody.message ?? 'Unknown error', res.status, errBody.data, errBody.hint);
|
|
40
78
|
}
|
|
41
79
|
}
|
|
42
80
|
export class CliApiError extends Error {
|
|
43
81
|
code;
|
|
44
82
|
statusCode;
|
|
45
|
-
|
|
83
|
+
data;
|
|
84
|
+
hint;
|
|
85
|
+
constructor(code, message, statusCode,
|
|
86
|
+
/** Structured payload some errors carry (e.g. BUILD_ERROR file/line/frame). */
|
|
87
|
+
data, hint) {
|
|
46
88
|
super(message);
|
|
47
89
|
this.code = code;
|
|
48
90
|
this.statusCode = statusCode;
|
|
91
|
+
this.data = data;
|
|
92
|
+
this.hint = hint;
|
|
49
93
|
this.name = 'CliApiError';
|
|
50
94
|
}
|
|
51
95
|
}
|
package/dist/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD,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;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -94,4 +94,38 @@ export function hasGlobalMcpConfig() {
|
|
|
94
94
|
return false;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
const CURSOR_DIR = join(homedir(), '.cursor');
|
|
98
|
+
export const CURSOR_MCP_PATH = join(CURSOR_DIR, 'mcp.json');
|
|
99
|
+
/** Cursor gets the stdio bridge (`somewhere mcp`) rather than an embedded
|
|
100
|
+
* bearer token: the bridge reads ~/.somewhere/config.json at runtime, so a
|
|
101
|
+
* re-login never leaves a stale token behind in Cursor's config. */
|
|
102
|
+
export function saveCursorMcpConfig() {
|
|
103
|
+
let config = {};
|
|
104
|
+
if (existsSync(CURSOR_MCP_PATH)) {
|
|
105
|
+
try {
|
|
106
|
+
config = JSON.parse(readFileSync(CURSOR_MCP_PATH, 'utf-8'));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Malformed — preserve nothing, write fresh
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const servers = (config.mcpServers ?? {});
|
|
113
|
+
servers.somewhere = { command: 'somewhere', args: ['mcp'] };
|
|
114
|
+
config.mcpServers = servers;
|
|
115
|
+
if (!existsSync(CURSOR_DIR))
|
|
116
|
+
mkdirSync(CURSOR_DIR, { recursive: true });
|
|
117
|
+
writeFileSync(CURSOR_MCP_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
118
|
+
}
|
|
119
|
+
export function hasCursorMcpConfig() {
|
|
120
|
+
if (!existsSync(CURSOR_MCP_PATH))
|
|
121
|
+
return false;
|
|
122
|
+
try {
|
|
123
|
+
const config = JSON.parse(readFileSync(CURSOR_MCP_PATH, 'utf-8'));
|
|
124
|
+
const servers = config.mcpServers;
|
|
125
|
+
return !!servers?.somewhere;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
97
131
|
//# 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":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal .env parser for local dev. Values from .env / .env.local in the
|
|
3
|
+
* project root feed sw.env when running functions locally — these files are
|
|
4
|
+
* in the deploy IGNORE list, so nothing here ever leaves the machine.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
export function parseEnvFile(content) {
|
|
9
|
+
const out = {};
|
|
10
|
+
for (const rawLine of content.split('\n')) {
|
|
11
|
+
const line = rawLine.trim();
|
|
12
|
+
if (!line || line.startsWith('#'))
|
|
13
|
+
continue;
|
|
14
|
+
const eq = line.indexOf('=');
|
|
15
|
+
if (eq <= 0)
|
|
16
|
+
continue;
|
|
17
|
+
const key = line.slice(0, eq).trim().replace(/^export\s+/, '');
|
|
18
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
19
|
+
continue;
|
|
20
|
+
let value = line.slice(eq + 1).trim();
|
|
21
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
22
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
23
|
+
value = value.slice(1, -1);
|
|
24
|
+
}
|
|
25
|
+
out[key] = value;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/** Load .env then .env.local (local wins), from the project directory. */
|
|
30
|
+
export function loadLocalEnv(dir) {
|
|
31
|
+
const merged = {};
|
|
32
|
+
for (const name of ['.env', '.env.local']) {
|
|
33
|
+
const path = join(dir, name);
|
|
34
|
+
if (!existsSync(path))
|
|
35
|
+
continue;
|
|
36
|
+
Object.assign(merged, parseEnvFile(readFileSync(path, 'utf-8')));
|
|
37
|
+
}
|
|
38
|
+
return merged;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=envfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envfile.js","sourceRoot":"","sources":["../../src/local/envfile.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,IAAI,CAAC;YAAE,SAAS;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QACpD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module loading for the local function runtime.
|
|
3
|
+
*
|
|
4
|
+
* Two jobs the deployed runtime gets for free from the platform compiler:
|
|
5
|
+
*
|
|
6
|
+
* 1. Extensionless cross-file imports — `import { db } from '../_lib/db'`
|
|
7
|
+
* works deployed; Node ESM requires extensions. A resolve hook tries the
|
|
8
|
+
* same candidates the platform accepts (.ts/.tsx/.mts/.js/.mjs/.jsx and
|
|
9
|
+
* directory index files) for relative imports originating inside the
|
|
10
|
+
* project.
|
|
11
|
+
*
|
|
12
|
+
* 2. Hot reload — ESM has no cache invalidation, so every project-local file
|
|
13
|
+
* URL carries a ?gen=N query. Bumping the generation makes the next
|
|
14
|
+
* import() re-evaluate the whole project module graph; the hook propagates
|
|
15
|
+
* the parent's generation to children so nothing stale survives a save.
|
|
16
|
+
*
|
|
17
|
+
* TypeScript runs through Node's native type stripping (>= 22.18 / 23.6).
|
|
18
|
+
*/
|
|
19
|
+
import { registerHooks } from 'node:module';
|
|
20
|
+
import { existsSync, statSync } from 'node:fs';
|
|
21
|
+
import { dirname, resolve as resolvePath } from 'node:path';
|
|
22
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
23
|
+
const EXT_CANDIDATES = ['.ts', '.tsx', '.mts', '.js', '.mjs', '.jsx'];
|
|
24
|
+
let generation = 1;
|
|
25
|
+
let installedRoot = null;
|
|
26
|
+
export function bumpGeneration() {
|
|
27
|
+
return ++generation;
|
|
28
|
+
}
|
|
29
|
+
/** file:// URL for a project entry file, stamped with the current generation. */
|
|
30
|
+
export function entryUrl(absPath) {
|
|
31
|
+
return `${pathToFileURL(absPath).href}?gen=${generation}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Verify the running Node supports what the local runtime needs:
|
|
35
|
+
* module.registerHooks + unflagged TypeScript type stripping.
|
|
36
|
+
*/
|
|
37
|
+
export function assertNodeSupport() {
|
|
38
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
39
|
+
const ok = major >= 24 || (major === 23 && minor >= 6) || (major === 22 && minor >= 18);
|
|
40
|
+
if (!ok) {
|
|
41
|
+
throw new Error(`somewhere dev --local needs Node >= 22.18 (or >= 23.6) for TypeScript support and module hooks — you're on ${process.versions.node}. Upgrade Node and retry.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isFile(p) {
|
|
45
|
+
try {
|
|
46
|
+
return existsSync(p) && statSync(p).isFile();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function resolveWithExtensions(base) {
|
|
53
|
+
if (isFile(base))
|
|
54
|
+
return base;
|
|
55
|
+
for (const ext of EXT_CANDIDATES) {
|
|
56
|
+
if (isFile(base + ext))
|
|
57
|
+
return base + ext;
|
|
58
|
+
}
|
|
59
|
+
for (const ext of EXT_CANDIDATES) {
|
|
60
|
+
const idx = resolvePath(base, 'index' + ext);
|
|
61
|
+
if (isFile(idx))
|
|
62
|
+
return idx;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Install the resolve hook for project files under `projectRoot`.
|
|
68
|
+
* Safe to call once per process; subsequent calls just update the root.
|
|
69
|
+
*/
|
|
70
|
+
export function installLoader(projectRoot) {
|
|
71
|
+
const root = resolvePath(projectRoot);
|
|
72
|
+
if (installedRoot !== null) {
|
|
73
|
+
installedRoot = root;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
installedRoot = root;
|
|
77
|
+
registerHooks({
|
|
78
|
+
resolve(specifier, context, nextResolve) {
|
|
79
|
+
const parent = context.parentURL;
|
|
80
|
+
if (!installedRoot ||
|
|
81
|
+
!parent ||
|
|
82
|
+
!parent.startsWith('file://') ||
|
|
83
|
+
(!specifier.startsWith('./') && !specifier.startsWith('../'))) {
|
|
84
|
+
return nextResolve(specifier, context);
|
|
85
|
+
}
|
|
86
|
+
const parentUrl = new URL(parent);
|
|
87
|
+
const parentPath = fileURLToPath(`file://${parentUrl.pathname}`);
|
|
88
|
+
if (!parentPath.startsWith(installedRoot)) {
|
|
89
|
+
return nextResolve(specifier, context);
|
|
90
|
+
}
|
|
91
|
+
const target = resolvePath(dirname(parentPath), specifier);
|
|
92
|
+
const found = resolveWithExtensions(target);
|
|
93
|
+
if (!found) {
|
|
94
|
+
// Let Node produce its standard (clear) ERR_MODULE_NOT_FOUND.
|
|
95
|
+
return nextResolve(specifier, context);
|
|
96
|
+
}
|
|
97
|
+
const gen = parentUrl.searchParams.get('gen');
|
|
98
|
+
const url = pathToFileURL(found).href + (gen ? `?gen=${gen}` : '');
|
|
99
|
+
return { url, shortCircuit: true };
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/local/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based routing for the local function runtime — a faithful port of the
|
|
3
|
+
* deploy pipeline's route compiler + matcher (worker/src/utils/function-bundle.ts:
|
|
4
|
+
* compileRoutePattern / routeSpecificityKey / matchRoute), so a URL resolves to
|
|
5
|
+
* the same function locally as it does deployed.
|
|
6
|
+
*
|
|
7
|
+
* api/hello.ts → /api/hello (static)
|
|
8
|
+
* api/sites/[id].ts → /api/sites/:id (param)
|
|
9
|
+
* api/files/[...path].ts → /api/files/*path (catch-all)
|
|
10
|
+
* [...path].ts (root) → /*path (root catch-all)
|
|
11
|
+
*
|
|
12
|
+
* Static beats param beats rest. `_lib/` and plain root files are bundled for
|
|
13
|
+
* imports but never routed.
|
|
14
|
+
*/
|
|
15
|
+
export function compileRoutePattern(file) {
|
|
16
|
+
const noExt = file.replace(/\.(ts|tsx|mts|js|mjs|jsx)$/, '');
|
|
17
|
+
const parts = noExt.split('/');
|
|
18
|
+
const pattern = [];
|
|
19
|
+
const display = [];
|
|
20
|
+
parts.forEach((seg, i) => {
|
|
21
|
+
const rest = seg.match(/^\[\.\.\.([a-zA-Z_][a-zA-Z0-9_]*)\]$/);
|
|
22
|
+
if (rest) {
|
|
23
|
+
if (i !== parts.length - 1) {
|
|
24
|
+
throw new Error(`catch-all [...${rest[1]}] must be the last path segment: ${file}`);
|
|
25
|
+
}
|
|
26
|
+
pattern.push({ type: 'rest', value: rest[1] });
|
|
27
|
+
display.push(`*${rest[1]}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const param = seg.match(/^\[([a-zA-Z_][a-zA-Z0-9_]*)\]$/);
|
|
31
|
+
if (param) {
|
|
32
|
+
pattern.push({ type: 'param', value: param[1] });
|
|
33
|
+
display.push(`:${param[1]}`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (/[\[\]]/.test(seg)) {
|
|
37
|
+
throw new Error(`malformed parametric segment "${seg}" in ${file}. Use [name] or [...name].`);
|
|
38
|
+
}
|
|
39
|
+
pattern.push({ type: 'static', value: seg });
|
|
40
|
+
display.push(seg);
|
|
41
|
+
});
|
|
42
|
+
return { pattern, displayPath: '/' + display.join('/') };
|
|
43
|
+
}
|
|
44
|
+
function routeSpecificityKey(pattern) {
|
|
45
|
+
return pattern.map((s) => (s.type === 'static' ? '2' : s.type === 'param' ? '1' : '0')).join('');
|
|
46
|
+
}
|
|
47
|
+
function hasRestSegment(pattern) {
|
|
48
|
+
return pattern.some((s) => s.type === 'rest');
|
|
49
|
+
}
|
|
50
|
+
export function isRoutable(file) {
|
|
51
|
+
const isRootParametric = !file.includes('/') && /\[/.test(file);
|
|
52
|
+
return file.startsWith('api/') || isRootParametric;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Compile + sort routes most-specific first, mirroring buildFunctionBundle:
|
|
56
|
+
* non-rest beats rest; within a group, segment-wise static > param wins.
|
|
57
|
+
* Throws on two files compiling to the same route (same deploy-time error).
|
|
58
|
+
*/
|
|
59
|
+
export function compileRoutes(files) {
|
|
60
|
+
const routes = [];
|
|
61
|
+
for (const { file, absPath } of files) {
|
|
62
|
+
if (!isRoutable(file))
|
|
63
|
+
continue;
|
|
64
|
+
const { pattern, displayPath } = compileRoutePattern(file);
|
|
65
|
+
routes.push({ file, absPath, pattern, displayPath });
|
|
66
|
+
}
|
|
67
|
+
const seen = new Map();
|
|
68
|
+
for (const r of routes) {
|
|
69
|
+
const prior = seen.get(r.displayPath);
|
|
70
|
+
if (prior) {
|
|
71
|
+
throw new Error(`Two functions compile to the same route "${r.displayPath}": ${prior} and ${r.file}`);
|
|
72
|
+
}
|
|
73
|
+
seen.set(r.displayPath, r.file);
|
|
74
|
+
}
|
|
75
|
+
routes.sort((a, b) => {
|
|
76
|
+
const aRest = hasRestSegment(a.pattern);
|
|
77
|
+
const bRest = hasRestSegment(b.pattern);
|
|
78
|
+
if (aRest !== bRest)
|
|
79
|
+
return aRest ? 1 : -1;
|
|
80
|
+
const ka = routeSpecificityKey(a.pattern);
|
|
81
|
+
const kb = routeSpecificityKey(b.pattern);
|
|
82
|
+
return kb.localeCompare(ka);
|
|
83
|
+
});
|
|
84
|
+
return routes;
|
|
85
|
+
}
|
|
86
|
+
/** Walk routes in order and return the first match — port of the shim's matchRoute. */
|
|
87
|
+
export function matchRoute(routes, pathname) {
|
|
88
|
+
const urlSegs = pathname.split('/').filter(Boolean);
|
|
89
|
+
outer: for (const route of routes) {
|
|
90
|
+
const params = {};
|
|
91
|
+
const pat = route.pattern;
|
|
92
|
+
for (let i = 0; i < pat.length; i++) {
|
|
93
|
+
const p = pat[i];
|
|
94
|
+
if (p.type === 'rest') {
|
|
95
|
+
params[p.value] = urlSegs.slice(i).map(decodeURIComponent).join('/');
|
|
96
|
+
return { route, params };
|
|
97
|
+
}
|
|
98
|
+
if (i >= urlSegs.length)
|
|
99
|
+
continue outer;
|
|
100
|
+
if (p.type === 'static') {
|
|
101
|
+
if (urlSegs[i] !== p.value)
|
|
102
|
+
continue outer;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
params[p.value] = decodeURIComponent(urlSegs[i]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (pat.length === urlSegs.length) {
|
|
109
|
+
return { route, params };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/local/router.ts"],"names":[],"mappings":"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"}
|