@autter/runtime-cli 1.0.0 → 1.1.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 +13 -7
- package/dist/{build-BXFh_jbP.d.cts → build-CPXR9Xd3.d.cts} +27 -8
- package/dist/{build-BXFh_jbP.d.ts → build-CPXR9Xd3.d.ts} +27 -8
- package/dist/chunk-DQLLM2NT.js +1035 -0
- package/dist/{chunk-GGHHEUPQ.js → chunk-I2743JCN.js} +26 -8
- package/dist/cli.js +468 -59
- package/dist/index.cjs +547 -49
- package/dist/index.d.cts +57 -2
- package/dist/index.d.ts +57 -2
- package/dist/index.js +9 -1
- package/dist/next.cjs +634 -97
- package/dist/next.d.cts +3 -2
- package/dist/next.d.ts +3 -2
- package/dist/next.js +27 -8
- package/dist/vite.cjs +611 -88
- package/dist/vite.d.cts +3 -2
- package/dist/vite.d.ts +3 -2
- package/dist/vite.js +32 -6
- package/dist/webpack.cjs +604 -88
- package/dist/webpack.d.cts +11 -4
- package/dist/webpack.d.ts +11 -4
- package/dist/webpack.js +2 -2
- package/package.json +5 -1
- package/dist/chunk-SIRFO2QU.js +0 -524
package/dist/index.cjs
CHANGED
|
@@ -25,10 +25,14 @@ __export(src_exports, {
|
|
|
25
25
|
DEBUG_ID_REGISTRY: () => DEBUG_ID_REGISTRY,
|
|
26
26
|
DEFAULT_ENDPOINT: () => DEFAULT_ENDPOINT,
|
|
27
27
|
FatalUploadError: () => FatalUploadError,
|
|
28
|
+
MAX_MAP_CHARS: () => MAX_MAP_CHARS,
|
|
28
29
|
MAX_UPLOAD_BYTES: () => MAX_UPLOAD_BYTES,
|
|
29
30
|
RELEASE_ENV_VARS: () => RELEASE_ENV_VARS,
|
|
30
31
|
RELEASE_RE: () => RELEASE_RE,
|
|
32
|
+
SCOPES_KEY: () => SCOPES_KEY,
|
|
33
|
+
SCOPES_VERSION: () => SCOPES_VERSION,
|
|
31
34
|
SNIPPET_LINE_KEY: () => SNIPPET_LINE_KEY,
|
|
35
|
+
computeScopes: () => computeScopes,
|
|
32
36
|
debugIdFor: () => debugIdFor,
|
|
33
37
|
debugIdSnippet: () => debugIdSnippet,
|
|
34
38
|
findBundles: () => findBundles,
|
|
@@ -121,7 +125,7 @@ function mapPathFor(js, code) {
|
|
|
121
125
|
const sibling = `${js}.map`;
|
|
122
126
|
return (0, import_node_fs.existsSync)(sibling) ? sibling : null;
|
|
123
127
|
}
|
|
124
|
-
async function walk(dir, out) {
|
|
128
|
+
async function walk(dir, out, pattern = BUNDLE_RE) {
|
|
125
129
|
let entries;
|
|
126
130
|
try {
|
|
127
131
|
entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
|
|
@@ -131,10 +135,47 @@ async function walk(dir, out) {
|
|
|
131
135
|
for (const entry of entries) {
|
|
132
136
|
if (entry.name === "node_modules") continue;
|
|
133
137
|
const full = (0, import_node_path.join)(dir, entry.name);
|
|
134
|
-
if (entry.isDirectory()) await walk(full, out);
|
|
135
|
-
else if (entry.isFile() &&
|
|
138
|
+
if (entry.isDirectory()) await walk(full, out, pattern);
|
|
139
|
+
else if (entry.isFile() && pattern.test(entry.name)) out.push(full);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
142
|
+
var CSS_SOURCE_MAPPING_URL_RE = /\/\*[#@] sourceMappingURL=([^\s*]+)\s*\*\/\s*$/;
|
|
143
|
+
function pointsAt(file, url, map) {
|
|
144
|
+
if (!url || /^[a-z][\w+.-]*:/i.test(url) || url.startsWith("/")) return false;
|
|
145
|
+
let path = url.split(/[?#]/)[0];
|
|
146
|
+
try {
|
|
147
|
+
path = decodeURIComponent(path);
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
return (0, import_node_path.resolve)((0, import_node_path.dirname)(file), path) === map;
|
|
151
|
+
}
|
|
152
|
+
async function stripReference(file, map) {
|
|
153
|
+
let code;
|
|
154
|
+
try {
|
|
155
|
+
code = await (0, import_promises.readFile)(file, "utf8");
|
|
156
|
+
} catch {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
let stripped = code;
|
|
160
|
+
if (BUNDLE_RE.test(file)) {
|
|
161
|
+
if (pointsAt(file, readSourceMappingUrl(code), map)) stripped = stripSourceMappingUrl(code);
|
|
162
|
+
} else if (file.endsWith(".css")) {
|
|
163
|
+
const match = CSS_SOURCE_MAPPING_URL_RE.exec(code);
|
|
164
|
+
if (match && pointsAt(file, match[1], map)) stripped = code.slice(0, match.index).replace(/\n?$/, "\n");
|
|
165
|
+
}
|
|
166
|
+
if (stripped !== code) await (0, import_promises.writeFile)(file, stripped);
|
|
167
|
+
}
|
|
168
|
+
async function removeSourceMaps(maps, owners = /* @__PURE__ */ new Map()) {
|
|
169
|
+
const removed = [];
|
|
170
|
+
for (const map of [...new Set(maps)].sort()) {
|
|
171
|
+
if (!(0, import_node_fs.existsSync)(map)) continue;
|
|
172
|
+
await (0, import_promises.rm)(map, { force: true });
|
|
173
|
+
removed.push(map);
|
|
174
|
+
const owner = owners.get(map) ?? map.replace(/\.map$/, "");
|
|
175
|
+
await stripReference(owner, map);
|
|
176
|
+
}
|
|
177
|
+
return removed;
|
|
178
|
+
}
|
|
138
179
|
async function findBundles(dir, files) {
|
|
139
180
|
const root = (0, import_node_path.resolve)(dir);
|
|
140
181
|
const candidates = [];
|
|
@@ -260,6 +301,8 @@ async function injectDir(dir, options = {}) {
|
|
|
260
301
|
// src/upload.ts
|
|
261
302
|
var import_node_crypto2 = require("crypto");
|
|
262
303
|
var import_promises3 = require("fs/promises");
|
|
304
|
+
var import_node_util = require("util");
|
|
305
|
+
var import_node_zlib = require("zlib");
|
|
263
306
|
|
|
264
307
|
// src/release.ts
|
|
265
308
|
var import_node_child_process = require("child_process");
|
|
@@ -305,9 +348,382 @@ function resolveRelease(explicit, env = process.env, cwd = process.cwd()) {
|
|
|
305
348
|
);
|
|
306
349
|
}
|
|
307
350
|
|
|
351
|
+
// src/scopes.ts
|
|
352
|
+
var import_acorn = require("acorn");
|
|
353
|
+
var SCOPES_KEY = "x_autter_scopes";
|
|
354
|
+
var SCOPES_VERSION = 1;
|
|
355
|
+
var BASE_OPTIONS = {
|
|
356
|
+
ecmaVersion: "latest",
|
|
357
|
+
allowHashBang: true,
|
|
358
|
+
allowReturnOutsideFunction: true,
|
|
359
|
+
allowReserved: true
|
|
360
|
+
};
|
|
361
|
+
function parseBundle(code) {
|
|
362
|
+
try {
|
|
363
|
+
return (0, import_acorn.parse)(code, {
|
|
364
|
+
...BASE_OPTIONS,
|
|
365
|
+
sourceType: "module",
|
|
366
|
+
allowAwaitOutsideFunction: true,
|
|
367
|
+
allowImportExportEverywhere: true
|
|
368
|
+
});
|
|
369
|
+
} catch (moduleError) {
|
|
370
|
+
try {
|
|
371
|
+
return (0, import_acorn.parse)(code, { ...BASE_OPTIONS, sourceType: "script" });
|
|
372
|
+
} catch (scriptError) {
|
|
373
|
+
const pos = (err) => typeof err.pos === "number" ? err.pos : -1;
|
|
374
|
+
throw pos(scriptError) > pos(moduleError) ? scriptError : moduleError;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function isNode(value) {
|
|
379
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
380
|
+
}
|
|
381
|
+
var IDENTIFIER_NAME_RE = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u;
|
|
382
|
+
function identifierToken(node) {
|
|
383
|
+
if (!isNode(node)) return null;
|
|
384
|
+
if (node.type === "Identifier") return { offset: node.start, name: node.name, literal: false };
|
|
385
|
+
if (node.type === "PrivateIdentifier") return { offset: node.start, name: `#${node.name}`, literal: false };
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
function literalToken(node) {
|
|
389
|
+
if (!isNode(node) || node.type !== "Literal" || typeof node.value !== "string") return null;
|
|
390
|
+
return IDENTIFIER_NAME_RE.test(node.value) ? { offset: node.start, name: node.value, literal: true } : null;
|
|
391
|
+
}
|
|
392
|
+
function keyToken(property) {
|
|
393
|
+
if (!property.computed) {
|
|
394
|
+
const id = identifierToken(property.key);
|
|
395
|
+
if (id) return id;
|
|
396
|
+
}
|
|
397
|
+
return literalToken(property.key);
|
|
398
|
+
}
|
|
399
|
+
function bindingToken(target) {
|
|
400
|
+
if (!isNode(target)) return null;
|
|
401
|
+
if (target.type === "Identifier") return identifierToken(target);
|
|
402
|
+
if (target.type === "MemberExpression") {
|
|
403
|
+
return target.computed ? literalToken(target.property) : identifierToken(target.property);
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
function contextTokens(node, parent) {
|
|
408
|
+
let token = null;
|
|
409
|
+
switch (parent?.type) {
|
|
410
|
+
case "VariableDeclarator":
|
|
411
|
+
if (parent.init === node) token = bindingToken(parent.id);
|
|
412
|
+
break;
|
|
413
|
+
case "AssignmentExpression":
|
|
414
|
+
case "AssignmentPattern":
|
|
415
|
+
if (parent.right === node) token = bindingToken(parent.left);
|
|
416
|
+
break;
|
|
417
|
+
case "Property":
|
|
418
|
+
case "PropertyDefinition":
|
|
419
|
+
case "MethodDefinition":
|
|
420
|
+
if (parent.value === node) token = keyToken(parent);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
return token ? [token] : [];
|
|
424
|
+
}
|
|
425
|
+
function classTokens(path) {
|
|
426
|
+
if (!path || path.node.type !== "ClassDeclaration" && path.node.type !== "ClassExpression") return [];
|
|
427
|
+
const own = identifierToken(path.node.id);
|
|
428
|
+
return [...own ? [own] : [], ...contextTokens(path.node, path.parent?.node)];
|
|
429
|
+
}
|
|
430
|
+
function describe(path) {
|
|
431
|
+
const fn = path.node;
|
|
432
|
+
const parent = path.parent?.node;
|
|
433
|
+
const own = identifierToken(fn.id);
|
|
434
|
+
const isMethod = parent?.type === "MethodDefinition" || parent?.type === "Property" && parent.value === fn && (parent.method === true || parent.kind !== "init");
|
|
435
|
+
let context;
|
|
436
|
+
if (parent?.type === "MethodDefinition" && parent.kind === "constructor") {
|
|
437
|
+
context = classTokens(path.parent?.parent?.parent ?? null);
|
|
438
|
+
} else {
|
|
439
|
+
context = contextTokens(fn, parent);
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
start: fn.start,
|
|
443
|
+
end: fn.end,
|
|
444
|
+
own,
|
|
445
|
+
recoverAt: !own && fn.type !== "ArrowFunctionExpression" && !isMethod ? fn.start : null,
|
|
446
|
+
context
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
var FUNCTION_TYPES = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
|
|
450
|
+
function classInitializer(path) {
|
|
451
|
+
const node = path.node;
|
|
452
|
+
let range = null;
|
|
453
|
+
if (node.type === "StaticBlock") range = node;
|
|
454
|
+
else if (node.type === "PropertyDefinition" && isNode(node.value) && !FUNCTION_TYPES.has(node.value.type)) range = node.value;
|
|
455
|
+
if (!range) return null;
|
|
456
|
+
return { start: range.start, end: range.end, own: null, recoverAt: null, context: classTokens(path.parent?.parent ?? null) };
|
|
457
|
+
}
|
|
458
|
+
function collectFunctions(program) {
|
|
459
|
+
const found = [];
|
|
460
|
+
const stack = [{ node: program, parent: null }];
|
|
461
|
+
for (let path = stack.pop(); path; path = stack.pop()) {
|
|
462
|
+
const node = path.node;
|
|
463
|
+
if (FUNCTION_TYPES.has(node.type)) found.push(describe(path));
|
|
464
|
+
else {
|
|
465
|
+
const initializer = classInitializer(path);
|
|
466
|
+
if (initializer) found.push(initializer);
|
|
467
|
+
}
|
|
468
|
+
for (const key in node) {
|
|
469
|
+
const value = node[key];
|
|
470
|
+
if (Array.isArray(value)) {
|
|
471
|
+
for (let i = value.length - 1; i >= 0; i--) if (isNode(value[i])) stack.push({ node: value[i], parent: path });
|
|
472
|
+
} else if (isNode(value)) {
|
|
473
|
+
stack.push({ node: value, parent: path });
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return found;
|
|
478
|
+
}
|
|
479
|
+
function lineStarts(code) {
|
|
480
|
+
const starts = [0];
|
|
481
|
+
for (let i = 0; i < code.length; i++) {
|
|
482
|
+
const c = code.charCodeAt(i);
|
|
483
|
+
if (c === 10 || c === 8232 || c === 8233) starts.push(i + 1);
|
|
484
|
+
else if (c === 13) {
|
|
485
|
+
if (code.charCodeAt(i + 1) === 10) i++;
|
|
486
|
+
starts.push(i + 1);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return starts;
|
|
490
|
+
}
|
|
491
|
+
function positionOf(starts, offset) {
|
|
492
|
+
let lo = 0;
|
|
493
|
+
let hi = starts.length - 1;
|
|
494
|
+
while (lo < hi) {
|
|
495
|
+
const mid = lo + hi + 1 >> 1;
|
|
496
|
+
if (starts[mid] <= offset) lo = mid;
|
|
497
|
+
else hi = mid - 1;
|
|
498
|
+
}
|
|
499
|
+
return [lo, offset - starts[lo]];
|
|
500
|
+
}
|
|
501
|
+
var BASE64 = new Int8Array(128).fill(-1);
|
|
502
|
+
for (const [i, ch] of [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"].entries()) BASE64[ch.charCodeAt(0)] = i;
|
|
503
|
+
function findSegments(mappings, wanted) {
|
|
504
|
+
let line = 0;
|
|
505
|
+
let column = 0;
|
|
506
|
+
let source = 0;
|
|
507
|
+
let originalLine = 0;
|
|
508
|
+
let originalColumn = 0;
|
|
509
|
+
let name = 0;
|
|
510
|
+
let want = wanted.get(0);
|
|
511
|
+
const fields = [0, 0, 0, 0, 0];
|
|
512
|
+
let i = 0;
|
|
513
|
+
while (i < mappings.length) {
|
|
514
|
+
const ch = mappings.charCodeAt(i);
|
|
515
|
+
if (ch === 59) {
|
|
516
|
+
line++;
|
|
517
|
+
column = 0;
|
|
518
|
+
want = wanted.get(line);
|
|
519
|
+
i++;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (ch === 44) {
|
|
523
|
+
i++;
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
let count = 0;
|
|
527
|
+
while (i < mappings.length) {
|
|
528
|
+
const next = mappings.charCodeAt(i);
|
|
529
|
+
if (next === 44 || next === 59) break;
|
|
530
|
+
let value = 0;
|
|
531
|
+
let shift = 0;
|
|
532
|
+
let digit;
|
|
533
|
+
do {
|
|
534
|
+
const code = mappings.charCodeAt(i++);
|
|
535
|
+
digit = code < 128 ? BASE64[code] : -1;
|
|
536
|
+
if (digit < 0 || shift > 30) throw new Error("invalid mappings");
|
|
537
|
+
value |= (digit & 31) << shift;
|
|
538
|
+
shift += 5;
|
|
539
|
+
} while (digit & 32);
|
|
540
|
+
const decoded = value & 1 ? -(value >>> 1) : value >>> 1;
|
|
541
|
+
if (count < 5) fields[count] = decoded;
|
|
542
|
+
count++;
|
|
543
|
+
}
|
|
544
|
+
column += fields[0];
|
|
545
|
+
if (count >= 4) {
|
|
546
|
+
source += fields[1];
|
|
547
|
+
originalLine += fields[2];
|
|
548
|
+
originalColumn += fields[3];
|
|
549
|
+
}
|
|
550
|
+
if (count >= 5) name += fields[4];
|
|
551
|
+
if (want && want.get(column) === null) {
|
|
552
|
+
want.set(column, {
|
|
553
|
+
source: count >= 4 ? source : -1,
|
|
554
|
+
line: originalLine,
|
|
555
|
+
column: originalColumn,
|
|
556
|
+
name: count >= 5 ? name : -1
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function looksMangled(name) {
|
|
562
|
+
return name.replace(/^#/, "").length <= 2;
|
|
563
|
+
}
|
|
564
|
+
var IDENTIFIER_AT_RE = /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/uy;
|
|
565
|
+
var OWN_NAME_AT_RE = /(?:async\s+)?function\b\s*\*?\s*([$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*)/uy;
|
|
566
|
+
var NOT_A_NAME = new Set(
|
|
567
|
+
"abstract async await break case catch class const continue debugger declare default delete do else enum export extends false finally for function get if implements import in instanceof interface let new null of override package private protected public readonly return set static super switch this throw true try typeof var void while with yield".split(" ")
|
|
568
|
+
);
|
|
569
|
+
var NameResolver = class {
|
|
570
|
+
constructor(map, segmentAt) {
|
|
571
|
+
this.segmentAt = segmentAt;
|
|
572
|
+
this.names = Array.isArray(map.names) ? map.names : [];
|
|
573
|
+
this.sourcesContent = Array.isArray(map.sourcesContent) ? map.sourcesContent : [];
|
|
574
|
+
}
|
|
575
|
+
segmentAt;
|
|
576
|
+
names;
|
|
577
|
+
sourcesContent;
|
|
578
|
+
sourceLines = /* @__PURE__ */ new Map();
|
|
579
|
+
originalLine(segment) {
|
|
580
|
+
if (segment.source < 0) return null;
|
|
581
|
+
let lines = this.sourceLines.get(segment.source);
|
|
582
|
+
if (lines === void 0) {
|
|
583
|
+
const content = this.sourcesContent[segment.source];
|
|
584
|
+
lines = typeof content === "string" ? content.split(/\r\n|[\n\r\u2028\u2029]/) : null;
|
|
585
|
+
this.sourceLines.set(segment.source, lines);
|
|
586
|
+
}
|
|
587
|
+
return lines?.[segment.line] ?? null;
|
|
588
|
+
}
|
|
589
|
+
/** The original identifier at a segment's source position. */
|
|
590
|
+
identifierAt(segment, re, group = 0) {
|
|
591
|
+
const text = this.originalLine(segment);
|
|
592
|
+
if (text === null) return null;
|
|
593
|
+
re.lastIndex = segment.column;
|
|
594
|
+
const found = re.exec(text)?.[group];
|
|
595
|
+
return found && !NOT_A_NAME.has(found) ? found : null;
|
|
596
|
+
}
|
|
597
|
+
/** Original name of a token: the map's `names` at its exact position;
|
|
598
|
+
* else the generated name when it isn't mangled; else the identifier
|
|
599
|
+
* at the mapped position in `sourcesContent`. Null when unknown. */
|
|
600
|
+
resolve(token) {
|
|
601
|
+
if (token.literal) return token.name;
|
|
602
|
+
const segment = this.segmentAt(token.offset);
|
|
603
|
+
if (segment && segment.name >= 0) {
|
|
604
|
+
const name = this.names[segment.name];
|
|
605
|
+
if (typeof name === "string" && name) return name;
|
|
606
|
+
}
|
|
607
|
+
if (!looksMangled(token.name)) return token.name;
|
|
608
|
+
return segment ? this.identifierAt(segment, IDENTIFIER_AT_RE) : null;
|
|
609
|
+
}
|
|
610
|
+
/** The name a minifier removed from `function name() {}`, read from the
|
|
611
|
+
* original source at the function's mapped start. */
|
|
612
|
+
recover(offset) {
|
|
613
|
+
const segment = this.segmentAt(offset);
|
|
614
|
+
return segment ? this.identifierAt(segment, OWN_NAME_AT_RE, 1) : null;
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
var BASE64_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
618
|
+
function vlq(value) {
|
|
619
|
+
let rest = value < 0 ? -value << 1 | 1 : value << 1;
|
|
620
|
+
let out = "";
|
|
621
|
+
do {
|
|
622
|
+
let digit = rest & 31;
|
|
623
|
+
rest >>>= 5;
|
|
624
|
+
if (rest > 0) digit |= 32;
|
|
625
|
+
out += BASE64_DIGITS[digit];
|
|
626
|
+
} while (rest > 0);
|
|
627
|
+
return out;
|
|
628
|
+
}
|
|
629
|
+
function encodeScopes(entries) {
|
|
630
|
+
const parts = [];
|
|
631
|
+
let line = 0;
|
|
632
|
+
let previousStart = 0;
|
|
633
|
+
let previousName = 0;
|
|
634
|
+
let firstOnLine = true;
|
|
635
|
+
for (const [startLine, startColumn, endLine, endColumn, nameIndex] of entries) {
|
|
636
|
+
if (startLine > line) {
|
|
637
|
+
parts.push(";".repeat(startLine - line));
|
|
638
|
+
line = startLine;
|
|
639
|
+
previousStart = 0;
|
|
640
|
+
firstOnLine = true;
|
|
641
|
+
}
|
|
642
|
+
if (!firstOnLine) parts.push(",");
|
|
643
|
+
firstOnLine = false;
|
|
644
|
+
let segment = vlq(startColumn - previousStart) + vlq(endLine - startLine) + vlq(endLine === startLine ? endColumn - startColumn : endColumn);
|
|
645
|
+
previousStart = startColumn;
|
|
646
|
+
if (nameIndex >= 0) {
|
|
647
|
+
segment += vlq(nameIndex - previousName);
|
|
648
|
+
previousName = nameIndex;
|
|
649
|
+
}
|
|
650
|
+
parts.push(segment);
|
|
651
|
+
}
|
|
652
|
+
return parts.join("");
|
|
653
|
+
}
|
|
654
|
+
function computeScopes(code, map) {
|
|
655
|
+
try {
|
|
656
|
+
return scopesOf(code, map);
|
|
657
|
+
} catch (err) {
|
|
658
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
function scopesOf(code, map) {
|
|
662
|
+
if (typeof map.mappings !== "string") return { error: "the map has no mappings string" };
|
|
663
|
+
let functions;
|
|
664
|
+
try {
|
|
665
|
+
functions = collectFunctions(parseBundle(code));
|
|
666
|
+
} catch (err) {
|
|
667
|
+
return { error: `could not parse the bundle: ${err instanceof Error ? err.message : String(err)}` };
|
|
668
|
+
}
|
|
669
|
+
const starts = lineStarts(code);
|
|
670
|
+
const wanted = /* @__PURE__ */ new Map();
|
|
671
|
+
const want = (offset) => {
|
|
672
|
+
const [line, column] = positionOf(starts, offset);
|
|
673
|
+
let columns = wanted.get(line);
|
|
674
|
+
if (!columns) wanted.set(line, columns = /* @__PURE__ */ new Map());
|
|
675
|
+
columns.set(column, null);
|
|
676
|
+
};
|
|
677
|
+
for (const fn of functions) {
|
|
678
|
+
if (fn.own && !fn.own.literal) want(fn.own.offset);
|
|
679
|
+
if (fn.recoverAt !== null) want(fn.recoverAt);
|
|
680
|
+
for (const token of fn.context) if (!token.literal) want(token.offset);
|
|
681
|
+
}
|
|
682
|
+
try {
|
|
683
|
+
findSegments(map.mappings, wanted);
|
|
684
|
+
} catch (err) {
|
|
685
|
+
return { error: `could not read the map: ${err instanceof Error ? err.message : String(err)}` };
|
|
686
|
+
}
|
|
687
|
+
const resolver = new NameResolver(map, (offset) => {
|
|
688
|
+
const [line, column] = positionOf(starts, offset);
|
|
689
|
+
return wanted.get(line)?.get(column) ?? null;
|
|
690
|
+
});
|
|
691
|
+
functions.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
692
|
+
const mapNames = Array.isArray(map.names) ? map.names : [];
|
|
693
|
+
const nameIndex = /* @__PURE__ */ new Map();
|
|
694
|
+
mapNames.forEach((name, index) => {
|
|
695
|
+
if (typeof name === "string" && !nameIndex.has(name)) nameIndex.set(name, index);
|
|
696
|
+
});
|
|
697
|
+
const extraNames = [];
|
|
698
|
+
const indexOf = (name) => {
|
|
699
|
+
let index = nameIndex.get(name);
|
|
700
|
+
if (index === void 0) {
|
|
701
|
+
index = mapNames.length + extraNames.push(name) - 1;
|
|
702
|
+
nameIndex.set(name, index);
|
|
703
|
+
}
|
|
704
|
+
return index;
|
|
705
|
+
};
|
|
706
|
+
const entries = functions.map((fn) => {
|
|
707
|
+
let name = fn.own ? resolver.resolve(fn.own) : null;
|
|
708
|
+
if (name === null && fn.recoverAt !== null) name = resolver.recover(fn.recoverAt);
|
|
709
|
+
for (const token of fn.context) {
|
|
710
|
+
if (name !== null) break;
|
|
711
|
+
name = resolver.resolve(token);
|
|
712
|
+
}
|
|
713
|
+
const index = name !== null ? indexOf(name) : fn.own || fn.context.length > 0 ? indexOf(null) : -1;
|
|
714
|
+
const [startLine, startColumn] = positionOf(starts, fn.start);
|
|
715
|
+
const [endLine, endColumn] = positionOf(starts, fn.end);
|
|
716
|
+
return [startLine, startColumn, endLine, endColumn, index];
|
|
717
|
+
});
|
|
718
|
+
return { scopes: { version: SCOPES_VERSION, names: extraNames, scopes: encodeScopes(entries) } };
|
|
719
|
+
}
|
|
720
|
+
|
|
308
721
|
// src/upload.ts
|
|
309
722
|
var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
310
|
-
var
|
|
723
|
+
var MAX_MAP_CHARS = 32 * 1024 * 1024;
|
|
724
|
+
var MAX_UPLOAD_BYTES = MAX_MAP_CHARS + 1024 * 1024;
|
|
725
|
+
var LEGACY_MAX_BYTES = 5 * 1024 * 1024;
|
|
726
|
+
var gzip = (0, import_node_util.promisify)(import_node_zlib.gzip);
|
|
311
727
|
var CHECK_BATCH = 500;
|
|
312
728
|
var MAX_ATTEMPTS = 3;
|
|
313
729
|
function resolveEndpoint(flag, env = process.env) {
|
|
@@ -324,7 +740,16 @@ function storedMapJson(map) {
|
|
|
324
740
|
const { sourcesContent: _omitted, ...safe } = map;
|
|
325
741
|
return JSON.stringify(safe);
|
|
326
742
|
}
|
|
327
|
-
|
|
743
|
+
function bytesOf(buffer) {
|
|
744
|
+
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
745
|
+
}
|
|
746
|
+
function fits(json, body) {
|
|
747
|
+
return json.length <= MAX_MAP_CHARS && Buffer.byteLength(body) <= MAX_UPLOAD_BYTES;
|
|
748
|
+
}
|
|
749
|
+
function uploadBody(release, filename, debugId, json) {
|
|
750
|
+
return `{"release":${JSON.stringify(release)},"filename":${JSON.stringify(filename)},${debugId ? `"debugId":${JSON.stringify(debugId)},` : ""}"map":${json}}`;
|
|
751
|
+
}
|
|
752
|
+
async function prepare(bundle, urlPrefix, release, log, compress) {
|
|
328
753
|
let map;
|
|
329
754
|
try {
|
|
330
755
|
map = JSON.parse(await (0, import_promises3.readFile)(bundle.map, "utf8"));
|
|
@@ -336,17 +761,31 @@ async function prepare(bundle, urlPrefix, release) {
|
|
|
336
761
|
}
|
|
337
762
|
const code = await (0, import_promises3.readFile)(bundle.js, "utf8");
|
|
338
763
|
const debugId = readDebugIdComment(code) ?? normalizeDebugId(map.debugId);
|
|
339
|
-
const json = storedMapJson(map);
|
|
340
764
|
const filename = servedFilename(urlPrefix, bundle.path);
|
|
341
|
-
const
|
|
765
|
+
const { [SCOPES_KEY]: _stale, ...plain } = map;
|
|
766
|
+
const scopes = computeScopes(code, map);
|
|
767
|
+
let json = storedMapJson(plain);
|
|
768
|
+
if ("scopes" in scopes) {
|
|
769
|
+
const scoped = storedMapJson({ ...plain, [SCOPES_KEY]: scopes.scopes });
|
|
770
|
+
if (fits(scoped, uploadBody(release, filename, debugId, scoped))) json = scoped;
|
|
771
|
+
else if (fits(json, uploadBody(release, filename, debugId, json))) {
|
|
772
|
+
log(`warning: ${bundle.path}: its map is over 32 MB with function scopes, so it is uploaded without them (frames keep call-site names)`);
|
|
773
|
+
}
|
|
774
|
+
} else {
|
|
775
|
+
log(`warning: ${bundle.path}: no function scopes (${scopes.error}); its map is uploaded without them (frames keep call-site names)`);
|
|
776
|
+
}
|
|
777
|
+
const body = uploadBody(release, filename, debugId, json);
|
|
342
778
|
return {
|
|
343
779
|
bundle,
|
|
344
|
-
|
|
780
|
+
// Maps are text that compresses several times over; the ingester
|
|
781
|
+
// inflates the body (Content-Encoding: gzip).
|
|
782
|
+
body: compress && fits(json, body) ? bytesOf(await gzip(body)) : new Uint8Array(0),
|
|
345
783
|
path: bundle.path,
|
|
346
784
|
filename,
|
|
347
785
|
debugId,
|
|
348
786
|
hash: (0, import_node_crypto2.createHash)("sha256").update(json).digest("hex"),
|
|
349
|
-
bytes: Buffer.byteLength(body)
|
|
787
|
+
bytes: Buffer.byteLength(body),
|
|
788
|
+
mapChars: json.length
|
|
350
789
|
};
|
|
351
790
|
}
|
|
352
791
|
var FatalUploadError = class extends Error {
|
|
@@ -374,14 +813,14 @@ async function uploadDir(dir, options = {}) {
|
|
|
374
813
|
};
|
|
375
814
|
const items = [];
|
|
376
815
|
for (const bundle of await findBundles(dir, options.files)) {
|
|
377
|
-
const prepared = await prepare(bundle, options.urlPrefix, release);
|
|
816
|
+
const prepared = await prepare(bundle, options.urlPrefix, release, log, !options.dryRun);
|
|
378
817
|
if ("error" in prepared) {
|
|
379
818
|
summary.failed.push({ path: bundle.path, filename: servedFilename(options.urlPrefix, bundle.path), error: prepared.error });
|
|
380
|
-
} else if (prepared.bytes > MAX_UPLOAD_BYTES) {
|
|
819
|
+
} else if (prepared.mapChars > MAX_MAP_CHARS || prepared.bytes > MAX_UPLOAD_BYTES) {
|
|
381
820
|
summary.failed.push({
|
|
382
821
|
path: prepared.path,
|
|
383
822
|
filename: prepared.filename,
|
|
384
|
-
error: `map is ${(prepared.
|
|
823
|
+
error: `map is ${(prepared.mapChars / 1048576).toFixed(1)} MB without sourcesContent; the ingester accepts up to 32 MB`
|
|
385
824
|
});
|
|
386
825
|
} else {
|
|
387
826
|
items.push(prepared);
|
|
@@ -397,6 +836,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
397
836
|
throw new FatalUploadError("AUTTER_RUNTIME_KEY is a publishable client key (autter_rtc_\u2026); uploads need a server key (autter_rt_\u2026)");
|
|
398
837
|
}
|
|
399
838
|
const headers = { "content-type": "application/json", authorization: `Bearer ${key}` };
|
|
839
|
+
const uploadHeaders = { ...headers, "content-encoding": "gzip" };
|
|
400
840
|
const skipped = /* @__PURE__ */ new Set();
|
|
401
841
|
for (let start = 0; start < items.length && !summary.legacyIngester; start += CHECK_BATCH) {
|
|
402
842
|
const batch = items.slice(start, start + CHECK_BATCH);
|
|
@@ -438,7 +878,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
438
878
|
let status = 0;
|
|
439
879
|
let detail = "";
|
|
440
880
|
try {
|
|
441
|
-
const res = await doFetch(`${endpoint}/v1/sourcemaps`, { method: "POST", headers, body: item.body });
|
|
881
|
+
const res = await doFetch(`${endpoint}/v1/sourcemaps`, { method: "POST", headers: uploadHeaders, body: item.body });
|
|
442
882
|
status = res.status;
|
|
443
883
|
if (res.ok) {
|
|
444
884
|
uploaded.push(item);
|
|
@@ -454,7 +894,11 @@ async function uploadDir(dir, options = {}) {
|
|
|
454
894
|
}
|
|
455
895
|
const retryable = status === 0 || status === 429 || status >= 500;
|
|
456
896
|
if (!retryable || attempt >= MAX_ATTEMPTS) {
|
|
457
|
-
|
|
897
|
+
let error = status ? `HTTP ${status}: ${detail}` : detail;
|
|
898
|
+
if (status === 413 && item.bytes > LEGACY_MAX_BYTES) {
|
|
899
|
+
error += ` (this map is ${(item.bytes / 1048576).toFixed(1)} MB; ingester 1.6.0 and older accept up to 5 MB, newer ones 32 MB)`;
|
|
900
|
+
}
|
|
901
|
+
summary.failed.push({ path: item.path, filename: item.filename, error });
|
|
458
902
|
return;
|
|
459
903
|
}
|
|
460
904
|
await sleep(500 * 2 ** (attempt - 1));
|
|
@@ -487,6 +931,12 @@ function strip(item) {
|
|
|
487
931
|
}
|
|
488
932
|
|
|
489
933
|
// src/build.ts
|
|
934
|
+
var import_node_fs2 = require("fs");
|
|
935
|
+
var import_node_path2 = require("path");
|
|
936
|
+
function buildKey(options) {
|
|
937
|
+
const key = (options.key ?? process.env.AUTTER_RUNTIME_KEY ?? "").trim();
|
|
938
|
+
return key || null;
|
|
939
|
+
}
|
|
490
940
|
function formatUploadSummary(summary) {
|
|
491
941
|
const lines = [];
|
|
492
942
|
const verb = summary.dryRun ? "would upload" : "uploaded";
|
|
@@ -505,46 +955,90 @@ async function processBuildOutput(input) {
|
|
|
505
955
|
const log = (line) => {
|
|
506
956
|
if (!options.silent) console.log(`[autter-runtime] ${line}`);
|
|
507
957
|
};
|
|
508
|
-
const result = { injected: [], upload: null };
|
|
958
|
+
const result = { injected: [], upload: null, removedMaps: [] };
|
|
959
|
+
let outcome = "they were uploaded";
|
|
960
|
+
const owners = /* @__PURE__ */ new Map();
|
|
961
|
+
if (input.ownMaps) {
|
|
962
|
+
for (const bundle of await findBundles(input.dir, input.files)) owners.set(bundle.map, bundle.js);
|
|
963
|
+
}
|
|
509
964
|
try {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
965
|
+
try {
|
|
966
|
+
result.injected = await injectDir(input.dir, {
|
|
967
|
+
files: input.files,
|
|
968
|
+
dryRun: options.dryRun,
|
|
969
|
+
stripSourceMappingUrl: input.stripSourceMappingUrl
|
|
970
|
+
});
|
|
971
|
+
const changed = result.injected.filter((r) => r.status === "injected").length;
|
|
972
|
+
if (result.injected.length) {
|
|
973
|
+
log(`debug ids: ${changed} bundle(s) injected, ${result.injected.length - changed} already had one`);
|
|
974
|
+
}
|
|
975
|
+
for (const bad of result.injected.filter((r) => r.status === "invalid-map")) log(`skipped ${bad.path}: its map is not valid JSON`);
|
|
976
|
+
if (options.upload === false) return result;
|
|
977
|
+
const key = buildKey(options);
|
|
978
|
+
if (!key && !options.dryRun) {
|
|
979
|
+
outcome = "AUTTER_RUNTIME_KEY is not set";
|
|
980
|
+
if (result.injected.length && !input.ownMaps) log("AUTTER_RUNTIME_KEY is not set: source maps were not uploaded");
|
|
981
|
+
return result;
|
|
982
|
+
}
|
|
983
|
+
if (!result.injected.some((r) => r.status !== "invalid-map")) {
|
|
984
|
+
outcome = "no bundle had a usable map to upload";
|
|
985
|
+
return result;
|
|
986
|
+
}
|
|
987
|
+
result.upload = await uploadDir(input.dir, {
|
|
988
|
+
files: input.files,
|
|
989
|
+
release: options.release,
|
|
990
|
+
urlPrefix: options.urlPrefix ?? input.urlPrefix,
|
|
991
|
+
endpoint: options.endpoint,
|
|
992
|
+
key: key ?? void 0,
|
|
993
|
+
dryRun: options.dryRun,
|
|
994
|
+
concurrency: options.concurrency,
|
|
995
|
+
deleteAfterUpload: options.deleteAfterUpload ?? input.deleteAfterUpload,
|
|
996
|
+
log
|
|
997
|
+
});
|
|
998
|
+
for (const line of formatUploadSummary(result.upload)) log(line);
|
|
999
|
+
const { failed, uploaded, skipped, dryRun } = result.upload;
|
|
1000
|
+
if (dryRun) outcome = "dry run, nothing was uploaded";
|
|
1001
|
+
else if (failed.length) {
|
|
1002
|
+
outcome = `${failed.length} of ${failed.length + uploaded.length + skipped.length} could not be uploaded (${failed[0].error})`;
|
|
1003
|
+
}
|
|
1004
|
+
if (failed.length && options.failOnError) {
|
|
1005
|
+
throw new Error(`${failed.length} source map upload(s) failed`);
|
|
1006
|
+
}
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1009
|
+
if (outcome === "they were uploaded") outcome = `the upload failed (${message})`;
|
|
1010
|
+
if (options.failOnError) throw new Error(`[autter-runtime] source maps: ${message}`);
|
|
1011
|
+
if (!options.silent) console.warn(`[autter-runtime] source maps: ${message}`);
|
|
518
1012
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
1013
|
+
} finally {
|
|
1014
|
+
await cleanUp();
|
|
1015
|
+
}
|
|
1016
|
+
return result;
|
|
1017
|
+
async function cleanUp() {
|
|
1018
|
+
if (!input.ownMaps) return;
|
|
1019
|
+
const maps = /* @__PURE__ */ new Set([...input.maps ?? [], ...owners.keys()]);
|
|
1020
|
+
const rel = (path) => (0, import_node_path2.relative)(input.dir, path).split(import_node_path2.sep).join("/");
|
|
1021
|
+
if (options.upload === false || options.deleteAfterUpload === false) {
|
|
1022
|
+
const kept = [...maps].filter((map) => (0, import_node_fs2.existsSync)(map));
|
|
1023
|
+
if (kept.length) {
|
|
1024
|
+
log(
|
|
1025
|
+
`kept ${kept.length} source map(s) this plugin generated (${options.upload === false ? "upload: false" : "deleteAfterUpload: false"}): they expose your source, so upload them with \`autter-runtime sourcemaps upload --delete-after-upload\` or keep them out of the deploy`
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
return;
|
|
525
1029
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
log
|
|
537
|
-
});
|
|
538
|
-
for (const line of formatUploadSummary(result.upload)) log(line);
|
|
539
|
-
if (result.upload.failed.length && options.failOnError) {
|
|
540
|
-
throw new Error(`${result.upload.failed.length} source map upload(s) failed`);
|
|
1030
|
+
try {
|
|
1031
|
+
await removeSourceMaps(maps, owners);
|
|
1032
|
+
} catch (err) {
|
|
1033
|
+
const message = `could not delete the source maps this plugin generated (${err instanceof Error ? err.message : String(err)}): keep them out of the deploy`;
|
|
1034
|
+
if (options.failOnError) throw new Error(`[autter-runtime] ${message}`);
|
|
1035
|
+
if (!options.silent) console.warn(`[autter-runtime] ${message}`);
|
|
1036
|
+
}
|
|
1037
|
+
result.removedMaps = [...maps].filter((map) => !(0, import_node_fs2.existsSync)(map)).map(rel).sort();
|
|
1038
|
+
if (result.removedMaps.length) {
|
|
1039
|
+
log(`removed ${result.removedMaps.length} source map(s) this plugin generated, so they are not deployed: ${outcome}`);
|
|
541
1040
|
}
|
|
542
|
-
} catch (err) {
|
|
543
|
-
const message = `source maps: ${err instanceof Error ? err.message : String(err)}`;
|
|
544
|
-
if (options.failOnError) throw new Error(`[autter-runtime] ${message}`);
|
|
545
|
-
if (!options.silent) console.warn(`[autter-runtime] ${message}`);
|
|
546
1041
|
}
|
|
547
|
-
return result;
|
|
548
1042
|
}
|
|
549
1043
|
// Annotate the CommonJS export names for ESM import in node:
|
|
550
1044
|
0 && (module.exports = {
|
|
@@ -553,10 +1047,14 @@ async function processBuildOutput(input) {
|
|
|
553
1047
|
DEBUG_ID_REGISTRY,
|
|
554
1048
|
DEFAULT_ENDPOINT,
|
|
555
1049
|
FatalUploadError,
|
|
1050
|
+
MAX_MAP_CHARS,
|
|
556
1051
|
MAX_UPLOAD_BYTES,
|
|
557
1052
|
RELEASE_ENV_VARS,
|
|
558
1053
|
RELEASE_RE,
|
|
1054
|
+
SCOPES_KEY,
|
|
1055
|
+
SCOPES_VERSION,
|
|
559
1056
|
SNIPPET_LINE_KEY,
|
|
1057
|
+
computeScopes,
|
|
560
1058
|
debugIdFor,
|
|
561
1059
|
debugIdSnippet,
|
|
562
1060
|
findBundles,
|