@somewhere-tech/cli 0.31.17 → 0.31.18
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/dist/commands/browser.js +1 -1
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/check.js +1 -2
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.js +18 -383
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/status.js +0 -36
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/typecheck.js +1 -1
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/verify.js +1 -1
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/{local → lib}/browser-run.js +1 -1
- package/dist/lib/browser-run.js.map +1 -0
- package/dist/lib/chrome.js.map +1 -0
- package/dist/lib/envfile-write.js +2 -2
- package/dist/lib/envfile-write.js.map +1 -1
- package/dist/lib/frontend-dev.js +122 -0
- package/dist/lib/frontend-dev.js.map +1 -0
- package/dist/lib/init-agent-guide.js +15 -19
- package/dist/lib/init-agent-guide.js.map +1 -1
- package/dist/lib/init-green-template.js +1 -1
- package/dist/lib/project-urls.js +13 -0
- package/dist/lib/project-urls.js.map +1 -1
- package/npm-shrinkwrap.json +2 -17
- package/package.json +4 -6
- package/runtime/VENDOR.json +0 -2
- package/dist/commands/exec.js +0 -145
- package/dist/commands/exec.js.map +0 -1
- package/dist/local/browser-run.js.map +0 -1
- package/dist/local/chrome.js.map +0 -1
- package/dist/local/compiler-core.js +0 -51
- package/dist/local/compiler-core.js.map +0 -1
- package/dist/local/compiler.js +0 -683
- package/dist/local/compiler.js.map +0 -1
- package/dist/local/dev-server.js +0 -517
- package/dist/local/dev-server.js.map +0 -1
- package/dist/local/envfile.js +0 -40
- package/dist/local/envfile.js.map +0 -1
- package/dist/local/loader.js +0 -299
- package/dist/local/loader.js.map +0 -1
- package/dist/local/loopback.js +0 -129
- package/dist/local/loopback.js.map +0 -1
- package/dist/local/request-timing.js +0 -101
- package/dist/local/request-timing.js.map +0 -1
- package/dist/local/router.js +0 -114
- package/dist/local/router.js.map +0 -1
- package/dist/local/runtime.js +0 -345
- package/dist/local/runtime.js.map +0 -1
- package/dist/local/server.js +0 -309
- package/dist/local/server.js.map +0 -1
- package/dist/local/telemetry-filter.js +0 -120
- package/dist/local/telemetry-filter.js.map +0 -1
- package/node_modules/esbuild-wasm/LICENSE.md +0 -21
- package/node_modules/esbuild-wasm/README.md +0 -3
- package/node_modules/esbuild-wasm/bin/esbuild +0 -91
- package/node_modules/esbuild-wasm/esbuild.wasm +0 -0
- package/node_modules/esbuild-wasm/esm/browser.d.ts +0 -705
- package/node_modules/esbuild-wasm/esm/browser.js +0 -2393
- package/node_modules/esbuild-wasm/esm/browser.min.js +0 -20
- package/node_modules/esbuild-wasm/lib/browser.d.ts +0 -705
- package/node_modules/esbuild-wasm/lib/browser.js +0 -2438
- package/node_modules/esbuild-wasm/lib/browser.min.js +0 -22
- package/node_modules/esbuild-wasm/lib/main.d.ts +0 -705
- package/node_modules/esbuild-wasm/lib/main.js +0 -2051
- package/node_modules/esbuild-wasm/package.json +0 -19
- package/node_modules/esbuild-wasm/wasm_exec.js +0 -561
- package/node_modules/esbuild-wasm/wasm_exec_node.js +0 -39
- package/runtime/compiler/VENDOR.json +0 -64
- package/runtime/compiler/compile-core.cjs +0 -2007
- package/runtime/compiler/graph-contract.cjs +0 -124
- package/runtime/compiler/typed-functions.cjs +0 -575
- package/runtime/platform-context.mjs +0 -8193
- package/runtime/sw-init.mjs +0 -283
- /package/dist/{local → lib}/chrome.js +0 -0
package/dist/local/loader.js
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
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. Bare specifiers the project has not installed — `import { createClient }
|
|
13
|
-
* from '@somewhere-tech/sdk'` in api/data.ts. Deployed, the platform
|
|
14
|
-
* resolves it; locally, Node looks only in the project's node_modules, so a
|
|
15
|
-
* project that has never run `npm install` renders its frontend fine (the
|
|
16
|
-
* compiler resolves the app's dependencies into the CLI's cache) and then
|
|
17
|
-
* 500s on every function with ERR_MODULE_NOT_FOUND — the loop half-working
|
|
18
|
-
* in the most confusing possible way (tsk_3269026d). A bare specifier Node
|
|
19
|
-
* cannot find is retried against the SAME search path the compiler used, by
|
|
20
|
-
* re-resolving with a parentURL rooted in each cache dir so package
|
|
21
|
-
* `exports` maps and subpaths behave exactly as Node would. The project's
|
|
22
|
-
* own node_modules always wins; the cache is a fallback, never an override.
|
|
23
|
-
*
|
|
24
|
-
* 3. Hot reload — ESM has no cache invalidation, so every project-local file
|
|
25
|
-
* URL carries a ?gen=N query. Bumping the generation makes the next
|
|
26
|
-
* import() re-evaluate the whole project module graph; the hook propagates
|
|
27
|
-
* the parent's generation to children so nothing stale survives a save.
|
|
28
|
-
*
|
|
29
|
-
* TypeScript runs through Node's native type stripping (>= 22.18 / 23.6).
|
|
30
|
-
*/
|
|
31
|
-
import { registerHooks } from 'node:module';
|
|
32
|
-
import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
33
|
-
import { dirname, extname, resolve as resolvePath, sep } from 'node:path';
|
|
34
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
35
|
-
const EXT_CANDIDATES = ['.ts', '.tsx', '.mts', '.js', '.mjs', '.jsx'];
|
|
36
|
-
let generation = 1;
|
|
37
|
-
let installedRoot = null;
|
|
38
|
-
/** Extra dirs to resolve bare specifiers from, in order, after the project. */
|
|
39
|
-
let fallbackModuleDirs = [];
|
|
40
|
-
/** `"type"` from the PROJECT'S OWN package.json — see declaredFormat. */
|
|
41
|
-
let projectModuleType = null;
|
|
42
|
-
let projectModuleTypeRead = false;
|
|
43
|
-
/**
|
|
44
|
-
* The project's declared module type, read from the package.json AT THE
|
|
45
|
-
* PROJECT ROOT and nowhere else.
|
|
46
|
-
*
|
|
47
|
-
* Absent is not "look higher up" — it is the answer, and the default below
|
|
48
|
-
* applies. A project without a package.json of its own does not inherit one
|
|
49
|
-
* from whatever happens to sit above it on this machine.
|
|
50
|
-
*/
|
|
51
|
-
function readProjectModuleType() {
|
|
52
|
-
if (projectModuleTypeRead)
|
|
53
|
-
return projectModuleType;
|
|
54
|
-
projectModuleTypeRead = true;
|
|
55
|
-
projectModuleType = null;
|
|
56
|
-
if (!installedRoot)
|
|
57
|
-
return null;
|
|
58
|
-
try {
|
|
59
|
-
const parsed = JSON.parse(readFileSync(resolvePath(installedRoot, 'package.json'), 'utf8'));
|
|
60
|
-
if (parsed.type === 'module' || parsed.type === 'commonjs')
|
|
61
|
-
projectModuleType = parsed.type;
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// No package.json at the project root, or not readable JSON. Both mean
|
|
65
|
-
// "the project did not say", which the default handles.
|
|
66
|
-
}
|
|
67
|
-
return projectModuleType;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* The module format for a file inside the project, so Node never has to guess.
|
|
71
|
-
*
|
|
72
|
-
* Guessing is what caused the damage (pfb_c4aee81d756a): with no format
|
|
73
|
-
* declared, Node walks UP from the module looking for the nearest package.json,
|
|
74
|
-
* a walk with no upper bound, and then prints advice naming whatever it found —
|
|
75
|
-
* on a real machine, `/Users/<name>/package.json`. Telling a developer (or the
|
|
76
|
-
* coding agent driving them) to edit a file outside the project is not advice
|
|
77
|
-
* anyone should act on, and the walk that produced it had already left the
|
|
78
|
-
* project.
|
|
79
|
-
*
|
|
80
|
-
* Declaring the format ends the walk. `export default async function (req, sw)`
|
|
81
|
-
* is the platform's function contract, so ESM is the default here exactly as it
|
|
82
|
-
* is on deploy; an explicit `"type"` in the project's OWN package.json still
|
|
83
|
-
* wins, because that is the developer saying otherwise about their own project.
|
|
84
|
-
*/
|
|
85
|
-
/** Does this source parse as a CommonJS module body? ES module syntax and
|
|
86
|
-
* top-level await do not, which is precisely the question Node asks before it
|
|
87
|
-
* falls back to ESM — asked here without compiling or RUNNING anything. */
|
|
88
|
-
function parsesAsCommonJs(source) {
|
|
89
|
-
try {
|
|
90
|
-
// eslint-disable-next-line no-new-func
|
|
91
|
-
new Function(source);
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const ESM_SYNTAX = /^[ \t]*(?:import|export)\b/m;
|
|
99
|
-
const CJS_SYNTAX = /\bmodule\.exports\b|\bexports\.[A-Za-z_$]/;
|
|
100
|
-
export function declaredFormat(path, projectType, readSource) {
|
|
101
|
-
const ext = extname(path).toLowerCase();
|
|
102
|
-
// Node decides these from the extension alone — no package.json, no walk.
|
|
103
|
-
if (ext === '.mts')
|
|
104
|
-
return 'module-typescript';
|
|
105
|
-
if (ext === '.cts')
|
|
106
|
-
return 'commonjs-typescript';
|
|
107
|
-
if (ext === '.mjs')
|
|
108
|
-
return 'module';
|
|
109
|
-
if (ext === '.cjs')
|
|
110
|
-
return 'commonjs';
|
|
111
|
-
const ts = ext === '.ts' || ext === '.tsx';
|
|
112
|
-
if (!ts && ext !== '.js')
|
|
113
|
-
return null;
|
|
114
|
-
if (projectType) {
|
|
115
|
-
const cjs = projectType === 'commonjs';
|
|
116
|
-
return ts ? (cjs ? 'commonjs-typescript' : 'module-typescript') : (cjs ? 'commonjs' : 'module');
|
|
117
|
-
}
|
|
118
|
-
// The project did not say, so answer it the way Node would — from the source
|
|
119
|
-
// in front of us, never from a package.json above this project. A `.js`
|
|
120
|
-
// function written `module.exports = async function (req, sw)` deploys and
|
|
121
|
-
// runs today; guessing ESM for it would have broken it locally only.
|
|
122
|
-
let source;
|
|
123
|
-
try {
|
|
124
|
-
source = readSource();
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
if (parsesAsCommonJs(source))
|
|
130
|
-
return ts ? 'commonjs-typescript' : 'commonjs';
|
|
131
|
-
if (!ts)
|
|
132
|
-
return 'module';
|
|
133
|
-
// A `.ts` that failed the parse may have failed on its TYPE annotations
|
|
134
|
-
// rather than on module syntax, so the two syntaxes are looked for directly.
|
|
135
|
-
// The platform's function contract is `export default`, which is the tie-break.
|
|
136
|
-
if (ESM_SYNTAX.test(source))
|
|
137
|
-
return 'module-typescript';
|
|
138
|
-
if (CJS_SYNTAX.test(source))
|
|
139
|
-
return 'commonjs-typescript';
|
|
140
|
-
return 'module-typescript';
|
|
141
|
-
}
|
|
142
|
-
/** Is `filePath` inside the project this loader was installed for? */
|
|
143
|
-
function withinProject(filePath) {
|
|
144
|
-
if (!installedRoot)
|
|
145
|
-
return false;
|
|
146
|
-
return filePath === installedRoot || filePath.startsWith(installedRoot + sep);
|
|
147
|
-
}
|
|
148
|
-
export function bumpGeneration() {
|
|
149
|
-
return ++generation;
|
|
150
|
-
}
|
|
151
|
-
/** file:// URL for a project entry file, stamped with the current generation. */
|
|
152
|
-
export function entryUrl(absPath) {
|
|
153
|
-
return `${pathToFileURL(absPath).href}?gen=${generation}`;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Verify the running Node supports what the local runtime needs:
|
|
157
|
-
* module.registerHooks + unflagged TypeScript type stripping.
|
|
158
|
-
*/
|
|
159
|
-
export function assertNodeSupport() {
|
|
160
|
-
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
161
|
-
const ok = major >= 24 || (major === 23 && minor >= 6) || (major === 22 && minor >= 18);
|
|
162
|
-
if (!ok) {
|
|
163
|
-
throw new Error(`somewhere dev needs Node >= 22.18 (or >= 23.6) for TypeScript support and module hooks — you're on ${process.versions.node}. Upgrade Node and retry.`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
function isFile(p) {
|
|
167
|
-
try {
|
|
168
|
-
return existsSync(p) && statSync(p).isFile();
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function resolveWithExtensions(base) {
|
|
175
|
-
if (isFile(base))
|
|
176
|
-
return base;
|
|
177
|
-
for (const ext of EXT_CANDIDATES) {
|
|
178
|
-
if (isFile(base + ext))
|
|
179
|
-
return base + ext;
|
|
180
|
-
}
|
|
181
|
-
for (const ext of EXT_CANDIDATES) {
|
|
182
|
-
const idx = resolvePath(base, 'index' + ext);
|
|
183
|
-
if (isFile(idx))
|
|
184
|
-
return idx;
|
|
185
|
-
}
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Install the resolve hook for project files under `projectRoot`.
|
|
190
|
-
* Safe to call once per process; subsequent calls just update the root.
|
|
191
|
-
*/
|
|
192
|
-
/**
|
|
193
|
-
* Resolve symlinks. Node reports parentURL as a REAL path, so an installedRoot
|
|
194
|
-
* that still contains a symlink never prefix-matches it and the hook silently
|
|
195
|
-
* does nothing at all — no extensionless imports, no generation stamping, no
|
|
196
|
-
* dependency fallback. macOS makes this the DEFAULT for anything under /tmp
|
|
197
|
-
* (/tmp → /private/tmp, /var → /private/var), and a symlinked project
|
|
198
|
-
* directory does it anywhere.
|
|
199
|
-
*/
|
|
200
|
-
function realPath(p) {
|
|
201
|
-
try {
|
|
202
|
-
return realpathSync(p);
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
return p;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
export function installLoader(projectRoot, moduleDirs = []) {
|
|
209
|
-
const root = realPath(resolvePath(projectRoot));
|
|
210
|
-
// Each entry is a node_modules dir; resolve from its PARENT so Node performs
|
|
211
|
-
// its normal node_modules lookup there.
|
|
212
|
-
fallbackModuleDirs = moduleDirs.map((dir) => realPath(resolvePath(dir, '..')));
|
|
213
|
-
if (installedRoot !== root)
|
|
214
|
-
projectModuleTypeRead = false;
|
|
215
|
-
if (installedRoot !== null) {
|
|
216
|
-
installedRoot = root;
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
installedRoot = root;
|
|
220
|
-
registerHooks({
|
|
221
|
-
resolve(specifier, context, nextResolve) {
|
|
222
|
-
const parent = context.parentURL;
|
|
223
|
-
if (!installedRoot || !parent || !parent.startsWith('file://')) {
|
|
224
|
-
return nextResolve(specifier, context);
|
|
225
|
-
}
|
|
226
|
-
const isRelative = specifier.startsWith('./') || specifier.startsWith('../');
|
|
227
|
-
// A bare specifier: not relative, not root-anchored, not a URL scheme
|
|
228
|
-
// (node:, file:, data:, …).
|
|
229
|
-
const isBare = !isRelative
|
|
230
|
-
&& !specifier.startsWith('/')
|
|
231
|
-
&& !/^[a-z][a-z0-9+.-]*:/i.test(specifier);
|
|
232
|
-
if (!isRelative && !isBare)
|
|
233
|
-
return nextResolve(specifier, context);
|
|
234
|
-
const parentUrl = new URL(parent);
|
|
235
|
-
const parentPath = fileURLToPath(`file://${parentUrl.pathname}`);
|
|
236
|
-
if (!parentPath.startsWith(installedRoot)) {
|
|
237
|
-
return nextResolve(specifier, context);
|
|
238
|
-
}
|
|
239
|
-
if (isBare) {
|
|
240
|
-
try {
|
|
241
|
-
// The project's own node_modules first, always.
|
|
242
|
-
return nextResolve(specifier, context);
|
|
243
|
-
}
|
|
244
|
-
catch (err) {
|
|
245
|
-
if (err?.code !== 'ERR_MODULE_NOT_FOUND')
|
|
246
|
-
throw err;
|
|
247
|
-
for (const dir of fallbackModuleDirs) {
|
|
248
|
-
try {
|
|
249
|
-
return nextResolve(specifier, {
|
|
250
|
-
...context,
|
|
251
|
-
parentURL: pathToFileURL(resolvePath(dir, '__sw_resolve.js')).href,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
catch (fallbackErr) {
|
|
255
|
-
if (fallbackErr?.code !== 'ERR_MODULE_NOT_FOUND')
|
|
256
|
-
throw fallbackErr;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
throw err;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
const target = resolvePath(dirname(parentPath), specifier);
|
|
263
|
-
const found = resolveWithExtensions(target);
|
|
264
|
-
if (!found) {
|
|
265
|
-
// Let Node produce its standard (clear) ERR_MODULE_NOT_FOUND.
|
|
266
|
-
return nextResolve(specifier, context);
|
|
267
|
-
}
|
|
268
|
-
const gen = parentUrl.searchParams.get('gen');
|
|
269
|
-
const url = pathToFileURL(found).href + (gen ? `?gen=${gen}` : '');
|
|
270
|
-
return { url, shortCircuit: true };
|
|
271
|
-
},
|
|
272
|
-
/**
|
|
273
|
-
* Declare the format of every project module, so Node's own
|
|
274
|
-
* nearest-package.json walk never runs and never reports a file outside
|
|
275
|
-
* this project (pfb_c4aee81d756a). Only project files are touched:
|
|
276
|
-
* anything in node_modules, the CLI's own tree, or a URL Node has already
|
|
277
|
-
* classified passes straight through.
|
|
278
|
-
*/
|
|
279
|
-
load(url, context, nextLoad) {
|
|
280
|
-
if (context.format || !installedRoot || !url.startsWith('file:')) {
|
|
281
|
-
return nextLoad(url, context);
|
|
282
|
-
}
|
|
283
|
-
let filePath;
|
|
284
|
-
try {
|
|
285
|
-
const parsed = new URL(url);
|
|
286
|
-
filePath = realPath(fileURLToPath(`file://${parsed.pathname}`));
|
|
287
|
-
}
|
|
288
|
-
catch {
|
|
289
|
-
return nextLoad(url, context);
|
|
290
|
-
}
|
|
291
|
-
if (!withinProject(filePath) || filePath.includes(`${sep}node_modules${sep}`)) {
|
|
292
|
-
return nextLoad(url, context);
|
|
293
|
-
}
|
|
294
|
-
const format = declaredFormat(filePath, readProjectModuleType(), () => readFileSync(filePath, 'utf8'));
|
|
295
|
-
return format ? nextLoad(url, { ...context, format }) : nextLoad(url, context);
|
|
296
|
-
},
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
//# sourceMappingURL=loader.js.map
|
package/dist/local/loader.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/local/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtE,IAAI,UAAU,GAAG,CAAC,CAAC;AACnB,IAAI,aAAa,GAAkB,IAAI,CAAC;AACxC,+EAA+E;AAC/E,IAAI,kBAAkB,GAAa,EAAE,CAAC;AACtC,yEAAyE;AACzE,IAAI,iBAAiB,GAAiC,IAAI,CAAC;AAC3D,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAElC;;;;;;;GAOG;AACH,SAAS,qBAAqB;IAC5B,IAAI,qBAAqB;QAAE,OAAO,iBAAiB,CAAC;IACpD,qBAAqB,GAAG,IAAI,CAAC;IAC7B,iBAAiB,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,aAAa,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAEzF,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;YAAE,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC;IAC9F,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,wDAAwD;IAC1D,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH;;4EAE4E;AAC5E,SAAS,gBAAgB,CAAC,MAAc;IACtC,IAAI,CAAC;QACH,uCAAuC;QACvC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,GAAG,6BAA6B,CAAC;AACjD,MAAM,UAAU,GAAG,2CAA2C,CAAC;AAE/D,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,WAAyC,EACzC,UAAwB;IAExB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACxC,0EAA0E;IAC1E,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,mBAAmB,CAAC;IAC/C,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,qBAAqB,CAAC;IACjD,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC;IACpC,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IAEtC,MAAM,EAAE,GAAG,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC;IAC3C,IAAI,CAAC,EAAE,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,WAAW,KAAK,UAAU,CAAC;QACvC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClG,CAAC;IAED,6EAA6E;IAC7E,wEAAwE;IACxE,2EAA2E;IAC3E,qEAAqE;IACrE,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,EAAE,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7E,IAAI,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC;IACzB,wEAAwE;IACxE,6EAA6E;IAC7E,gFAAgF;IAChF,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACxD,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,qBAAqB,CAAC;IAC1D,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAC,QAAgB;IACrC,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,QAAQ,KAAK,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,UAAU,CAAC;AACtB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,QAAQ,UAAU,EAAE,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,KAAK,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;IACxF,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CACb,sGAAsG,OAAO,CAAC,QAAQ,CAAC,IAAI,2BAA2B,CACvJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,GAAG,GAAG,CAAC;IAC5C,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,aAAuB,EAAE;IAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;IAChD,6EAA6E;IAC7E,wCAAwC;IACxC,kBAAkB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,aAAa,KAAK,IAAI;QAAE,qBAAqB,GAAG,KAAK,CAAC;IAC1D,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,IAAI,CAAC;QACrB,OAAO;IACT,CAAC;IACD,aAAa,GAAG,IAAI,CAAC;IAErB,aAAa,CAAC;QACZ,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;YACjC,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/D,OAAO,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7E,sEAAsE;YACtE,4BAA4B;YAC5B,MAAM,MAAM,GAAG,CAAC,UAAU;mBACrB,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;mBAC1B,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,CAAC,UAAU,IAAI,CAAC,MAAM;gBAAE,OAAO,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAEnE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1C,OAAO,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC;oBACH,gDAAgD;oBAChD,OAAO,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACzC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAK,GAA6B,EAAE,IAAI,KAAK,sBAAsB;wBAAE,MAAM,GAAG,CAAC;oBAC/E,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;wBACrC,IAAI,CAAC;4BACH,OAAO,WAAW,CAAC,SAAS,EAAE;gCAC5B,GAAG,OAAO;gCACV,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI;6BACnE,CAAC,CAAC;wBACL,CAAC;wBAAC,OAAO,WAAW,EAAE,CAAC;4BACrB,IAAK,WAAqC,EAAE,IAAI,KAAK,sBAAsB;gCAAE,MAAM,WAAW,CAAC;wBACjG,CAAC;oBACH,CAAC;oBACD,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,8DAA8D;gBAC9D,OAAO,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YAED,MAAM,GAAG,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QACrC,CAAC;QAED;;;;;;WAMG;QACH,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ;YACzB,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjE,OAAO,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,QAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC5B,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAClE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,eAAe,GAAG,EAAE,CAAC,EAAE,CAAC;gBAC9E,OAAO,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,qBAAqB,EAAE,EAAE,GAAG,EAAE,CACpE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAC/B,CAAC;YACF,OAAO,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjF,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/local/loopback.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Serve on loopback — both families of it.
|
|
3
|
-
*
|
|
4
|
-
* These servers run the developer's functions with their real CLI token
|
|
5
|
-
* against their real project, so the listener must never leave loopback. But
|
|
6
|
-
* `127.0.0.1` alone is not loopback-complete: on a dual-stack machine
|
|
7
|
-
* `localhost` resolves to `::1` first, so a browser opening the URL the CLI
|
|
8
|
-
* prints got ERR_CONNECTION_REFUSED while every terminal check passed, because
|
|
9
|
-
* curl falls back to IPv4 (tsk_737ff0d2). The failure read as "the CLI is
|
|
10
|
-
* broken" and survived because the serving path was only ever checked with
|
|
11
|
-
* curl.
|
|
12
|
-
*
|
|
13
|
-
* One Node server binds one address, so this is two servers sharing one
|
|
14
|
-
* request handler. IPv4 is required; IPv6 is best-effort, because a machine
|
|
15
|
-
* with IPv6 disabled has no `::1` to bind and that is fine.
|
|
16
|
-
*/
|
|
17
|
-
import { execFile } from 'node:child_process';
|
|
18
|
-
import { createServer } from 'node:http';
|
|
19
|
-
import { promisify } from 'node:util';
|
|
20
|
-
const execFileAsync = promisify(execFile);
|
|
21
|
-
export class PortInUseError extends Error {
|
|
22
|
-
port;
|
|
23
|
-
owner;
|
|
24
|
-
constructor(port, owner) {
|
|
25
|
-
super(`Port ${port} is already in use${owner ? ` by ${owner}` : ''}. `
|
|
26
|
-
+ `Stop that process or choose another port with --port <n>.`);
|
|
27
|
-
this.port = port;
|
|
28
|
-
this.owner = owner;
|
|
29
|
-
this.name = 'PortInUseError';
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
async function canBind(port, host) {
|
|
33
|
-
const probe = createServer();
|
|
34
|
-
return new Promise((resolveProbe) => {
|
|
35
|
-
const finish = (result) => {
|
|
36
|
-
probe.removeAllListeners();
|
|
37
|
-
resolveProbe(result);
|
|
38
|
-
};
|
|
39
|
-
probe.once('error', (err) => {
|
|
40
|
-
finish(err.code === 'EADDRINUSE' ? 'busy' : 'unavailable');
|
|
41
|
-
});
|
|
42
|
-
probe.listen({ port, host, ipv6Only: host === '::1' }, () => {
|
|
43
|
-
probe.close(() => finish('yes'));
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
async function loopbackPortAvailable(port) {
|
|
48
|
-
const v4 = await canBind(port, '127.0.0.1');
|
|
49
|
-
if (v4 !== 'yes')
|
|
50
|
-
return false;
|
|
51
|
-
const v6 = await canBind(port, '::1');
|
|
52
|
-
// IPv6 is optional, but an existing IPv6 listener would receive requests
|
|
53
|
-
// from browsers that resolve localhost to ::1 before 127.0.0.1.
|
|
54
|
-
return v6 !== 'busy';
|
|
55
|
-
}
|
|
56
|
-
async function portOwner(port) {
|
|
57
|
-
try {
|
|
58
|
-
const { stdout } = await execFileAsync('lsof', ['-nP', `-iTCP:${port}`, '-sTCP:LISTEN', '-Fpc'], { timeout: 1500 });
|
|
59
|
-
let pid = '';
|
|
60
|
-
let command = '';
|
|
61
|
-
for (const line of stdout.split('\n')) {
|
|
62
|
-
if (!pid && line.startsWith('p'))
|
|
63
|
-
pid = line.slice(1).trim();
|
|
64
|
-
if (!command && line.startsWith('c'))
|
|
65
|
-
command = line.slice(1).trim();
|
|
66
|
-
}
|
|
67
|
-
if (!command)
|
|
68
|
-
return pid ? `PID ${pid}` : null;
|
|
69
|
-
return pid ? `${command} (PID ${pid})` : command;
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Resolve the port before compiler/project setup so a requested busy port
|
|
77
|
-
* fails immediately. An omitted port walks forward from 8787; an explicit
|
|
78
|
-
* --port is strict and never silently changes the developer's request.
|
|
79
|
-
*/
|
|
80
|
-
export async function chooseDevPort(requestedPort, defaultPort = 8787) {
|
|
81
|
-
if (requestedPort !== undefined) {
|
|
82
|
-
if (await loopbackPortAvailable(requestedPort))
|
|
83
|
-
return { port: requestedPort, movedFrom: null };
|
|
84
|
-
throw new PortInUseError(requestedPort, await portOwner(requestedPort));
|
|
85
|
-
}
|
|
86
|
-
for (let port = defaultPort; port <= 65535; port += 1) {
|
|
87
|
-
if (await loopbackPortAvailable(port)) {
|
|
88
|
-
return { port, movedFrom: port === defaultPort ? null : defaultPort };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
throw new Error(`No free local port was found from ${defaultPort} through 65535.`);
|
|
92
|
-
}
|
|
93
|
-
export async function serveLoopback(handler, port, onPortInUse) {
|
|
94
|
-
const servers = [];
|
|
95
|
-
const v4 = createServer(handler);
|
|
96
|
-
await new Promise((done, fail) => {
|
|
97
|
-
const onError = (err) => {
|
|
98
|
-
if (err.code === 'EADDRINUSE')
|
|
99
|
-
onPortInUse(port);
|
|
100
|
-
fail(err);
|
|
101
|
-
};
|
|
102
|
-
v4.once('error', onError);
|
|
103
|
-
v4.listen(port, '127.0.0.1', () => {
|
|
104
|
-
v4.off('error', onError);
|
|
105
|
-
done();
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
servers.push(v4);
|
|
109
|
-
// Best-effort. ipv6Only keeps this from colliding with the IPv4 listener on
|
|
110
|
-
// platforms where an unqualified ::1 bind would also claim 0.0.0.0.
|
|
111
|
-
const v6 = createServer(handler);
|
|
112
|
-
const ipv6 = await new Promise((done) => {
|
|
113
|
-
const onError = () => done(false);
|
|
114
|
-
v6.once('error', onError);
|
|
115
|
-
try {
|
|
116
|
-
v6.listen({ port, host: '::1', ipv6Only: true }, () => {
|
|
117
|
-
v6.off('error', onError);
|
|
118
|
-
done(true);
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
done(false);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
if (ipv6)
|
|
126
|
-
servers.push(v6);
|
|
127
|
-
return { servers, ipv6 };
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=loopback.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loopback.js","sourceRoot":"","sources":["../../src/local/loopback.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
const DATABASE_PATHS = new Set(['/v1/db/query', '/v1/db/batch', '/v1/db/raw-read']);
|
|
2
|
-
function record(value) {
|
|
3
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
4
|
-
? value
|
|
5
|
-
: null;
|
|
6
|
-
}
|
|
7
|
-
function responseData(payload) {
|
|
8
|
-
const root = record(payload);
|
|
9
|
-
return record(root?.data) ?? root;
|
|
10
|
-
}
|
|
11
|
-
function durationFromMeta(value) {
|
|
12
|
-
const duration = record(value)?.duration;
|
|
13
|
-
return typeof duration === 'number' && Number.isFinite(duration) && duration >= 0 ? duration : null;
|
|
14
|
-
}
|
|
15
|
-
/** Read the current database response contract: data.meta.duration for one
|
|
16
|
-
* query, or each data.results[].meta.duration for a batch. */
|
|
17
|
-
export function platformDatabaseDuration(payload) {
|
|
18
|
-
const data = responseData(payload);
|
|
19
|
-
const direct = durationFromMeta(data?.meta);
|
|
20
|
-
if (direct !== null)
|
|
21
|
-
return direct;
|
|
22
|
-
if (!Array.isArray(data?.results))
|
|
23
|
-
return null;
|
|
24
|
-
const durations = data.results.map((item) => durationFromMeta(record(item)?.meta));
|
|
25
|
-
if (!durations.length || durations.some((duration) => duration === null))
|
|
26
|
-
return null;
|
|
27
|
-
return durations.reduce((sum, duration) => sum + (duration ?? 0), 0);
|
|
28
|
-
}
|
|
29
|
-
function requestPath(input) {
|
|
30
|
-
try {
|
|
31
|
-
const url = typeof input === 'string' || input instanceof URL
|
|
32
|
-
? String(input)
|
|
33
|
-
: input.url;
|
|
34
|
-
return new URL(url).pathname;
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function roundedMs(startedAt) {
|
|
41
|
-
return Math.max(0, Math.round((performance.now() - startedAt) * 10) / 10);
|
|
42
|
-
}
|
|
43
|
-
/** One collector per incoming localhost request. It observes only database
|
|
44
|
-
* calls and never changes their request, response, retry, or failure behavior. */
|
|
45
|
-
export class LocalRequestTiming {
|
|
46
|
-
fetchImpl;
|
|
47
|
-
calls = [];
|
|
48
|
-
pending = [];
|
|
49
|
-
constructor(fetchImpl = globalThis.fetch) {
|
|
50
|
-
this.fetchImpl = fetchImpl;
|
|
51
|
-
}
|
|
52
|
-
fetch = async (input, init) => {
|
|
53
|
-
if (!DATABASE_PATHS.has(requestPath(input) ?? ''))
|
|
54
|
-
return this.fetchImpl(input, init);
|
|
55
|
-
const startedAt = performance.now();
|
|
56
|
-
let response;
|
|
57
|
-
try {
|
|
58
|
-
response = await this.fetchImpl(input, init);
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
this.calls.push({ totalMs: roundedMs(startedAt), platformMs: null });
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
const captured = response.clone().json()
|
|
65
|
-
.then((payload) => {
|
|
66
|
-
this.calls.push({
|
|
67
|
-
totalMs: roundedMs(startedAt),
|
|
68
|
-
platformMs: platformDatabaseDuration(payload),
|
|
69
|
-
});
|
|
70
|
-
})
|
|
71
|
-
.catch(() => {
|
|
72
|
-
this.calls.push({ totalMs: roundedMs(startedAt), platformMs: null });
|
|
73
|
-
});
|
|
74
|
-
this.pending.push(captured);
|
|
75
|
-
return response;
|
|
76
|
-
};
|
|
77
|
-
async finish() {
|
|
78
|
-
await Promise.all(this.pending);
|
|
79
|
-
if (!this.calls.length)
|
|
80
|
-
return null;
|
|
81
|
-
const reported = this.calls.filter((call) => call.platformMs !== null);
|
|
82
|
-
return {
|
|
83
|
-
calls: this.calls.length,
|
|
84
|
-
totalMs: Math.round(this.calls.reduce((sum, call) => sum + call.totalMs, 0) * 10) / 10,
|
|
85
|
-
platformMs: reported.length
|
|
86
|
-
? Math.round(reported.reduce((sum, call) => sum + (call.platformMs ?? 0), 0) * 1000) / 1000
|
|
87
|
-
: null,
|
|
88
|
-
platformReportedCalls: reported.length,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
export function formatDatabaseTiming(timing) {
|
|
93
|
-
if (!timing)
|
|
94
|
-
return '';
|
|
95
|
-
const calls = timing.calls === 1 ? '' : ` across ${timing.calls} calls`;
|
|
96
|
-
const platform = timing.platformMs === null
|
|
97
|
-
? 'platform timing not reported'
|
|
98
|
-
: `${timing.platformMs}ms platform-reported${timing.platformReportedCalls === timing.calls ? '' : ` for ${timing.platformReportedCalls}/${timing.calls} calls`}`;
|
|
99
|
-
return `database ${timing.totalMs}ms total${calls}, ${platform}`;
|
|
100
|
-
}
|
|
101
|
-
//# sourceMappingURL=request-timing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-timing.js","sourceRoot":"","sources":["../../src/local/request-timing.ts"],"names":[],"mappings":"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"}
|