@autter/runtime-cli 1.0.0 → 1.2.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 +97 -19
- package/dist/{build-BXFh_jbP.d.cts → build-BqjqqeLg.d.cts} +35 -9
- package/dist/{build-BXFh_jbP.d.ts → build-BqjqqeLg.d.ts} +35 -9
- package/dist/chunk-KIQRQY3X.js +1044 -0
- package/dist/{chunk-GGHHEUPQ.js → chunk-SIL3WZZ3.js} +26 -8
- package/dist/cli.js +2394 -154
- package/dist/index.cjs +817 -60
- package/dist/index.d.cts +111 -2
- package/dist/index.d.ts +111 -2
- package/dist/index.js +261 -2
- package/dist/next.cjs +645 -104
- package/dist/next.d.cts +3 -2
- package/dist/next.d.ts +3 -2
- package/dist/next.js +27 -8
- package/dist/vite.cjs +622 -95
- package/dist/vite.d.cts +3 -2
- package/dist/vite.d.ts +3 -2
- package/dist/vite.js +32 -6
- package/dist/webpack.cjs +615 -95
- package/dist/webpack.d.cts +11 -4
- package/dist/webpack.d.ts +11 -4
- package/dist/webpack.js +2 -2
- package/package.json +6 -1
- package/dist/chunk-SIRFO2QU.js +0 -524
package/dist/next.cjs
CHANGED
|
@@ -26,40 +26,11 @@ __export(next_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(next_exports);
|
|
28
28
|
var import_node_module = require("module");
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
// src/inject.ts
|
|
32
|
-
var import_promises2 = require("fs/promises");
|
|
29
|
+
var import_node_path4 = require("path");
|
|
33
30
|
|
|
34
|
-
// src/
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
function normalizeDebugId(value) {
|
|
38
|
-
if (typeof value !== "string") return null;
|
|
39
|
-
const id = value.trim().toLowerCase();
|
|
40
|
-
return DEBUG_ID_RE.test(id) ? id : null;
|
|
41
|
-
}
|
|
42
|
-
function debugIdFor(bytes) {
|
|
43
|
-
const hash = (0, import_node_crypto.createHash)("sha256").update(bytes).digest();
|
|
44
|
-
hash[6] = hash[6] & 15 | 64;
|
|
45
|
-
hash[8] = hash[8] & 63 | 128;
|
|
46
|
-
const hex = hash.subarray(0, 16).toString("hex");
|
|
47
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
48
|
-
}
|
|
49
|
-
var DEBUG_ID_COMMENT_RE = /^\/\/# debugId=([0-9a-fA-F-]{36})[ \t]*\r?$/gm;
|
|
50
|
-
function readDebugIdComment(code) {
|
|
51
|
-
let found = null;
|
|
52
|
-
for (const match of code.matchAll(DEBUG_ID_COMMENT_RE)) found = normalizeDebugId(match[1]) ?? found;
|
|
53
|
-
return found;
|
|
54
|
-
}
|
|
55
|
-
var DEBUG_ID_REGISTRY = "_autterDebugIds";
|
|
56
|
-
function debugIdSnippet(id) {
|
|
57
|
-
return `;!function(){try{var g="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof self?self:{},s=(new g.Error).stack;s&&((g.${DEBUG_ID_REGISTRY}=g.${DEBUG_ID_REGISTRY}||{})[s]="${id}")}catch(e){}}();`;
|
|
58
|
-
}
|
|
59
|
-
var SNIPPET_RE = /\(g\._autterDebugIds=g\._autterDebugIds\|\|\{\}\)\[s\]="[0-9a-f]{8}-/;
|
|
60
|
-
function hasDebugIdSnippet(code) {
|
|
61
|
-
return SNIPPET_RE.test(code);
|
|
62
|
-
}
|
|
31
|
+
// src/build.ts
|
|
32
|
+
var import_node_fs2 = require("fs");
|
|
33
|
+
var import_node_path2 = require("path");
|
|
63
34
|
|
|
64
35
|
// src/files.ts
|
|
65
36
|
var import_node_fs = require("fs");
|
|
@@ -99,7 +70,7 @@ function mapPathFor(js, code) {
|
|
|
99
70
|
const sibling = `${js}.map`;
|
|
100
71
|
return (0, import_node_fs.existsSync)(sibling) ? sibling : null;
|
|
101
72
|
}
|
|
102
|
-
async function walk(dir, out) {
|
|
73
|
+
async function walk(dir, out, pattern = BUNDLE_RE) {
|
|
103
74
|
let entries;
|
|
104
75
|
try {
|
|
105
76
|
entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
|
|
@@ -109,9 +80,51 @@ async function walk(dir, out) {
|
|
|
109
80
|
for (const entry of entries) {
|
|
110
81
|
if (entry.name === "node_modules") continue;
|
|
111
82
|
const full = (0, import_node_path.join)(dir, entry.name);
|
|
112
|
-
if (entry.isDirectory()) await walk(full, out);
|
|
113
|
-
else if (entry.isFile() &&
|
|
83
|
+
if (entry.isDirectory()) await walk(full, out, pattern);
|
|
84
|
+
else if (entry.isFile() && pattern.test(entry.name)) out.push(full);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function findMapFiles(dir) {
|
|
88
|
+
const out = [];
|
|
89
|
+
await walk((0, import_node_path.resolve)(dir), out, /\.map$/);
|
|
90
|
+
return out.sort();
|
|
91
|
+
}
|
|
92
|
+
var CSS_SOURCE_MAPPING_URL_RE = /\/\*[#@] sourceMappingURL=([^\s*]+)\s*\*\/\s*$/;
|
|
93
|
+
function pointsAt(file, url, map) {
|
|
94
|
+
if (!url || /^[a-z][\w+.-]*:/i.test(url) || url.startsWith("/")) return false;
|
|
95
|
+
let path = url.split(/[?#]/)[0];
|
|
96
|
+
try {
|
|
97
|
+
path = decodeURIComponent(path);
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
return (0, import_node_path.resolve)((0, import_node_path.dirname)(file), path) === map;
|
|
101
|
+
}
|
|
102
|
+
async function stripReference(file, map) {
|
|
103
|
+
let code;
|
|
104
|
+
try {
|
|
105
|
+
code = await (0, import_promises.readFile)(file, "utf8");
|
|
106
|
+
} catch {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
let stripped = code;
|
|
110
|
+
if (BUNDLE_RE.test(file)) {
|
|
111
|
+
if (pointsAt(file, readSourceMappingUrl(code), map)) stripped = stripSourceMappingUrl(code);
|
|
112
|
+
} else if (file.endsWith(".css")) {
|
|
113
|
+
const match = CSS_SOURCE_MAPPING_URL_RE.exec(code);
|
|
114
|
+
if (match && pointsAt(file, match[1], map)) stripped = code.slice(0, match.index).replace(/\n?$/, "\n");
|
|
114
115
|
}
|
|
116
|
+
if (stripped !== code) await (0, import_promises.writeFile)(file, stripped);
|
|
117
|
+
}
|
|
118
|
+
async function removeSourceMaps(maps, owners = /* @__PURE__ */ new Map()) {
|
|
119
|
+
const removed = [];
|
|
120
|
+
for (const map of [...new Set(maps)].sort()) {
|
|
121
|
+
if (!(0, import_node_fs.existsSync)(map)) continue;
|
|
122
|
+
await (0, import_promises.rm)(map, { force: true });
|
|
123
|
+
removed.push(map);
|
|
124
|
+
const owner = owners.get(map) ?? map.replace(/\.map$/, "");
|
|
125
|
+
await stripReference(owner, map);
|
|
126
|
+
}
|
|
127
|
+
return removed;
|
|
115
128
|
}
|
|
116
129
|
async function findBundles(dir, files) {
|
|
117
130
|
const root = (0, import_node_path.resolve)(dir);
|
|
@@ -135,6 +148,39 @@ async function findBundles(dir, files) {
|
|
|
135
148
|
return bundles;
|
|
136
149
|
}
|
|
137
150
|
|
|
151
|
+
// src/inject.ts
|
|
152
|
+
var import_promises2 = require("fs/promises");
|
|
153
|
+
|
|
154
|
+
// src/debug-id.ts
|
|
155
|
+
var import_node_crypto = require("crypto");
|
|
156
|
+
var DEBUG_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
157
|
+
function normalizeDebugId(value) {
|
|
158
|
+
if (typeof value !== "string") return null;
|
|
159
|
+
const id = value.trim().toLowerCase();
|
|
160
|
+
return DEBUG_ID_RE.test(id) ? id : null;
|
|
161
|
+
}
|
|
162
|
+
function debugIdFor(bytes) {
|
|
163
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(bytes).digest();
|
|
164
|
+
hash[6] = hash[6] & 15 | 64;
|
|
165
|
+
hash[8] = hash[8] & 63 | 128;
|
|
166
|
+
const hex = hash.subarray(0, 16).toString("hex");
|
|
167
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
168
|
+
}
|
|
169
|
+
var DEBUG_ID_COMMENT_RE = /^\/\/# debugId=([0-9a-fA-F-]{36})[ \t]*\r?$/gm;
|
|
170
|
+
function readDebugIdComment(code) {
|
|
171
|
+
let found = null;
|
|
172
|
+
for (const match of code.matchAll(DEBUG_ID_COMMENT_RE)) found = normalizeDebugId(match[1]) ?? found;
|
|
173
|
+
return found;
|
|
174
|
+
}
|
|
175
|
+
var DEBUG_ID_REGISTRY = "_autterDebugIds";
|
|
176
|
+
function debugIdSnippet(id) {
|
|
177
|
+
return `;!function(){try{var g="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof self?self:{},s=(new g.Error).stack;s&&((g.${DEBUG_ID_REGISTRY}=g.${DEBUG_ID_REGISTRY}||{})[s]="${id}")}catch(e){}}();`;
|
|
178
|
+
}
|
|
179
|
+
var SNIPPET_RE = /\(g\._autterDebugIds=g\._autterDebugIds\|\|\{\}\)\[s\]="[0-9a-f]{8}-/;
|
|
180
|
+
function hasDebugIdSnippet(code) {
|
|
181
|
+
return SNIPPET_RE.test(code);
|
|
182
|
+
}
|
|
183
|
+
|
|
138
184
|
// src/inject.ts
|
|
139
185
|
var SNIPPET_LINE_KEY = "x_autter_snippet_line";
|
|
140
186
|
function snippetLine(code) {
|
|
@@ -237,6 +283,8 @@ async function injectDir(dir, options = {}) {
|
|
|
237
283
|
// src/upload.ts
|
|
238
284
|
var import_node_crypto2 = require("crypto");
|
|
239
285
|
var import_promises3 = require("fs/promises");
|
|
286
|
+
var import_node_util = require("util");
|
|
287
|
+
var import_node_zlib = require("zlib");
|
|
240
288
|
|
|
241
289
|
// src/release.ts
|
|
242
290
|
var import_node_child_process = require("child_process");
|
|
@@ -282,9 +330,385 @@ function resolveRelease(explicit, env = process.env, cwd = process.cwd()) {
|
|
|
282
330
|
);
|
|
283
331
|
}
|
|
284
332
|
|
|
333
|
+
// src/scopes.ts
|
|
334
|
+
var import_acorn = require("acorn");
|
|
335
|
+
var SCOPES_KEY = "x_autter_scopes";
|
|
336
|
+
var SCOPES_VERSION = 1;
|
|
337
|
+
var BASE_OPTIONS = {
|
|
338
|
+
ecmaVersion: "latest",
|
|
339
|
+
allowHashBang: true,
|
|
340
|
+
allowReturnOutsideFunction: true,
|
|
341
|
+
allowReserved: true
|
|
342
|
+
};
|
|
343
|
+
function parseBundle(code) {
|
|
344
|
+
try {
|
|
345
|
+
return (0, import_acorn.parse)(code, {
|
|
346
|
+
...BASE_OPTIONS,
|
|
347
|
+
sourceType: "module",
|
|
348
|
+
allowAwaitOutsideFunction: true,
|
|
349
|
+
allowImportExportEverywhere: true
|
|
350
|
+
});
|
|
351
|
+
} catch (moduleError) {
|
|
352
|
+
try {
|
|
353
|
+
return (0, import_acorn.parse)(code, { ...BASE_OPTIONS, sourceType: "script" });
|
|
354
|
+
} catch (scriptError) {
|
|
355
|
+
const pos = (err) => typeof err.pos === "number" ? err.pos : -1;
|
|
356
|
+
throw pos(scriptError) > pos(moduleError) ? scriptError : moduleError;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function isNode(value) {
|
|
361
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
362
|
+
}
|
|
363
|
+
var IDENTIFIER_NAME_RE = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u;
|
|
364
|
+
function identifierToken(node) {
|
|
365
|
+
if (!isNode(node)) return null;
|
|
366
|
+
if (node.type === "Identifier") return { offset: node.start, name: node.name, literal: false };
|
|
367
|
+
if (node.type === "PrivateIdentifier") return { offset: node.start, name: `#${node.name}`, literal: false };
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
function literalToken(node) {
|
|
371
|
+
if (!isNode(node) || node.type !== "Literal" || typeof node.value !== "string") return null;
|
|
372
|
+
return IDENTIFIER_NAME_RE.test(node.value) ? { offset: node.start, name: node.value, literal: true } : null;
|
|
373
|
+
}
|
|
374
|
+
function keyToken(property) {
|
|
375
|
+
if (!property.computed) {
|
|
376
|
+
const id = identifierToken(property.key);
|
|
377
|
+
if (id) return id;
|
|
378
|
+
}
|
|
379
|
+
return literalToken(property.key);
|
|
380
|
+
}
|
|
381
|
+
function bindingToken(target) {
|
|
382
|
+
if (!isNode(target)) return null;
|
|
383
|
+
if (target.type === "Identifier") return identifierToken(target);
|
|
384
|
+
if (target.type === "MemberExpression") {
|
|
385
|
+
return target.computed ? literalToken(target.property) : identifierToken(target.property);
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
function contextTokens(node, parent) {
|
|
390
|
+
let token = null;
|
|
391
|
+
switch (parent?.type) {
|
|
392
|
+
case "VariableDeclarator":
|
|
393
|
+
if (parent.init === node) token = bindingToken(parent.id);
|
|
394
|
+
break;
|
|
395
|
+
case "AssignmentExpression":
|
|
396
|
+
case "AssignmentPattern":
|
|
397
|
+
if (parent.right === node) token = bindingToken(parent.left);
|
|
398
|
+
break;
|
|
399
|
+
case "Property":
|
|
400
|
+
case "PropertyDefinition":
|
|
401
|
+
case "MethodDefinition":
|
|
402
|
+
if (parent.value === node) token = keyToken(parent);
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
return token ? [token] : [];
|
|
406
|
+
}
|
|
407
|
+
function classTokens(path) {
|
|
408
|
+
if (!path || path.node.type !== "ClassDeclaration" && path.node.type !== "ClassExpression") return [];
|
|
409
|
+
const own = identifierToken(path.node.id);
|
|
410
|
+
return [...own ? [own] : [], ...contextTokens(path.node, path.parent?.node)];
|
|
411
|
+
}
|
|
412
|
+
function describe(path) {
|
|
413
|
+
const fn = path.node;
|
|
414
|
+
const parent = path.parent?.node;
|
|
415
|
+
const own = identifierToken(fn.id);
|
|
416
|
+
const isMethod = parent?.type === "MethodDefinition" || parent?.type === "Property" && parent.value === fn && (parent.method === true || parent.kind !== "init");
|
|
417
|
+
let context;
|
|
418
|
+
if (parent?.type === "MethodDefinition" && parent.kind === "constructor") {
|
|
419
|
+
context = classTokens(path.parent?.parent?.parent ?? null);
|
|
420
|
+
} else {
|
|
421
|
+
context = contextTokens(fn, parent);
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
start: fn.start,
|
|
425
|
+
end: fn.end,
|
|
426
|
+
own,
|
|
427
|
+
recoverAt: !own && fn.type !== "ArrowFunctionExpression" && !isMethod ? fn.start : null,
|
|
428
|
+
context
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
var FUNCTION_TYPES = /* @__PURE__ */ new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
|
|
432
|
+
function classInitializer(path) {
|
|
433
|
+
const node = path.node;
|
|
434
|
+
let range = null;
|
|
435
|
+
if (node.type === "StaticBlock") range = node;
|
|
436
|
+
else if (node.type === "PropertyDefinition" && isNode(node.value) && !FUNCTION_TYPES.has(node.value.type)) range = node.value;
|
|
437
|
+
if (!range) return null;
|
|
438
|
+
return { start: range.start, end: range.end, own: null, recoverAt: null, context: classTokens(path.parent?.parent ?? null) };
|
|
439
|
+
}
|
|
440
|
+
function collectFunctions(program) {
|
|
441
|
+
const found = [];
|
|
442
|
+
const stack = [{ node: program, parent: null }];
|
|
443
|
+
for (let path = stack.pop(); path; path = stack.pop()) {
|
|
444
|
+
const node = path.node;
|
|
445
|
+
if (FUNCTION_TYPES.has(node.type)) found.push(describe(path));
|
|
446
|
+
else {
|
|
447
|
+
const initializer = classInitializer(path);
|
|
448
|
+
if (initializer) found.push(initializer);
|
|
449
|
+
}
|
|
450
|
+
for (const key in node) {
|
|
451
|
+
const value = node[key];
|
|
452
|
+
if (Array.isArray(value)) {
|
|
453
|
+
for (let i = value.length - 1; i >= 0; i--) if (isNode(value[i])) stack.push({ node: value[i], parent: path });
|
|
454
|
+
} else if (isNode(value)) {
|
|
455
|
+
stack.push({ node: value, parent: path });
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return found;
|
|
460
|
+
}
|
|
461
|
+
function lineStarts(code) {
|
|
462
|
+
const starts = [0];
|
|
463
|
+
for (let i = 0; i < code.length; i++) {
|
|
464
|
+
const c = code.charCodeAt(i);
|
|
465
|
+
if (c === 10 || c === 8232 || c === 8233) starts.push(i + 1);
|
|
466
|
+
else if (c === 13) {
|
|
467
|
+
if (code.charCodeAt(i + 1) === 10) i++;
|
|
468
|
+
starts.push(i + 1);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return starts;
|
|
472
|
+
}
|
|
473
|
+
function positionOf(starts, offset) {
|
|
474
|
+
let lo = 0;
|
|
475
|
+
let hi = starts.length - 1;
|
|
476
|
+
while (lo < hi) {
|
|
477
|
+
const mid = lo + hi + 1 >> 1;
|
|
478
|
+
if (starts[mid] <= offset) lo = mid;
|
|
479
|
+
else hi = mid - 1;
|
|
480
|
+
}
|
|
481
|
+
return [lo, offset - starts[lo]];
|
|
482
|
+
}
|
|
483
|
+
var BASE64 = new Int8Array(128).fill(-1);
|
|
484
|
+
for (const [i, ch] of [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"].entries()) BASE64[ch.charCodeAt(0)] = i;
|
|
485
|
+
function findSegments(mappings, wanted) {
|
|
486
|
+
let line = 0;
|
|
487
|
+
let column = 0;
|
|
488
|
+
let source = 0;
|
|
489
|
+
let originalLine = 0;
|
|
490
|
+
let originalColumn = 0;
|
|
491
|
+
let name = 0;
|
|
492
|
+
let want = wanted.get(0);
|
|
493
|
+
const fields = [0, 0, 0, 0, 0];
|
|
494
|
+
let i = 0;
|
|
495
|
+
while (i < mappings.length) {
|
|
496
|
+
const ch = mappings.charCodeAt(i);
|
|
497
|
+
if (ch === 59) {
|
|
498
|
+
line++;
|
|
499
|
+
column = 0;
|
|
500
|
+
want = wanted.get(line);
|
|
501
|
+
i++;
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (ch === 44) {
|
|
505
|
+
i++;
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
let count = 0;
|
|
509
|
+
while (i < mappings.length) {
|
|
510
|
+
const next = mappings.charCodeAt(i);
|
|
511
|
+
if (next === 44 || next === 59) break;
|
|
512
|
+
let value = 0;
|
|
513
|
+
let shift = 0;
|
|
514
|
+
let digit;
|
|
515
|
+
do {
|
|
516
|
+
const code = mappings.charCodeAt(i++);
|
|
517
|
+
digit = code < 128 ? BASE64[code] : -1;
|
|
518
|
+
if (digit < 0 || shift > 30) throw new Error("invalid mappings");
|
|
519
|
+
value |= (digit & 31) << shift;
|
|
520
|
+
shift += 5;
|
|
521
|
+
} while (digit & 32);
|
|
522
|
+
const decoded = value & 1 ? -(value >>> 1) : value >>> 1;
|
|
523
|
+
if (count < 5) fields[count] = decoded;
|
|
524
|
+
count++;
|
|
525
|
+
}
|
|
526
|
+
column += fields[0];
|
|
527
|
+
if (count >= 4) {
|
|
528
|
+
source += fields[1];
|
|
529
|
+
originalLine += fields[2];
|
|
530
|
+
originalColumn += fields[3];
|
|
531
|
+
}
|
|
532
|
+
if (count >= 5) name += fields[4];
|
|
533
|
+
if (want && want.get(column) === null) {
|
|
534
|
+
want.set(column, {
|
|
535
|
+
source: count >= 4 ? source : -1,
|
|
536
|
+
line: originalLine,
|
|
537
|
+
column: originalColumn,
|
|
538
|
+
name: count >= 5 ? name : -1
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function looksMangled(name) {
|
|
544
|
+
return name.replace(/^#/, "").length <= 2;
|
|
545
|
+
}
|
|
546
|
+
var IDENTIFIER_AT_RE = /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/uy;
|
|
547
|
+
var OWN_NAME_AT_RE = /(?:async\s+)?function\b\s*\*?\s*([$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*)/uy;
|
|
548
|
+
var NOT_A_NAME = new Set(
|
|
549
|
+
"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(" ")
|
|
550
|
+
);
|
|
551
|
+
var NameResolver = class {
|
|
552
|
+
constructor(map, segmentAt) {
|
|
553
|
+
this.segmentAt = segmentAt;
|
|
554
|
+
this.names = Array.isArray(map.names) ? map.names : [];
|
|
555
|
+
this.sourcesContent = Array.isArray(map.sourcesContent) ? map.sourcesContent : [];
|
|
556
|
+
}
|
|
557
|
+
segmentAt;
|
|
558
|
+
names;
|
|
559
|
+
sourcesContent;
|
|
560
|
+
sourceLines = /* @__PURE__ */ new Map();
|
|
561
|
+
originalLine(segment) {
|
|
562
|
+
if (segment.source < 0) return null;
|
|
563
|
+
let lines = this.sourceLines.get(segment.source);
|
|
564
|
+
if (lines === void 0) {
|
|
565
|
+
const content = this.sourcesContent[segment.source];
|
|
566
|
+
lines = typeof content === "string" ? content.split(/\r\n|[\n\r\u2028\u2029]/) : null;
|
|
567
|
+
this.sourceLines.set(segment.source, lines);
|
|
568
|
+
}
|
|
569
|
+
return lines?.[segment.line] ?? null;
|
|
570
|
+
}
|
|
571
|
+
/** The original identifier at a segment's source position. */
|
|
572
|
+
identifierAt(segment, re, group = 0) {
|
|
573
|
+
const text = this.originalLine(segment);
|
|
574
|
+
if (text === null) return null;
|
|
575
|
+
re.lastIndex = segment.column;
|
|
576
|
+
const found = re.exec(text)?.[group];
|
|
577
|
+
return found && !NOT_A_NAME.has(found) ? found : null;
|
|
578
|
+
}
|
|
579
|
+
/** Original name of a token: the map's `names` at its exact position;
|
|
580
|
+
* else the generated name when it isn't mangled; else the identifier
|
|
581
|
+
* at the mapped position in `sourcesContent`. Null when unknown. */
|
|
582
|
+
resolve(token) {
|
|
583
|
+
if (token.literal) return token.name;
|
|
584
|
+
const segment = this.segmentAt(token.offset);
|
|
585
|
+
if (segment && segment.name >= 0) {
|
|
586
|
+
const name = this.names[segment.name];
|
|
587
|
+
if (typeof name === "string" && name) return name;
|
|
588
|
+
}
|
|
589
|
+
if (!looksMangled(token.name)) return token.name;
|
|
590
|
+
return segment ? this.identifierAt(segment, IDENTIFIER_AT_RE) : null;
|
|
591
|
+
}
|
|
592
|
+
/** The name a minifier removed from `function name() {}`, read from the
|
|
593
|
+
* original source at the function's mapped start. */
|
|
594
|
+
recover(offset) {
|
|
595
|
+
const segment = this.segmentAt(offset);
|
|
596
|
+
return segment ? this.identifierAt(segment, OWN_NAME_AT_RE, 1) : null;
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
var BASE64_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
600
|
+
function vlq(value) {
|
|
601
|
+
let rest = value < 0 ? -value << 1 | 1 : value << 1;
|
|
602
|
+
let out = "";
|
|
603
|
+
do {
|
|
604
|
+
let digit = rest & 31;
|
|
605
|
+
rest >>>= 5;
|
|
606
|
+
if (rest > 0) digit |= 32;
|
|
607
|
+
out += BASE64_DIGITS[digit];
|
|
608
|
+
} while (rest > 0);
|
|
609
|
+
return out;
|
|
610
|
+
}
|
|
611
|
+
function encodeScopes(entries) {
|
|
612
|
+
const parts = [];
|
|
613
|
+
let line = 0;
|
|
614
|
+
let previousStart = 0;
|
|
615
|
+
let previousName = 0;
|
|
616
|
+
let firstOnLine = true;
|
|
617
|
+
for (const [startLine, startColumn, endLine, endColumn, nameIndex] of entries) {
|
|
618
|
+
if (startLine > line) {
|
|
619
|
+
parts.push(";".repeat(startLine - line));
|
|
620
|
+
line = startLine;
|
|
621
|
+
previousStart = 0;
|
|
622
|
+
firstOnLine = true;
|
|
623
|
+
}
|
|
624
|
+
if (!firstOnLine) parts.push(",");
|
|
625
|
+
firstOnLine = false;
|
|
626
|
+
let segment = vlq(startColumn - previousStart) + vlq(endLine - startLine) + vlq(endLine === startLine ? endColumn - startColumn : endColumn);
|
|
627
|
+
previousStart = startColumn;
|
|
628
|
+
if (nameIndex >= 0) {
|
|
629
|
+
segment += vlq(nameIndex - previousName);
|
|
630
|
+
previousName = nameIndex;
|
|
631
|
+
}
|
|
632
|
+
parts.push(segment);
|
|
633
|
+
}
|
|
634
|
+
return parts.join("");
|
|
635
|
+
}
|
|
636
|
+
function computeScopes(code, map) {
|
|
637
|
+
try {
|
|
638
|
+
return scopesOf(code, map);
|
|
639
|
+
} catch (err) {
|
|
640
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function scopesOf(code, map) {
|
|
644
|
+
if (typeof map.mappings !== "string") return { error: "the map has no mappings string" };
|
|
645
|
+
let functions;
|
|
646
|
+
try {
|
|
647
|
+
functions = collectFunctions(parseBundle(code));
|
|
648
|
+
} catch (err) {
|
|
649
|
+
return { error: `could not parse the bundle: ${err instanceof Error ? err.message : String(err)}` };
|
|
650
|
+
}
|
|
651
|
+
const starts = lineStarts(code);
|
|
652
|
+
const wanted = /* @__PURE__ */ new Map();
|
|
653
|
+
const want = (offset) => {
|
|
654
|
+
const [line, column] = positionOf(starts, offset);
|
|
655
|
+
let columns = wanted.get(line);
|
|
656
|
+
if (!columns) wanted.set(line, columns = /* @__PURE__ */ new Map());
|
|
657
|
+
columns.set(column, null);
|
|
658
|
+
};
|
|
659
|
+
for (const fn of functions) {
|
|
660
|
+
if (fn.own && !fn.own.literal) want(fn.own.offset);
|
|
661
|
+
if (fn.recoverAt !== null) want(fn.recoverAt);
|
|
662
|
+
for (const token of fn.context) if (!token.literal) want(token.offset);
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
findSegments(map.mappings, wanted);
|
|
666
|
+
} catch (err) {
|
|
667
|
+
return { error: `could not read the map: ${err instanceof Error ? err.message : String(err)}` };
|
|
668
|
+
}
|
|
669
|
+
const resolver = new NameResolver(map, (offset) => {
|
|
670
|
+
const [line, column] = positionOf(starts, offset);
|
|
671
|
+
return wanted.get(line)?.get(column) ?? null;
|
|
672
|
+
});
|
|
673
|
+
functions.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
674
|
+
const mapNames = Array.isArray(map.names) ? map.names : [];
|
|
675
|
+
const nameIndex = /* @__PURE__ */ new Map();
|
|
676
|
+
mapNames.forEach((name, index) => {
|
|
677
|
+
if (typeof name === "string" && !nameIndex.has(name)) nameIndex.set(name, index);
|
|
678
|
+
});
|
|
679
|
+
const extraNames = [];
|
|
680
|
+
const indexOf = (name) => {
|
|
681
|
+
let index = nameIndex.get(name);
|
|
682
|
+
if (index === void 0) {
|
|
683
|
+
index = mapNames.length + extraNames.push(name) - 1;
|
|
684
|
+
nameIndex.set(name, index);
|
|
685
|
+
}
|
|
686
|
+
return index;
|
|
687
|
+
};
|
|
688
|
+
const entries = functions.map((fn) => {
|
|
689
|
+
let name = fn.own ? resolver.resolve(fn.own) : null;
|
|
690
|
+
if (name === null && fn.recoverAt !== null) name = resolver.recover(fn.recoverAt);
|
|
691
|
+
for (const token of fn.context) {
|
|
692
|
+
if (name !== null) break;
|
|
693
|
+
name = resolver.resolve(token);
|
|
694
|
+
}
|
|
695
|
+
const index = name !== null ? indexOf(name) : fn.own || fn.context.length > 0 ? indexOf(null) : -1;
|
|
696
|
+
const [startLine, startColumn] = positionOf(starts, fn.start);
|
|
697
|
+
const [endLine, endColumn] = positionOf(starts, fn.end);
|
|
698
|
+
return [startLine, startColumn, endLine, endColumn, index];
|
|
699
|
+
});
|
|
700
|
+
return { scopes: { version: SCOPES_VERSION, names: extraNames, scopes: encodeScopes(entries) } };
|
|
701
|
+
}
|
|
702
|
+
|
|
285
703
|
// src/upload.ts
|
|
286
704
|
var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
287
|
-
var
|
|
705
|
+
var MAX_MAP_CHARS = 32 * 1024 * 1024;
|
|
706
|
+
var MAX_UPLOAD_BYTES = MAX_MAP_CHARS + 1024 * 1024;
|
|
707
|
+
var LEGACY_MAX_BYTES = 5 * 1024 * 1024;
|
|
708
|
+
var UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
709
|
+
var CLIENT_KEY_PREFIX = "autter_rtc_";
|
|
710
|
+
var KEY_ADVICE = "set AUTTER_RUNTIME_KEY to an upload-only key (autter_rtu_\u2026, recommended for CI: it can only upload source maps) or the full server key (autter_rt_\u2026, also works)";
|
|
711
|
+
var gzip = (0, import_node_util.promisify)(import_node_zlib.gzip);
|
|
288
712
|
var CHECK_BATCH = 500;
|
|
289
713
|
var MAX_ATTEMPTS = 3;
|
|
290
714
|
function resolveEndpoint(flag, env = process.env) {
|
|
@@ -301,7 +725,16 @@ function storedMapJson(map) {
|
|
|
301
725
|
const { sourcesContent: _omitted, ...safe } = map;
|
|
302
726
|
return JSON.stringify(safe);
|
|
303
727
|
}
|
|
304
|
-
|
|
728
|
+
function bytesOf(buffer) {
|
|
729
|
+
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
730
|
+
}
|
|
731
|
+
function fits(json, body) {
|
|
732
|
+
return json.length <= MAX_MAP_CHARS && Buffer.byteLength(body) <= MAX_UPLOAD_BYTES;
|
|
733
|
+
}
|
|
734
|
+
function uploadBody(release, filename, debugId, json) {
|
|
735
|
+
return `{"release":${JSON.stringify(release)},"filename":${JSON.stringify(filename)},${debugId ? `"debugId":${JSON.stringify(debugId)},` : ""}"map":${json}}`;
|
|
736
|
+
}
|
|
737
|
+
async function prepare(bundle, urlPrefix, release, log, compress) {
|
|
305
738
|
let map;
|
|
306
739
|
try {
|
|
307
740
|
map = JSON.parse(await (0, import_promises3.readFile)(bundle.map, "utf8"));
|
|
@@ -313,17 +746,31 @@ async function prepare(bundle, urlPrefix, release) {
|
|
|
313
746
|
}
|
|
314
747
|
const code = await (0, import_promises3.readFile)(bundle.js, "utf8");
|
|
315
748
|
const debugId = readDebugIdComment(code) ?? normalizeDebugId(map.debugId);
|
|
316
|
-
const json = storedMapJson(map);
|
|
317
749
|
const filename = servedFilename(urlPrefix, bundle.path);
|
|
318
|
-
const
|
|
750
|
+
const { [SCOPES_KEY]: _stale, ...plain } = map;
|
|
751
|
+
const scopes = computeScopes(code, map);
|
|
752
|
+
let json = storedMapJson(plain);
|
|
753
|
+
if ("scopes" in scopes) {
|
|
754
|
+
const scoped = storedMapJson({ ...plain, [SCOPES_KEY]: scopes.scopes });
|
|
755
|
+
if (fits(scoped, uploadBody(release, filename, debugId, scoped))) json = scoped;
|
|
756
|
+
else if (fits(json, uploadBody(release, filename, debugId, json))) {
|
|
757
|
+
log(`warning: ${bundle.path}: its map is over 32 MB with function scopes, so it is uploaded without them (frames keep call-site names)`);
|
|
758
|
+
}
|
|
759
|
+
} else {
|
|
760
|
+
log(`warning: ${bundle.path}: no function scopes (${scopes.error}); its map is uploaded without them (frames keep call-site names)`);
|
|
761
|
+
}
|
|
762
|
+
const body = uploadBody(release, filename, debugId, json);
|
|
319
763
|
return {
|
|
320
764
|
bundle,
|
|
321
|
-
|
|
765
|
+
// Maps are text that compresses several times over; the ingester
|
|
766
|
+
// inflates the body (Content-Encoding: gzip).
|
|
767
|
+
body: compress && fits(json, body) ? bytesOf(await gzip(body)) : new Uint8Array(0),
|
|
322
768
|
path: bundle.path,
|
|
323
769
|
filename,
|
|
324
770
|
debugId,
|
|
325
771
|
hash: (0, import_node_crypto2.createHash)("sha256").update(json).digest("hex"),
|
|
326
|
-
bytes: Buffer.byteLength(body)
|
|
772
|
+
bytes: Buffer.byteLength(body),
|
|
773
|
+
mapChars: json.length
|
|
327
774
|
};
|
|
328
775
|
}
|
|
329
776
|
var FatalUploadError = class extends Error {
|
|
@@ -351,14 +798,14 @@ async function uploadDir(dir, options = {}) {
|
|
|
351
798
|
};
|
|
352
799
|
const items = [];
|
|
353
800
|
for (const bundle of await findBundles(dir, options.files)) {
|
|
354
|
-
const prepared = await prepare(bundle, options.urlPrefix, release);
|
|
801
|
+
const prepared = await prepare(bundle, options.urlPrefix, release, log, !options.dryRun);
|
|
355
802
|
if ("error" in prepared) {
|
|
356
803
|
summary.failed.push({ path: bundle.path, filename: servedFilename(options.urlPrefix, bundle.path), error: prepared.error });
|
|
357
|
-
} else if (prepared.bytes > MAX_UPLOAD_BYTES) {
|
|
804
|
+
} else if (prepared.mapChars > MAX_MAP_CHARS || prepared.bytes > MAX_UPLOAD_BYTES) {
|
|
358
805
|
summary.failed.push({
|
|
359
806
|
path: prepared.path,
|
|
360
807
|
filename: prepared.filename,
|
|
361
|
-
error: `map is ${(prepared.
|
|
808
|
+
error: `map is ${(prepared.mapChars / 1048576).toFixed(1)} MB without sourcesContent; the ingester accepts up to 32 MB`
|
|
362
809
|
});
|
|
363
810
|
} else {
|
|
364
811
|
items.push(prepared);
|
|
@@ -369,11 +816,15 @@ async function uploadDir(dir, options = {}) {
|
|
|
369
816
|
return summary;
|
|
370
817
|
}
|
|
371
818
|
const key = (options.key ?? env.AUTTER_RUNTIME_KEY ?? "").trim();
|
|
372
|
-
if (!key) throw new FatalUploadError(
|
|
373
|
-
if (key.startsWith(
|
|
374
|
-
throw new FatalUploadError(
|
|
819
|
+
if (!key) throw new FatalUploadError(`no ingest key: ${KEY_ADVICE}`);
|
|
820
|
+
if (key.startsWith(CLIENT_KEY_PREFIX)) {
|
|
821
|
+
throw new FatalUploadError(`AUTTER_RUNTIME_KEY is a publishable client key (autter_rtc_\u2026), which cannot upload source maps: ${KEY_ADVICE}`);
|
|
375
822
|
}
|
|
823
|
+
const rejected = (status, detail) => new FatalUploadError(
|
|
824
|
+
`the ingester rejected the key (${status}): ${detail}` + (key.startsWith(UPLOAD_KEY_PREFIX) ? " (upload keys, autter_rtu_\u2026, need ingester 1.7.0 or later; the server key works with any)" : "")
|
|
825
|
+
);
|
|
376
826
|
const headers = { "content-type": "application/json", authorization: `Bearer ${key}` };
|
|
827
|
+
const uploadHeaders = { ...headers, "content-encoding": "gzip" };
|
|
377
828
|
const skipped = /* @__PURE__ */ new Set();
|
|
378
829
|
for (let start = 0; start < items.length && !summary.legacyIngester; start += CHECK_BATCH) {
|
|
379
830
|
const batch = items.slice(start, start + CHECK_BATCH);
|
|
@@ -393,9 +844,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
393
844
|
);
|
|
394
845
|
break;
|
|
395
846
|
}
|
|
396
|
-
if (res.status === 401 || res.status === 403)
|
|
397
|
-
throw new FatalUploadError(`the ingester rejected the key (${res.status}): ${(await res.text()).slice(0, 300)}`);
|
|
398
|
-
}
|
|
847
|
+
if (res.status === 401 || res.status === 403) throw rejected(res.status, (await res.text()).slice(0, 300));
|
|
399
848
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
400
849
|
const body = await res.json();
|
|
401
850
|
const present = new Set(Array.isArray(body.present) ? body.present : []);
|
|
@@ -415,7 +864,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
415
864
|
let status = 0;
|
|
416
865
|
let detail = "";
|
|
417
866
|
try {
|
|
418
|
-
const res = await doFetch(`${endpoint}/v1/sourcemaps`, { method: "POST", headers, body: item.body });
|
|
867
|
+
const res = await doFetch(`${endpoint}/v1/sourcemaps`, { method: "POST", headers: uploadHeaders, body: item.body });
|
|
419
868
|
status = res.status;
|
|
420
869
|
if (res.ok) {
|
|
421
870
|
uploaded.push(item);
|
|
@@ -426,12 +875,16 @@ async function uploadDir(dir, options = {}) {
|
|
|
426
875
|
detail = err.message;
|
|
427
876
|
}
|
|
428
877
|
if (status === 401 || status === 403) {
|
|
429
|
-
fatal =
|
|
878
|
+
fatal = rejected(status, detail);
|
|
430
879
|
return;
|
|
431
880
|
}
|
|
432
881
|
const retryable = status === 0 || status === 429 || status >= 500;
|
|
433
882
|
if (!retryable || attempt >= MAX_ATTEMPTS) {
|
|
434
|
-
|
|
883
|
+
let error = status ? `HTTP ${status}: ${detail}` : detail;
|
|
884
|
+
if (status === 413 && item.bytes > LEGACY_MAX_BYTES) {
|
|
885
|
+
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)`;
|
|
886
|
+
}
|
|
887
|
+
summary.failed.push({ path: item.path, filename: item.filename, error });
|
|
435
888
|
return;
|
|
436
889
|
}
|
|
437
890
|
await sleep(500 * 2 ** (attempt - 1));
|
|
@@ -464,6 +917,18 @@ function strip(item) {
|
|
|
464
917
|
}
|
|
465
918
|
|
|
466
919
|
// src/build.ts
|
|
920
|
+
function buildKey(options) {
|
|
921
|
+
const key = (options.key ?? process.env.AUTTER_RUNTIME_KEY ?? "").trim();
|
|
922
|
+
return key || null;
|
|
923
|
+
}
|
|
924
|
+
function shouldGenerateMaps(options) {
|
|
925
|
+
return options.upload === false || Boolean(options.dryRun) || buildKey(options) !== null;
|
|
926
|
+
}
|
|
927
|
+
function logMapsNotGenerated(options) {
|
|
928
|
+
if (!options.silent) {
|
|
929
|
+
console.log("[autter-runtime] AUTTER_RUNTIME_KEY is not set: no source maps generated, nothing uploaded");
|
|
930
|
+
}
|
|
931
|
+
}
|
|
467
932
|
function formatUploadSummary(summary) {
|
|
468
933
|
const lines = [];
|
|
469
934
|
const verb = summary.dryRun ? "would upload" : "uploaded";
|
|
@@ -482,71 +947,131 @@ async function processBuildOutput(input) {
|
|
|
482
947
|
const log = (line) => {
|
|
483
948
|
if (!options.silent) console.log(`[autter-runtime] ${line}`);
|
|
484
949
|
};
|
|
485
|
-
const result = { injected: [], upload: null };
|
|
950
|
+
const result = { injected: [], upload: null, removedMaps: [] };
|
|
951
|
+
let outcome = "they were uploaded";
|
|
952
|
+
const owners = /* @__PURE__ */ new Map();
|
|
953
|
+
if (input.ownMaps) {
|
|
954
|
+
for (const bundle of await findBundles(input.dir, input.files)) owners.set(bundle.map, bundle.js);
|
|
955
|
+
}
|
|
486
956
|
try {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
957
|
+
try {
|
|
958
|
+
result.injected = await injectDir(input.dir, {
|
|
959
|
+
files: input.files,
|
|
960
|
+
dryRun: options.dryRun,
|
|
961
|
+
stripSourceMappingUrl: input.stripSourceMappingUrl
|
|
962
|
+
});
|
|
963
|
+
const changed = result.injected.filter((r) => r.status === "injected").length;
|
|
964
|
+
if (result.injected.length) {
|
|
965
|
+
log(`debug ids: ${changed} bundle(s) injected, ${result.injected.length - changed} already had one`);
|
|
966
|
+
}
|
|
967
|
+
for (const bad of result.injected.filter((r) => r.status === "invalid-map")) log(`skipped ${bad.path}: its map is not valid JSON`);
|
|
968
|
+
if (options.upload === false) return result;
|
|
969
|
+
const key = buildKey(options);
|
|
970
|
+
if (!key && !options.dryRun) {
|
|
971
|
+
outcome = "AUTTER_RUNTIME_KEY is not set";
|
|
972
|
+
if (result.injected.length && !input.ownMaps) log("AUTTER_RUNTIME_KEY is not set: source maps were not uploaded");
|
|
973
|
+
return result;
|
|
974
|
+
}
|
|
975
|
+
if (!result.injected.some((r) => r.status !== "invalid-map")) {
|
|
976
|
+
outcome = "no bundle had a usable map to upload";
|
|
977
|
+
return result;
|
|
978
|
+
}
|
|
979
|
+
result.upload = await uploadDir(input.dir, {
|
|
980
|
+
files: input.files,
|
|
981
|
+
release: options.release,
|
|
982
|
+
urlPrefix: options.urlPrefix ?? input.urlPrefix,
|
|
983
|
+
endpoint: options.endpoint,
|
|
984
|
+
key: key ?? void 0,
|
|
985
|
+
dryRun: options.dryRun,
|
|
986
|
+
concurrency: options.concurrency,
|
|
987
|
+
deleteAfterUpload: options.deleteAfterUpload ?? input.deleteAfterUpload,
|
|
988
|
+
log
|
|
989
|
+
});
|
|
990
|
+
for (const line of formatUploadSummary(result.upload)) log(line);
|
|
991
|
+
const { failed, uploaded, skipped, dryRun } = result.upload;
|
|
992
|
+
if (dryRun) outcome = "dry run, nothing was uploaded";
|
|
993
|
+
else if (failed.length) {
|
|
994
|
+
outcome = `${failed.length} of ${failed.length + uploaded.length + skipped.length} could not be uploaded (${failed[0].error})`;
|
|
995
|
+
}
|
|
996
|
+
if (failed.length && options.failOnError) {
|
|
997
|
+
throw new Error(`${failed.length} source map upload(s) failed`);
|
|
998
|
+
}
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1001
|
+
if (outcome === "they were uploaded") outcome = `the upload failed (${message})`;
|
|
1002
|
+
if (options.failOnError) throw new Error(`[autter-runtime] source maps: ${message}`);
|
|
1003
|
+
if (!options.silent) console.warn(`[autter-runtime] source maps: ${message}`);
|
|
518
1004
|
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
if (options.failOnError) throw new Error(`[autter-runtime] ${message}`);
|
|
522
|
-
if (!options.silent) console.warn(`[autter-runtime] ${message}`);
|
|
1005
|
+
} finally {
|
|
1006
|
+
await cleanUp();
|
|
523
1007
|
}
|
|
524
1008
|
return result;
|
|
1009
|
+
async function cleanUp() {
|
|
1010
|
+
if (!input.ownMaps) return;
|
|
1011
|
+
const maps = /* @__PURE__ */ new Set([...input.maps ?? [], ...owners.keys()]);
|
|
1012
|
+
const rel = (path) => (0, import_node_path2.relative)(input.dir, path).split(import_node_path2.sep).join("/");
|
|
1013
|
+
if (options.upload === false || options.deleteAfterUpload === false) {
|
|
1014
|
+
const kept = [...maps].filter((map) => (0, import_node_fs2.existsSync)(map));
|
|
1015
|
+
if (kept.length) {
|
|
1016
|
+
log(
|
|
1017
|
+
`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`
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
try {
|
|
1023
|
+
await removeSourceMaps(maps, owners);
|
|
1024
|
+
} catch (err) {
|
|
1025
|
+
const message = `could not delete the source maps this plugin generated (${err instanceof Error ? err.message : String(err)}): keep them out of the deploy`;
|
|
1026
|
+
if (options.failOnError) throw new Error(`[autter-runtime] ${message}`);
|
|
1027
|
+
if (!options.silent) console.warn(`[autter-runtime] ${message}`);
|
|
1028
|
+
}
|
|
1029
|
+
result.removedMaps = [...maps].filter((map) => !(0, import_node_fs2.existsSync)(map)).map(rel).sort();
|
|
1030
|
+
if (result.removedMaps.length) {
|
|
1031
|
+
log(`removed ${result.removedMaps.length} source map(s) this plugin generated, so they are not deployed: ${outcome}`);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
525
1034
|
}
|
|
526
1035
|
|
|
527
1036
|
// src/webpack.ts
|
|
528
|
-
var
|
|
1037
|
+
var import_node_path3 = require("path");
|
|
529
1038
|
var PLUGIN_NAME = "AutterSourceMapsWebpackPlugin";
|
|
530
1039
|
var AutterSourceMapsWebpackPlugin = class {
|
|
531
|
-
constructor(options = {}) {
|
|
1040
|
+
constructor(options = {}, internal = {}) {
|
|
532
1041
|
this.options = options;
|
|
1042
|
+
this.internal = internal;
|
|
533
1043
|
}
|
|
534
1044
|
options;
|
|
1045
|
+
internal;
|
|
535
1046
|
apply(compiler) {
|
|
536
1047
|
const mode = compiler.options.mode ?? (process.env.NODE_ENV === "development" ? "development" : void 0);
|
|
537
1048
|
if (mode === "development") return;
|
|
538
|
-
let enabledMaps = false;
|
|
1049
|
+
let enabledMaps = this.internal.ownMaps ?? false;
|
|
539
1050
|
if (!compiler.options.devtool) {
|
|
540
|
-
|
|
541
|
-
|
|
1051
|
+
if (shouldGenerateMaps(this.options)) {
|
|
1052
|
+
compiler.options.devtool = "hidden-source-map";
|
|
1053
|
+
enabledMaps = true;
|
|
1054
|
+
} else {
|
|
1055
|
+
logMapsNotGenerated(this.options);
|
|
1056
|
+
}
|
|
542
1057
|
}
|
|
543
1058
|
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, async (compilation) => {
|
|
544
1059
|
const dir = compilation.outputOptions.path ?? compiler.outputPath;
|
|
545
1060
|
if (!dir) return;
|
|
546
1061
|
const publicPath = compilation.outputOptions.publicPath;
|
|
547
1062
|
const urlPrefix = typeof publicPath === "string" && publicPath !== "auto" && publicPath !== "" ? publicPath : "/";
|
|
548
|
-
const
|
|
549
|
-
|
|
1063
|
+
const assets = compilation.getAssets().map((asset) => asset.name);
|
|
1064
|
+
const files = assets.filter((name) => BUNDLE_RE.test(name)).map((name) => (0, import_node_path3.resolve)(dir, name));
|
|
1065
|
+
const maps = assets.filter((name) => name.endsWith(".map")).map((name) => (0, import_node_path3.resolve)(dir, name));
|
|
1066
|
+
await processBuildOutput({
|
|
1067
|
+
dir,
|
|
1068
|
+
files,
|
|
1069
|
+
maps,
|
|
1070
|
+
urlPrefix,
|
|
1071
|
+
options: this.options,
|
|
1072
|
+
deleteAfterUpload: enabledMaps,
|
|
1073
|
+
ownMaps: enabledMaps
|
|
1074
|
+
});
|
|
550
1075
|
});
|
|
551
1076
|
}
|
|
552
1077
|
};
|
|
@@ -555,7 +1080,7 @@ var AutterSourceMapsWebpackPlugin = class {
|
|
|
555
1080
|
var AFTER_COMPILE_HOOK_SINCE = [15, 4, 1];
|
|
556
1081
|
function installedNextVersion(cwd = process.cwd()) {
|
|
557
1082
|
try {
|
|
558
|
-
const version = (0, import_node_module.createRequire)((0,
|
|
1083
|
+
const version = (0, import_node_module.createRequire)((0, import_node_path4.join)(cwd, "package.json"))("next/package.json").version;
|
|
559
1084
|
return typeof version === "string" ? version : null;
|
|
560
1085
|
} catch {
|
|
561
1086
|
return null;
|
|
@@ -572,7 +1097,15 @@ function hasAfterCompileHook(version) {
|
|
|
572
1097
|
}
|
|
573
1098
|
function wrapConfig(config, options) {
|
|
574
1099
|
const publicMaps = config.productionBrowserSourceMaps === true;
|
|
1100
|
+
const ownMaps = !publicMaps && shouldGenerateMaps(options);
|
|
575
1101
|
const deleteAfterUpload = options.deleteAfterUpload ?? !publicMaps;
|
|
1102
|
+
let notified = false;
|
|
1103
|
+
const notifyNoMaps = () => {
|
|
1104
|
+
if (!publicMaps && !ownMaps && !notified) {
|
|
1105
|
+
notified = true;
|
|
1106
|
+
logMapsNotGenerated(options);
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
576
1109
|
const base = String(config.assetPrefix || config.basePath || "").replace(/\/+$/, "");
|
|
577
1110
|
const nextPrefix = `${base}/_next/`;
|
|
578
1111
|
const useHook = hasAfterCompileHook(installedNextVersion());
|
|
@@ -582,11 +1115,14 @@ function wrapConfig(config, options) {
|
|
|
582
1115
|
webpack(webpackConfig, context) {
|
|
583
1116
|
const result = typeof userWebpack === "function" ? userWebpack(webpackConfig, context) : webpackConfig;
|
|
584
1117
|
if (!context.isServer && !context.dev) {
|
|
585
|
-
if (
|
|
1118
|
+
if (ownMaps) result.devtool = "hidden-source-map";
|
|
586
1119
|
if (!useHook) {
|
|
587
1120
|
result.plugins = [
|
|
588
1121
|
...result.plugins ?? [],
|
|
589
|
-
new AutterSourceMapsWebpackPlugin(
|
|
1122
|
+
new AutterSourceMapsWebpackPlugin(
|
|
1123
|
+
{ ...options, urlPrefix: options.urlPrefix ?? nextPrefix, deleteAfterUpload },
|
|
1124
|
+
{ ownMaps }
|
|
1125
|
+
)
|
|
590
1126
|
];
|
|
591
1127
|
}
|
|
592
1128
|
}
|
|
@@ -594,19 +1130,24 @@ function wrapConfig(config, options) {
|
|
|
594
1130
|
}
|
|
595
1131
|
};
|
|
596
1132
|
if (useHook) {
|
|
597
|
-
wrapped.productionBrowserSourceMaps = true;
|
|
1133
|
+
if (ownMaps) wrapped.productionBrowserSourceMaps = true;
|
|
598
1134
|
const userHook = config.compiler?.runAfterProductionCompile;
|
|
599
1135
|
wrapped.compiler = {
|
|
600
1136
|
...config.compiler,
|
|
601
1137
|
async runAfterProductionCompile(ctx = {}) {
|
|
602
1138
|
if (typeof userHook === "function") await userHook(ctx);
|
|
603
|
-
const distDir = ctx.distDir ?? (0,
|
|
1139
|
+
const distDir = ctx.distDir ?? (0, import_node_path4.resolve)(ctx.projectDir ?? process.cwd(), String(config.distDir ?? ".next"));
|
|
1140
|
+
const staticDir = (0, import_node_path4.join)(distDir, "static");
|
|
1141
|
+
notifyNoMaps();
|
|
604
1142
|
await processBuildOutput({
|
|
605
|
-
dir:
|
|
1143
|
+
dir: staticDir,
|
|
606
1144
|
urlPrefix: options.urlPrefix ?? `${nextPrefix}static/`,
|
|
607
1145
|
options: { ...options, deleteAfterUpload },
|
|
608
1146
|
deleteAfterUpload,
|
|
609
|
-
stripSourceMappingUrl: !publicMaps
|
|
1147
|
+
stripSourceMappingUrl: !publicMaps,
|
|
1148
|
+
ownMaps,
|
|
1149
|
+
// Every client map (JS and CSS): .next/static is deployed as is.
|
|
1150
|
+
maps: ownMaps ? await findMapFiles(staticDir) : void 0
|
|
610
1151
|
});
|
|
611
1152
|
}
|
|
612
1153
|
};
|