@interfere/next 10.0.0 → 10.0.1-canary.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 +6 -1
- package/dist/config.d.mts +1 -0
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +1 -110
- package/dist/config.mjs.map +1 -1
- package/dist/instrument-client.d.mts +7 -10
- package/dist/instrument-client.d.mts.map +1 -1
- package/dist/instrument-client.mjs +1 -9
- package/dist/instrument-client.mjs.map +1 -1
- package/dist/instrumentation-client.mjs +1 -22
- package/dist/instrumentation-client.mjs.map +1 -1
- package/dist/instrumentation.d.mts +3 -3
- package/dist/instrumentation.d.mts.map +1 -1
- package/dist/instrumentation.edge.d.mts +1 -1
- package/dist/instrumentation.edge.d.mts.map +1 -1
- package/dist/instrumentation.edge.mjs +1 -34
- package/dist/instrumentation.edge.mjs.map +1 -1
- package/dist/instrumentation.mjs +1 -165
- package/dist/instrumentation.mjs.map +1 -1
- package/dist/internal/build/configure-build.d.mts +2 -0
- package/dist/internal/build/configure-build.d.mts.map +1 -1
- package/dist/internal/build/configure-build.mjs +1 -95
- package/dist/internal/build/configure-build.mjs.map +1 -1
- package/dist/internal/build/detect-bundler.d.mts +3 -2
- package/dist/internal/build/detect-bundler.d.mts.map +1 -1
- package/dist/internal/build/detect-bundler.mjs +1 -9
- package/dist/internal/build/detect-bundler.mjs.map +1 -1
- package/dist/internal/build/pipeline.d.mts +5 -7
- package/dist/internal/build/pipeline.d.mts.map +1 -1
- package/dist/internal/build/pipeline.mjs +1 -82
- package/dist/internal/build/pipeline.mjs.map +1 -1
- package/dist/internal/build/release/destinations/index.mjs +1 -13
- package/dist/internal/build/release/destinations/index.mjs.map +1 -1
- package/dist/internal/build/release/destinations/vercel.d.mts.map +1 -1
- package/dist/internal/build/release/destinations/vercel.mjs +1 -23
- package/dist/internal/build/release/destinations/vercel.mjs.map +1 -1
- package/dist/internal/build/release/git.d.mts.map +1 -1
- package/dist/internal/build/release/git.mjs +1 -32
- package/dist/internal/build/release/git.mjs.map +1 -1
- package/dist/internal/build/release/index.mjs +1 -18
- package/dist/internal/build/release/index.mjs.map +1 -1
- package/dist/internal/build/release/sources/github.d.mts.map +1 -1
- package/dist/internal/build/release/sources/github.mjs +1 -13
- package/dist/internal/build/release/sources/github.mjs.map +1 -1
- package/dist/internal/build/release/sources/index.d.mts.map +1 -1
- package/dist/internal/build/release/sources/index.mjs +1 -20
- package/dist/internal/build/release/sources/index.mjs.map +1 -1
- package/dist/internal/build/source-maps/discover-turbopack.d.mts.map +1 -1
- package/dist/internal/build/source-maps/discover-turbopack.mjs +1 -68
- package/dist/internal/build/source-maps/discover-turbopack.mjs.map +1 -1
- package/dist/internal/build/source-maps/discover-webpack.d.mts.map +1 -1
- package/dist/internal/build/source-maps/discover-webpack.mjs +1 -112
- package/dist/internal/build/source-maps/discover-webpack.mjs.map +1 -1
- package/dist/internal/build/source-maps/discover.d.mts +4 -4
- package/dist/internal/build/source-maps/discover.d.mts.map +1 -1
- package/dist/internal/build/source-maps/discover.mjs +1 -26
- package/dist/internal/build/source-maps/discover.mjs.map +1 -1
- package/dist/internal/build/source-maps/index.d.mts.map +1 -1
- package/dist/internal/build/source-maps/index.mjs +1 -18
- package/dist/internal/build/source-maps/index.mjs.map +1 -1
- package/dist/internal/build/source-maps/paths.d.mts.map +1 -1
- package/dist/internal/build/source-maps/paths.mjs +1 -49
- package/dist/internal/build/source-maps/paths.mjs.map +1 -1
- package/dist/internal/build/source-maps/upload.d.mts.map +1 -1
- package/dist/internal/build/source-maps/upload.mjs +1 -134
- package/dist/internal/build/source-maps/upload.mjs.map +1 -1
- package/dist/internal/build/value-injection-loader.d.mts.map +1 -1
- package/dist/internal/build/value-injection-loader.mjs +2 -24
- package/dist/internal/build/value-injection-loader.mjs.map +1 -1
- package/dist/internal/env.d.mts +2 -1
- package/dist/internal/env.d.mts.map +1 -1
- package/dist/internal/env.mjs +1 -32
- package/dist/internal/env.mjs.map +1 -1
- package/dist/internal/logger.d.mts.map +1 -1
- package/dist/internal/logger.mjs +1 -68
- package/dist/internal/logger.mjs.map +1 -1
- package/dist/internal/release-slug.d.mts.map +1 -1
- package/dist/internal/release-slug.mjs +1 -32
- package/dist/internal/release-slug.mjs.map +1 -1
- package/dist/internal/route/handle-get.d.mts.map +1 -1
- package/dist/internal/route/handle-get.mjs +1 -43
- package/dist/internal/route/handle-get.mjs.map +1 -1
- package/dist/internal/route/handle-post.d.mts.map +1 -1
- package/dist/internal/route/handle-post.mjs +1 -31
- package/dist/internal/route/handle-post.mjs.map +1 -1
- package/dist/internal/route/proxy.d.mts +8 -6
- package/dist/internal/route/proxy.d.mts.map +1 -1
- package/dist/internal/route/proxy.mjs +1 -134
- package/dist/internal/route/proxy.mjs.map +1 -1
- package/dist/internal/server/capture.d.mts.map +1 -1
- package/dist/internal/server/capture.mjs +1 -89
- package/dist/internal/server/capture.mjs.map +1 -1
- package/dist/internal/server/console-bridge.d.mts.map +1 -1
- package/dist/internal/server/console-bridge.mjs +1 -112
- package/dist/internal/server/console-bridge.mjs.map +1 -1
- package/dist/internal/server/id-generator.d.mts.map +1 -1
- package/dist/internal/server/id-generator.mjs +1 -68
- package/dist/internal/server/id-generator.mjs.map +1 -1
- package/dist/internal/server/instrumentation-options.d.mts.map +1 -1
- package/dist/internal/server/instrumentation-options.mjs +1 -1
- package/dist/internal/server/remote-config.d.mts.map +1 -1
- package/dist/internal/server/remote-config.mjs +1 -29
- package/dist/internal/server/remote-config.mjs.map +1 -1
- package/dist/internal/server/trace-meta.d.mts +1 -3
- package/dist/internal/server/trace-meta.d.mts.map +1 -1
- package/dist/internal/server/trace-meta.mjs +1 -41
- package/dist/internal/server/trace-meta.mjs.map +1 -1
- package/dist/internal/server/traceparent.d.mts.map +1 -1
- package/dist/internal/server/traceparent.mjs +1 -26
- package/dist/internal/server/traceparent.mjs.map +1 -1
- package/dist/internal/server/types.d.mts.map +1 -1
- package/dist/internal/server/types.mjs +1 -1
- package/dist/internal/setup-warnings.d.mts +1 -1
- package/dist/internal/setup-warnings.d.mts.map +1 -1
- package/dist/internal/setup-warnings.mjs +1 -45
- package/dist/internal/setup-warnings.mjs.map +1 -1
- package/dist/internal/url.d.mts +4 -0
- package/dist/internal/url.d.mts.map +1 -0
- package/dist/internal/url.mjs +1 -0
- package/dist/internal/url.mjs.map +1 -0
- package/dist/internal/version.mjs +1 -5
- package/dist/internal/version.mjs.map +1 -1
- package/dist/package.mjs +1 -5
- package/dist/provider.d.mts.map +1 -1
- package/dist/provider.mjs +1 -25
- package/dist/provider.mjs.map +1 -1
- package/dist/route-handler.d.mts.map +1 -1
- package/dist/route-handler.mjs +1 -33
- package/dist/route-handler.mjs.map +1 -1
- package/dist/server.mjs +1 -3
- package/package.json +29 -30
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"mappings":";;;iBAKgB,OAAA,CAAA,GAAW,
|
|
1
|
+
{"version":3,"file":"github.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"mappings":";;;iBAKgB,OAAA,CAAA,GAAW,qBAAqB"}
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { parseEnvValue } from "@interfere/types/sdk/env";
|
|
3
|
-
//#region src/internal/build/release/sources/github.ts
|
|
4
|
-
function resolve() {
|
|
5
|
-
return {
|
|
6
|
-
provider: "github",
|
|
7
|
-
branch: parseEnvValue(process.env["VERCEL_GIT_COMMIT_REF"]) ?? parseEnvValue(process.env["GITHUB_REF_NAME"]) ?? parseEnvValue(process.env["GITHUB_HEAD_REF"]) ?? runGitCommand("git rev-parse --abbrev-ref HEAD") ?? "unknown",
|
|
8
|
-
commitMessage: parseEnvValue(process.env["VERCEL_GIT_COMMIT_MESSAGE"]) ?? runGitCommand("git log -1 --pretty=%B") ?? "",
|
|
9
|
-
commitSha: parseEnvValue(process.env["VERCEL_GIT_COMMIT_SHA"]) ?? parseEnvValue(process.env["GITHUB_SHA"]) ?? runGitCommand("git rev-parse HEAD")
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
export { resolve };
|
|
1
|
+
import{runGitCommand}from"../git.mjs";import{parseEnvValue}from"@interfere/types/sdk/env";function resolve(){return{provider:`github`,branch:parseEnvValue(process.env.VERCEL_GIT_COMMIT_REF)??parseEnvValue(process.env.GITHUB_REF_NAME)??parseEnvValue(process.env.GITHUB_HEAD_REF)??runGitCommand(`git rev-parse --abbrev-ref HEAD`)??`unknown`,commitMessage:parseEnvValue(process.env.VERCEL_GIT_COMMIT_MESSAGE)??runGitCommand(`git log -1 --pretty=%B`)??``,commitSha:parseEnvValue(process.env.VERCEL_GIT_COMMIT_SHA)??parseEnvValue(process.env.GITHUB_SHA)??runGitCommand(`git rev-parse HEAD`)}}export{resolve};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.mjs","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"sourcesContent":["import type { ReleaseSourceMetadata } from \"@interfere/types/integrations\";\nimport { parseEnvValue } from \"@interfere/types/sdk/env\";\n\nimport { runGitCommand } from \"../git.js\";\n\nexport function resolve(): ReleaseSourceMetadata {\n return {\n provider: \"github\",\n branch:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_REF\"]) ??\n parseEnvValue(process.env[\"GITHUB_REF_NAME\"]) ??\n parseEnvValue(process.env[\"GITHUB_HEAD_REF\"]) ??\n runGitCommand(\"git rev-parse --abbrev-ref HEAD\") ??\n \"unknown\",\n commitMessage:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_MESSAGE\"]) ??\n runGitCommand(\"git log -1 --pretty=%B\") ??\n \"\",\n commitSha:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_SHA\"]) ??\n parseEnvValue(process.env[\"GITHUB_SHA\"]) ??\n runGitCommand(\"git rev-parse HEAD\"),\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"github.mjs","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"sourcesContent":["import type { ReleaseSourceMetadata } from \"@interfere/types/integrations\";\nimport { parseEnvValue } from \"@interfere/types/sdk/env\";\n\nimport { runGitCommand } from \"../git.js\";\n\nexport function resolve(): ReleaseSourceMetadata {\n return {\n provider: \"github\",\n branch:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_REF\"]) ??\n parseEnvValue(process.env[\"GITHUB_REF_NAME\"]) ??\n parseEnvValue(process.env[\"GITHUB_HEAD_REF\"]) ??\n runGitCommand(\"git rev-parse --abbrev-ref HEAD\") ??\n \"unknown\",\n commitMessage:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_MESSAGE\"]) ??\n runGitCommand(\"git log -1 --pretty=%B\") ??\n \"\",\n commitSha:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_SHA\"]) ??\n parseEnvValue(process.env[\"GITHUB_SHA\"]) ??\n runGitCommand(\"git rev-parse HEAD\"),\n };\n}\n"],"mappings":"0FAKA,SAAgB,SAAiC,CAC/C,MAAO,CACL,SAAU,SACV,OACE,cAAc,QAAQ,IAAI,qBAAwB,GAClD,cAAc,QAAQ,IAAI,eAAkB,GAC5C,cAAc,QAAQ,IAAI,eAAkB,GAC5C,cAAc,iCAAiC,GAC/C,UACF,cACE,cAAc,QAAQ,IAAI,yBAA4B,GACtD,cAAc,wBAAwB,GACtC,GACF,UACE,cAAc,QAAQ,IAAI,qBAAwB,GAClD,cAAc,QAAQ,IAAI,UAAa,GACvC,cAAc,oBAAoB,CACtC,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"mappings":";;;;;AAsBA
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"mappings":";;;;;AAsBA;;;;;;;;;;;;AAAwE;cAA3D,OAAA,EAAS,MAAA,CAAO,cAAA,QAAsB,qBAAA"}
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
//#region src/internal/build/release/sources/index.ts
|
|
3
|
-
/**
|
|
4
|
-
* Per-provider source metadata resolvers. Each entry knows how to read
|
|
5
|
-
* its platform's env vars (and falls back to local git where applicable)
|
|
6
|
-
* and returns a `ReleaseSourceMetadata` blob keyed to the provider.
|
|
7
|
-
*
|
|
8
|
-
* Adding a new provider (gitlab, bitbucket, …) is one new file under
|
|
9
|
-
* this directory + one entry here. Every consumer that walks this
|
|
10
|
-
* registry — release-create payload assembly in the build pipeline —
|
|
11
|
-
* picks up the new provider for free.
|
|
12
|
-
*
|
|
13
|
-
* Lives under `internal/build/` because resolvers shell out to git via
|
|
14
|
-
* `runGitCommand`, which depends on `node:child_process` (not Edge-safe).
|
|
15
|
-
* Anything imported from `instrumentation.ts` must stay edge-safe; this
|
|
16
|
-
* tree is build-only.
|
|
17
|
-
*/
|
|
18
|
-
const sources = { github: resolve };
|
|
19
|
-
//#endregion
|
|
20
|
-
export { sources };
|
|
1
|
+
import{resolve}from"./github.mjs";const sources={github:resolve};export{sources};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["resolveGithub"],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"sourcesContent":["import type {\n ReleaseSourceMetadata,\n SourceProvider,\n} from \"@interfere/types/integrations\";\n\nimport { resolve as resolveGithub } from \"./github.js\";\n\n/**\n * Per-provider source metadata resolvers. Each entry knows how to read\n * its platform's env vars (and falls back to local git where applicable)\n * and returns a `ReleaseSourceMetadata` blob keyed to the provider.\n *\n * Adding a new provider (gitlab, bitbucket, …) is one new file under\n * this directory + one entry here. Every consumer that walks this\n * registry — release-create payload assembly in the build pipeline —\n * picks up the new provider for free.\n *\n * Lives under `internal/build/` because resolvers shell out to git via\n * `runGitCommand`, which depends on `node:child_process` (not Edge-safe).\n * Anything imported from `instrumentation.ts` must stay edge-safe; this\n * tree is build-only.\n */\nexport const sources: Record<SourceProvider, () => ReleaseSourceMetadata> = {\n github: resolveGithub,\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["resolveGithub"],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"sourcesContent":["import type {\n ReleaseSourceMetadata,\n SourceProvider,\n} from \"@interfere/types/integrations\";\n\nimport { resolve as resolveGithub } from \"./github.js\";\n\n/**\n * Per-provider source metadata resolvers. Each entry knows how to read\n * its platform's env vars (and falls back to local git where applicable)\n * and returns a `ReleaseSourceMetadata` blob keyed to the provider.\n *\n * Adding a new provider (gitlab, bitbucket, …) is one new file under\n * this directory + one entry here. Every consumer that walks this\n * registry — release-create payload assembly in the build pipeline —\n * picks up the new provider for free.\n *\n * Lives under `internal/build/` because resolvers shell out to git via\n * `runGitCommand`, which depends on `node:child_process` (not Edge-safe).\n * Anything imported from `instrumentation.ts` must stay edge-safe; this\n * tree is build-only.\n */\nexport const sources: Record<SourceProvider, () => ReleaseSourceMetadata> = {\n github: resolveGithub,\n};\n"],"mappings":"kCAsBA,MAAa,QAA+D,CAC1E,OAAQA,OACV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-turbopack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"mappings":";;;;;AA6BA
|
|
1
|
+
{"version":3,"file":"discover-turbopack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"mappings":";;;;;AA6BA;;;;;;;;;;;;AAGqD;;;;;;iBAH/B,iBAAA,CAAkB,IAAA;EACtC,UAAA;EACA,OAAA;AAAA,IACE,OAAO;EAAG,KAAA,EAAO,aAAA;EAAiB,eAAA;AAAA"}
|
|
@@ -1,68 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { relative } from "node:path";
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
4
|
-
import { readFile } from "node:fs/promises";
|
|
5
|
-
//#region src/internal/build/source-maps/discover-turbopack.ts
|
|
6
|
-
const DEBUG_ID_RE = /\/\/[#@]\s*debugId=([0-9a-f-]+)\s*$/m;
|
|
7
|
-
/**
|
|
8
|
-
* Turbopack-mode discovery.
|
|
9
|
-
*
|
|
10
|
-
* Turbopack hashes the JS chunk and its source map independently, so the
|
|
11
|
-
* `//# sourceMappingURL=…` URL embedded in the chunk never matches the
|
|
12
|
-
* on-disk `.js.map` filename. When `experimental.turbo.debugIds` is on
|
|
13
|
-
* (we set it for the user in `configure-build.ts`), turbopack natively
|
|
14
|
-
* injects matching `debugId` values into both the chunk
|
|
15
|
-
* (`//# debugId=…`) and the source map (`"debugId": "…"`).
|
|
16
|
-
*
|
|
17
|
-
* We pair JS chunks ↔ source maps by `debugId` (turbopack's natural key)
|
|
18
|
-
* and additionally record each chunk's public URL as `chunkUrl` so the
|
|
19
|
-
* server-side suffix-match resolver has a uniform field to look up by
|
|
20
|
-
* `frame.fileName` regardless of bundler. The webpack discoverer
|
|
21
|
-
* populates the same field directly from the chunk's URL; the turbopack
|
|
22
|
-
* discoverer derives it from the JS chunk's on-disk path.
|
|
23
|
-
*
|
|
24
|
-
* Maps without a debugId, or whose debugId never appears in any chunk,
|
|
25
|
-
* are silently skipped — they have no way to resolve at runtime.
|
|
26
|
-
*/
|
|
27
|
-
async function discoverTurbopack(opts) {
|
|
28
|
-
const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);
|
|
29
|
-
const relDistDir = relative(opts.projectDir, absDistDir);
|
|
30
|
-
const [mapPaths, jsPaths] = await Promise.all([walkDistTrees(absDistDir, ".js.map"), walkDistTrees(absDistDir, ".js")]);
|
|
31
|
-
const debugIdToChunkUrl = /* @__PURE__ */ new Map();
|
|
32
|
-
await Promise.all(jsPaths.map(async (jsAbs) => {
|
|
33
|
-
const content = await readFile(jsAbs, "utf8").catch(() => null);
|
|
34
|
-
if (content === null) return;
|
|
35
|
-
const debugId = DEBUG_ID_RE.exec(content)?.[1];
|
|
36
|
-
if (!debugId) return;
|
|
37
|
-
const chunkUrl = toPublicPath(relative(opts.projectDir, jsAbs), relDistDir);
|
|
38
|
-
if (!debugIdToChunkUrl.has(debugId)) debugIdToChunkUrl.set(debugId, chunkUrl);
|
|
39
|
-
}));
|
|
40
|
-
const loaded = (await Promise.all(mapPaths.map(async (mapAbs) => {
|
|
41
|
-
const content = await readFile(mapAbs, "utf8").catch(() => null);
|
|
42
|
-
if (content === null) return null;
|
|
43
|
-
let debugId;
|
|
44
|
-
try {
|
|
45
|
-
const parsed = JSON.parse(content);
|
|
46
|
-
if (typeof parsed.debugId === "string" && parsed.debugId.length > 0) debugId = parsed.debugId;
|
|
47
|
-
} catch {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
if (!debugId) return null;
|
|
51
|
-
const chunkUrl = debugIdToChunkUrl.get(debugId);
|
|
52
|
-
if (!chunkUrl) return null;
|
|
53
|
-
return {
|
|
54
|
-
absolute: mapAbs,
|
|
55
|
-
path: toPublicPath(relative(opts.projectDir, mapAbs), relDistDir),
|
|
56
|
-
content,
|
|
57
|
-
hash: createHash("sha256").update(content).digest("hex"),
|
|
58
|
-
debugId,
|
|
59
|
-
chunkUrl
|
|
60
|
-
};
|
|
61
|
-
}))).filter((f) => f !== null);
|
|
62
|
-
return {
|
|
63
|
-
files: loaded,
|
|
64
|
-
sourceFileCount: loaded.length
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
//#endregion
|
|
68
|
-
export { discoverTurbopack };
|
|
1
|
+
import{resolveDistDir,toPublicPath,walkDistTrees}from"./paths.mjs";import{relative}from"node:path";import{createHash}from"node:crypto";import{readFile}from"node:fs/promises";const DEBUG_ID_RE=/\/\/[#@]\s*debugId=([0-9a-f-]+)\s*$/m;async function discoverTurbopack(opts){let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),relDistDir=relative(opts.projectDir,absDistDir),[mapPaths,jsPaths]=await Promise.all([walkDistTrees(absDistDir,`.js.map`),walkDistTrees(absDistDir,`.js`)]),debugIdToChunkUrl=new Map;await Promise.all(jsPaths.map(async jsAbs=>{let content=await readFile(jsAbs,`utf8`).catch(()=>null);if(content===null)return;let debugId=DEBUG_ID_RE.exec(content)?.[1];if(!debugId)return;let chunkUrl=toPublicPath(relative(opts.projectDir,jsAbs),relDistDir);debugIdToChunkUrl.has(debugId)||debugIdToChunkUrl.set(debugId,chunkUrl)}));let loaded=(await Promise.all(mapPaths.map(async mapAbs=>{let content=await readFile(mapAbs,`utf8`).catch(()=>null);if(content===null)return null;let debugId;try{let parsed=JSON.parse(content);typeof parsed.debugId==`string`&&parsed.debugId.length>0&&(debugId=parsed.debugId)}catch{return null}if(!debugId)return null;let chunkUrl=debugIdToChunkUrl.get(debugId);return chunkUrl?{absolute:mapAbs,path:toPublicPath(relative(opts.projectDir,mapAbs),relDistDir),content,hash:createHash(`sha256`).update(content).digest(`hex`),debugId,chunkUrl}:null}))).filter(f=>f!==null);return{files:loaded,sourceFileCount:loaded.length}}export{discoverTurbopack};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-turbopack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst DEBUG_ID_RE = /\\/\\/[#@]\\s*debugId=([0-9a-f-]+)\\s*$/m;\n\n/**\n * Turbopack-mode discovery.\n *\n * Turbopack hashes the JS chunk and its source map independently, so the\n * `//# sourceMappingURL=…` URL embedded in the chunk never matches the\n * on-disk `.js.map` filename. When `experimental.turbo.debugIds` is on\n * (we set it for the user in `configure-build.ts`), turbopack natively\n * injects matching `debugId` values into both the chunk\n * (`//# debugId=…`) and the source map (`\"debugId\": \"…\"`).\n *\n * We pair JS chunks ↔ source maps by `debugId` (turbopack's natural key)\n * and additionally record each chunk's public URL as `chunkUrl` so the\n * server-side suffix-match resolver has a uniform field to look up by\n * `frame.fileName` regardless of bundler. The webpack discoverer\n * populates the same field directly from the chunk's URL; the turbopack\n * discoverer derives it from the JS chunk's on-disk path.\n *\n * Maps without a debugId, or whose debugId never appears in any chunk,\n * are silently skipped — they have no way to resolve at runtime.\n */\nexport async function discoverTurbopack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const [mapPaths, jsPaths] = await Promise.all([\n walkDistTrees(absDistDir, \".js.map\"),\n walkDistTrees(absDistDir, \".js\"),\n ]);\n\n // Walk JS chunks once and build `debugId → publicUrl` so a single\n // pass over the maps can attach `chunkUrl` per entry.\n const debugIdToChunkUrl = new Map<string, string>();\n await Promise.all(\n jsPaths.map(async (jsAbs) => {\n const content = await readFile(jsAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return;\n }\n const match = DEBUG_ID_RE.exec(content);\n const debugId = match?.[1];\n if (!debugId) {\n return;\n }\n const chunkUrl = toPublicPath(\n relative(opts.projectDir, jsAbs),\n relDistDir\n );\n // First write wins — collisions across .js shouldn't happen with\n // content-hashed chunk filenames, but if they do, the first walked\n // entry is the deterministic choice.\n if (!debugIdToChunkUrl.has(debugId)) {\n debugIdToChunkUrl.set(debugId, chunkUrl);\n }\n })\n );\n\n const files = await Promise.all(\n mapPaths.map(async (mapAbs): Promise<SourceMapFile | null> => {\n const content = await readFile(mapAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return null;\n }\n\n let debugId: string | undefined;\n try {\n const parsed = JSON.parse(content) as { debugId?: unknown };\n if (typeof parsed.debugId === \"string\" && parsed.debugId.length > 0) {\n debugId = parsed.debugId;\n }\n } catch {\n return null;\n }\n\n if (!debugId) {\n return null;\n }\n\n const chunkUrl = debugIdToChunkUrl.get(debugId);\n if (!chunkUrl) {\n // No JS chunk in the dist tree carries this debugId — the map\n // can't pair to a runtime URL, so it's unresolvable. Drop it\n // rather than emitting an unusable manifest entry.\n return null;\n }\n\n return {\n absolute: mapAbs,\n path: toPublicPath(relative(opts.projectDir, mapAbs), relDistDir),\n content,\n hash: createHash(\"sha256\").update(content).digest(\"hex\"),\n debugId,\n chunkUrl,\n } satisfies SourceMapFile;\n })\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: loaded.length,\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"discover-turbopack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst DEBUG_ID_RE = /\\/\\/[#@]\\s*debugId=([0-9a-f-]+)\\s*$/m;\n\n/**\n * Turbopack-mode discovery.\n *\n * Turbopack hashes the JS chunk and its source map independently, so the\n * `//# sourceMappingURL=…` URL embedded in the chunk never matches the\n * on-disk `.js.map` filename. When `experimental.turbo.debugIds` is on\n * (we set it for the user in `configure-build.ts`), turbopack natively\n * injects matching `debugId` values into both the chunk\n * (`//# debugId=…`) and the source map (`\"debugId\": \"…\"`).\n *\n * We pair JS chunks ↔ source maps by `debugId` (turbopack's natural key)\n * and additionally record each chunk's public URL as `chunkUrl` so the\n * server-side suffix-match resolver has a uniform field to look up by\n * `frame.fileName` regardless of bundler. The webpack discoverer\n * populates the same field directly from the chunk's URL; the turbopack\n * discoverer derives it from the JS chunk's on-disk path.\n *\n * Maps without a debugId, or whose debugId never appears in any chunk,\n * are silently skipped — they have no way to resolve at runtime.\n */\nexport async function discoverTurbopack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const [mapPaths, jsPaths] = await Promise.all([\n walkDistTrees(absDistDir, \".js.map\"),\n walkDistTrees(absDistDir, \".js\"),\n ]);\n\n // Walk JS chunks once and build `debugId → publicUrl` so a single\n // pass over the maps can attach `chunkUrl` per entry.\n const debugIdToChunkUrl = new Map<string, string>();\n await Promise.all(\n jsPaths.map(async (jsAbs) => {\n const content = await readFile(jsAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return;\n }\n const match = DEBUG_ID_RE.exec(content);\n const debugId = match?.[1];\n if (!debugId) {\n return;\n }\n const chunkUrl = toPublicPath(\n relative(opts.projectDir, jsAbs),\n relDistDir\n );\n // First write wins — collisions across .js shouldn't happen with\n // content-hashed chunk filenames, but if they do, the first walked\n // entry is the deterministic choice.\n if (!debugIdToChunkUrl.has(debugId)) {\n debugIdToChunkUrl.set(debugId, chunkUrl);\n }\n })\n );\n\n const files = await Promise.all(\n mapPaths.map(async (mapAbs): Promise<SourceMapFile | null> => {\n const content = await readFile(mapAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return null;\n }\n\n let debugId: string | undefined;\n try {\n const parsed = JSON.parse(content) as { debugId?: unknown };\n if (typeof parsed.debugId === \"string\" && parsed.debugId.length > 0) {\n debugId = parsed.debugId;\n }\n } catch {\n return null;\n }\n\n if (!debugId) {\n return null;\n }\n\n const chunkUrl = debugIdToChunkUrl.get(debugId);\n if (!chunkUrl) {\n // No JS chunk in the dist tree carries this debugId — the map\n // can't pair to a runtime URL, so it's unresolvable. Drop it\n // rather than emitting an unusable manifest entry.\n return null;\n }\n\n return {\n absolute: mapAbs,\n path: toPublicPath(relative(opts.projectDir, mapAbs), relDistDir),\n content,\n hash: createHash(\"sha256\").update(content).digest(\"hex\"),\n debugId,\n chunkUrl,\n } satisfies SourceMapFile;\n })\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: loaded.length,\n };\n}\n"],"mappings":"8KAOA,MAAM,YAAc,uCAsBpB,eAAsB,kBAAkB,KAGyB,CAC/D,IAAM,WAAa,eAAe,KAAK,WAAY,KAAK,OAAO,EACzD,WAAa,SAAS,KAAK,WAAY,UAAU,EAEjD,CAAC,SAAU,SAAW,MAAM,QAAQ,IAAI,CAC5C,cAAc,WAAY,SAAS,EACnC,cAAc,WAAY,KAAK,CACjC,CAAC,EAIK,kBAAoB,IAAI,IAC9B,MAAM,QAAQ,IACZ,QAAQ,IAAI,KAAO,QAAU,CAC3B,IAAM,QAAU,MAAM,SAAS,MAAO,MAAM,EAAE,UAAY,IAAI,EAC9D,GAAI,UAAY,KACd,OAGF,IAAM,QADQ,YAAY,KAAK,OACX,IAAI,GACxB,GAAI,CAAC,QACH,OAEF,IAAM,SAAW,aACf,SAAS,KAAK,WAAY,KAAK,EAC/B,UACF,EAIK,kBAAkB,IAAI,OAAO,GAChC,kBAAkB,IAAI,QAAS,QAAQ,CAE3C,CAAC,CACH,EA0CA,IAAM,QAAS,MAxCK,QAAQ,IAC1B,SAAS,IAAI,KAAO,SAA0C,CAC5D,IAAM,QAAU,MAAM,SAAS,OAAQ,MAAM,EAAE,UAAY,IAAI,EAC/D,GAAI,UAAY,KACd,OAAO,KAGT,IAAI,QACJ,GAAI,CACF,IAAM,OAAS,KAAK,MAAM,OAAO,EAC7B,OAAO,OAAO,SAAY,UAAY,OAAO,QAAQ,OAAS,IAChE,QAAU,OAAO,QAErB,MAAQ,CACN,OAAO,IACT,CAEA,GAAI,CAAC,QACH,OAAO,KAGT,IAAM,SAAW,kBAAkB,IAAI,OAAO,EAQ9C,OAPK,SAOE,CACL,SAAU,OACV,KAAM,aAAa,SAAS,KAAK,WAAY,MAAM,EAAG,UAAU,EAChE,QACA,KAAM,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK,EACvD,QACA,QACF,EAVS,IAWX,CAAC,CACH,GAEqB,OAAQ,GAA0B,IAAM,IAAI,EAEjE,MAAO,CACL,MAAO,OACP,gBAAiB,OAAO,MAC1B,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-webpack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"mappings":";;;;;AAwBA;;;iBAAgB,iBAAA,CAAkB,
|
|
1
|
+
{"version":3,"file":"discover-webpack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"mappings":";;;;;AAwBA;;;iBAAgB,iBAAA,CAAkB,OAAe;AAAA;AAgBjD;;;;AAAoE;AAuBpE;;;;AAAqE;AAvCpB,iBAgBjC,mBAAA,CAAoB,OAAA,UAAiB,OAAe;;;;;;;iBAuBpD,oBAAA,CAAqB,OAAA,UAAiB,OAAe;;;;;AAyBhB;;;;;;;;;;;;iBAH/B,eAAA,CAAgB,IAAA;EACpC,UAAA;EACA,OAAA;AAAA,IACE,OAAO;EAAG,KAAA,EAAO,aAAA;EAAiB,eAAA;AAAA"}
|
|
@@ -1,112 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { relative } from "node:path";
|
|
3
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
5
|
-
//#region src/internal/build/source-maps/discover-webpack.ts
|
|
6
|
-
const SOURCEMAPPING_RE = /\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/;
|
|
7
|
-
/**
|
|
8
|
-
* Per the TC39 sourcemap-debug-id proposal, the LAST `//# debugId=…`
|
|
9
|
-
* comment in the bundle is the canonical one. Same regex Sentry uses
|
|
10
|
-
* to detect spec-compliant debug IDs already injected by another tool
|
|
11
|
-
* (webpack 5.104+ `SourceMapDevToolPlugin({ debugIds: true })`,
|
|
12
|
-
* turbopack `experimental.turbopack.debugIds`, rollup, vite, etc.).
|
|
13
|
-
*/
|
|
14
|
-
const SPEC_LAST_DEBUG_ID_RE = /\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;
|
|
15
|
-
/**
|
|
16
|
-
* Reads an existing `//# debugId=…` comment from the bundle source.
|
|
17
|
-
* Returns `null` when no debug ID comment is present — the caller is
|
|
18
|
-
* expected to generate and inject one.
|
|
19
|
-
*/
|
|
20
|
-
function readDebugIdFromJs(content) {
|
|
21
|
-
return SPEC_LAST_DEBUG_ID_RE.exec(content)?.[1] ?? null;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Inserts a `//# debugId=…` comment into the chunk. Idempotent: if a
|
|
25
|
-
* spec-compliant comment is already present (e.g. webpack 5.104+ with
|
|
26
|
-
* `SourceMapDevToolPlugin({ debugIds: true })`, turbopack with
|
|
27
|
-
* `experimental.turbopack.debugIds`, or any other tool) it's
|
|
28
|
-
* overwritten with the supplied debugId — callers that read the
|
|
29
|
-
* existing id via `readDebugIdFromJs` first get an idempotent no-op.
|
|
30
|
-
*
|
|
31
|
-
* Otherwise the comment is appended just before the existing
|
|
32
|
-
* `//# sourceMappingURL=…` line so the browser still resolves the map.
|
|
33
|
-
*/
|
|
34
|
-
function injectDebugIdIntoJs(content, debugId) {
|
|
35
|
-
const debugIdComment = `//# debugId=${debugId}`;
|
|
36
|
-
if (SPEC_LAST_DEBUG_ID_RE.test(content)) return content.replace(SPEC_LAST_DEBUG_ID_RE, debugIdComment);
|
|
37
|
-
const match = SOURCEMAPPING_RE.exec(content);
|
|
38
|
-
if (match) return `${content.slice(0, match.index).trimEnd()}\n${debugIdComment}\n${match[0]}`;
|
|
39
|
-
return `${content}\n${debugIdComment}`;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Adds `debugId` to the source-map JSON. Idempotent: writes both
|
|
43
|
-
* `debugId` (TC39 spec field) and `debug_id` (legacy variant some
|
|
44
|
-
* older Sentry tooling emits) so manifests stay readable across the
|
|
45
|
-
* ecosystem. Re-running with the same id produces identical output.
|
|
46
|
-
*/
|
|
47
|
-
function injectDebugIdIntoMap(content, debugId) {
|
|
48
|
-
const json = JSON.parse(content);
|
|
49
|
-
json["debugId"] = debugId;
|
|
50
|
-
return JSON.stringify(json);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Webpack-mode discovery: walks the dist tree, parses each `.js`
|
|
54
|
-
* chunk's `//# sourceMappingURL=…` comment to find its paired `.map`,
|
|
55
|
-
* and ensures both carry the same `debugId`.
|
|
56
|
-
*
|
|
57
|
-
* Idempotent w.r.t. debug-id state on disk:
|
|
58
|
-
* - If the chunk already carries a `//# debugId=…` comment (webpack
|
|
59
|
-
* 5.104+ with `SourceMapDevToolPlugin({ debugIds: true })`, or a
|
|
60
|
-
* third-party tool that already injected one) we reuse it.
|
|
61
|
-
* - Otherwise we generate a fresh UUID and inject it into both files.
|
|
62
|
-
*
|
|
63
|
-
* The "reuse if present" branch matches the strategy in Sentry's
|
|
64
|
-
* webpack plugin (`addDebugIdToBundleSource` in
|
|
65
|
-
* `bundler-plugin-core/src/debug-id-upload.ts`) and means our
|
|
66
|
-
* discovery works transparently when bundlers natively emit debugIds.
|
|
67
|
-
*/
|
|
68
|
-
async function discoverWebpack(opts) {
|
|
69
|
-
const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);
|
|
70
|
-
const relDistDir = relative(opts.projectDir, absDistDir);
|
|
71
|
-
const jsPaths = await walkDistTrees(absDistDir, ".js");
|
|
72
|
-
const pairs = /* @__PURE__ */ new Map();
|
|
73
|
-
for (const jsAbs of jsPaths) {
|
|
74
|
-
const content = await readFile(jsAbs, "utf8");
|
|
75
|
-
const match = SOURCEMAPPING_RE.exec(content);
|
|
76
|
-
if (!match?.[1]) continue;
|
|
77
|
-
const mapAbs = `${jsAbs.slice(0, jsAbs.lastIndexOf("/") + 1)}${decodeURIComponent(match[1])}`;
|
|
78
|
-
const jsPublic = toPublicPath(relative(opts.projectDir, jsAbs), relDistDir);
|
|
79
|
-
const mapPublic = toPublicPath(relative(opts.projectDir, mapAbs), relDistDir);
|
|
80
|
-
pairs.set(mapPublic, {
|
|
81
|
-
mapAbs,
|
|
82
|
-
jsAbs,
|
|
83
|
-
jsPublic,
|
|
84
|
-
jsContent: content,
|
|
85
|
-
existingDebugId: readDebugIdFromJs(content)
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
files: (await Promise.all(Array.from(pairs.entries(), async ([mapPublic, pair]) => {
|
|
90
|
-
const mapContent = await readFile(pair.mapAbs, "utf8").catch(() => null);
|
|
91
|
-
if (mapContent === null) return null;
|
|
92
|
-
const debugId = pair.existingDebugId ?? randomUUID();
|
|
93
|
-
if (!pair.existingDebugId) {
|
|
94
|
-
const injectedJs = injectDebugIdIntoJs(pair.jsContent, debugId);
|
|
95
|
-
await writeFile(pair.jsAbs, injectedJs, "utf8");
|
|
96
|
-
}
|
|
97
|
-
const finalMap = JSON.parse(mapContent)["debugId"] === debugId ? mapContent : injectDebugIdIntoMap(mapContent, debugId);
|
|
98
|
-
if (finalMap !== mapContent) await writeFile(pair.mapAbs, finalMap, "utf8");
|
|
99
|
-
return {
|
|
100
|
-
absolute: pair.mapAbs,
|
|
101
|
-
path: mapPublic,
|
|
102
|
-
content: finalMap,
|
|
103
|
-
hash: createHash("sha256").update(finalMap).digest("hex"),
|
|
104
|
-
debugId,
|
|
105
|
-
chunkUrl: pair.jsPublic
|
|
106
|
-
};
|
|
107
|
-
}))).filter((f) => f !== null),
|
|
108
|
-
sourceFileCount: pairs.size
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
//#endregion
|
|
112
|
-
export { discoverWebpack, injectDebugIdIntoJs, injectDebugIdIntoMap, readDebugIdFromJs };
|
|
1
|
+
import{resolveDistDir,toPublicPath,walkDistTrees}from"./paths.mjs";import{relative}from"node:path";import{createHash,randomUUID}from"node:crypto";import{readFile,writeFile}from"node:fs/promises";const SOURCEMAPPING_RE=/\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/,SPEC_LAST_DEBUG_ID_RE=/\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;function readDebugIdFromJs(content){return SPEC_LAST_DEBUG_ID_RE.exec(content)?.[1]??null}function injectDebugIdIntoJs(content,debugId){let debugIdComment=`//# debugId=${debugId}`;if(SPEC_LAST_DEBUG_ID_RE.test(content))return content.replace(SPEC_LAST_DEBUG_ID_RE,debugIdComment);let match=SOURCEMAPPING_RE.exec(content);return match?`${content.slice(0,match.index).trimEnd()}\n${debugIdComment}\n${match[0]}`:`${content}\n${debugIdComment}`}function injectDebugIdIntoMap(content,debugId){let json=JSON.parse(content);return json.debugId=debugId,JSON.stringify(json)}async function discoverWebpack(opts){let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),relDistDir=relative(opts.projectDir,absDistDir),jsPaths=await walkDistTrees(absDistDir,`.js`),pairs=new Map;for(let jsAbs of jsPaths){let content=await readFile(jsAbs,`utf8`),match=SOURCEMAPPING_RE.exec(content);if(!match?.[1])continue;let mapAbs=`${jsAbs.slice(0,jsAbs.lastIndexOf(`/`)+1)}${decodeURIComponent(match[1])}`,jsPublic=toPublicPath(relative(opts.projectDir,jsAbs),relDistDir),mapPublic=toPublicPath(relative(opts.projectDir,mapAbs),relDistDir);pairs.set(mapPublic,{mapAbs,jsAbs,jsPublic,jsContent:content,existingDebugId:readDebugIdFromJs(content)})}return{files:(await Promise.all(Array.from(pairs.entries(),async([mapPublic,pair])=>{let mapContent=await readFile(pair.mapAbs,`utf8`).catch(()=>null);if(mapContent===null)return null;let debugId=pair.existingDebugId??randomUUID();if(!pair.existingDebugId){let injectedJs=injectDebugIdIntoJs(pair.jsContent,debugId);await writeFile(pair.jsAbs,injectedJs,`utf8`)}let finalMap=JSON.parse(mapContent).debugId===debugId?mapContent:injectDebugIdIntoMap(mapContent,debugId);return finalMap!==mapContent&&await writeFile(pair.mapAbs,finalMap,`utf8`),{absolute:pair.mapAbs,path:mapPublic,content:finalMap,hash:createHash(`sha256`).update(finalMap).digest(`hex`),debugId,chunkUrl:pair.jsPublic}}))).filter(f=>f!==null),sourceFileCount:pairs.size}}export{discoverWebpack,injectDebugIdIntoJs,injectDebugIdIntoMap,readDebugIdFromJs};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-webpack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst SOURCEMAPPING_RE = /\\/\\/[#@]\\s*sourceMappingURL=(\\S+)\\s*$/;\n\n/**\n * Per the TC39 sourcemap-debug-id proposal, the LAST `//# debugId=…`\n * comment in the bundle is the canonical one. Same regex Sentry uses\n * to detect spec-compliant debug IDs already injected by another tool\n * (webpack 5.104+ `SourceMapDevToolPlugin({ debugIds: true })`,\n * turbopack `experimental.turbopack.debugIds`, rollup, vite, etc.).\n */\nconst SPEC_LAST_DEBUG_ID_RE =\n /\\/\\/# debugId=([a-fA-F0-9-]+)(?![\\s\\S]*\\/\\/# debugId=)/m;\n\n/**\n * Reads an existing `//# debugId=…` comment from the bundle source.\n * Returns `null` when no debug ID comment is present — the caller is\n * expected to generate and inject one.\n */\nexport function readDebugIdFromJs(content: string): string | null {\n const match = SPEC_LAST_DEBUG_ID_RE.exec(content);\n return match?.[1] ?? null;\n}\n\n/**\n * Inserts a `//# debugId=…` comment into the chunk. Idempotent: if a\n * spec-compliant comment is already present (e.g. webpack 5.104+ with\n * `SourceMapDevToolPlugin({ debugIds: true })`, turbopack with\n * `experimental.turbopack.debugIds`, or any other tool) it's\n * overwritten with the supplied debugId — callers that read the\n * existing id via `readDebugIdFromJs` first get an idempotent no-op.\n *\n * Otherwise the comment is appended just before the existing\n * `//# sourceMappingURL=…` line so the browser still resolves the map.\n */\nexport function injectDebugIdIntoJs(content: string, debugId: string): string {\n const debugIdComment = `//# debugId=${debugId}`;\n\n if (SPEC_LAST_DEBUG_ID_RE.test(content)) {\n return content.replace(SPEC_LAST_DEBUG_ID_RE, debugIdComment);\n }\n\n const match = SOURCEMAPPING_RE.exec(content);\n if (match) {\n const before = content.slice(0, match.index).trimEnd();\n const sourceMappingLine = match[0];\n return `${before}\\n${debugIdComment}\\n${sourceMappingLine}`;\n }\n\n return `${content}\\n${debugIdComment}`;\n}\n\n/**\n * Adds `debugId` to the source-map JSON. Idempotent: writes both\n * `debugId` (TC39 spec field) and `debug_id` (legacy variant some\n * older Sentry tooling emits) so manifests stay readable across the\n * ecosystem. Re-running with the same id produces identical output.\n */\nexport function injectDebugIdIntoMap(content: string, debugId: string): string {\n const json = JSON.parse(content) as Record<string, unknown>;\n json[\"debugId\"] = debugId;\n return JSON.stringify(json);\n}\n\n/**\n * Webpack-mode discovery: walks the dist tree, parses each `.js`\n * chunk's `//# sourceMappingURL=…` comment to find its paired `.map`,\n * and ensures both carry the same `debugId`.\n *\n * Idempotent w.r.t. debug-id state on disk:\n * - If the chunk already carries a `//# debugId=…` comment (webpack\n * 5.104+ with `SourceMapDevToolPlugin({ debugIds: true })`, or a\n * third-party tool that already injected one) we reuse it.\n * - Otherwise we generate a fresh UUID and inject it into both files.\n *\n * The \"reuse if present\" branch matches the strategy in Sentry's\n * webpack plugin (`addDebugIdToBundleSource` in\n * `bundler-plugin-core/src/debug-id-upload.ts`) and means our\n * discovery works transparently when bundlers natively emit debugIds.\n */\nexport async function discoverWebpack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const jsPaths = await walkDistTrees(absDistDir, \".js\");\n\n const pairs = new Map<\n string,\n {\n mapAbs: string;\n jsAbs: string;\n jsPublic: string;\n jsContent: string;\n existingDebugId: string | null;\n }\n >();\n\n for (const jsAbs of jsPaths) {\n const content = await readFile(jsAbs, \"utf8\");\n const match = SOURCEMAPPING_RE.exec(content);\n if (!match?.[1]) {\n continue;\n }\n\n const jsDir = jsAbs.slice(0, jsAbs.lastIndexOf(\"/\") + 1);\n const mapRef = decodeURIComponent(match[1]);\n const mapAbs = `${jsDir}${mapRef}`;\n const jsPublic = toPublicPath(relative(opts.projectDir, jsAbs), relDistDir);\n const mapPublic = toPublicPath(\n relative(opts.projectDir, mapAbs),\n relDistDir\n );\n\n pairs.set(mapPublic, {\n mapAbs,\n jsAbs,\n jsPublic,\n jsContent: content,\n existingDebugId: readDebugIdFromJs(content),\n });\n }\n\n const files = await Promise.all(\n Array.from(\n pairs.entries(),\n async ([mapPublic, pair]): Promise<SourceMapFile | null> => {\n const mapContent = await readFile(pair.mapAbs, \"utf8\").catch(\n () => null\n );\n if (mapContent === null) {\n return null;\n }\n\n const debugId = pair.existingDebugId ?? randomUUID();\n\n // Skip the rewrite when the bundler already injected the\n // canonical debug-id comment + source-map field (webpack\n // native debugIds, turbopack, etc.). Re-running with the\n // same id is a no-op anyway, but skipping the I/O is faster\n // and keeps file mtimes stable for incremental builds.\n if (!pair.existingDebugId) {\n const injectedJs = injectDebugIdIntoJs(pair.jsContent, debugId);\n await writeFile(pair.jsAbs, injectedJs, \"utf8\");\n }\n\n const mapJson = JSON.parse(mapContent) as Record<string, unknown>;\n const finalMap =\n mapJson[\"debugId\"] === debugId\n ? mapContent\n : injectDebugIdIntoMap(mapContent, debugId);\n if (finalMap !== mapContent) {\n await writeFile(pair.mapAbs, finalMap, \"utf8\");\n }\n\n return {\n absolute: pair.mapAbs,\n path: mapPublic,\n content: finalMap,\n hash: createHash(\"sha256\").update(finalMap).digest(\"hex\"),\n debugId,\n chunkUrl: pair.jsPublic,\n };\n }\n )\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: pairs.size,\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"discover-webpack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst SOURCEMAPPING_RE = /\\/\\/[#@]\\s*sourceMappingURL=(\\S+)\\s*$/;\n\n/**\n * Per the TC39 sourcemap-debug-id proposal, the LAST `//# debugId=…`\n * comment in the bundle is the canonical one. Same regex Sentry uses\n * to detect spec-compliant debug IDs already injected by another tool\n * (webpack 5.104+ `SourceMapDevToolPlugin({ debugIds: true })`,\n * turbopack `experimental.turbopack.debugIds`, rollup, vite, etc.).\n */\nconst SPEC_LAST_DEBUG_ID_RE =\n /\\/\\/# debugId=([a-fA-F0-9-]+)(?![\\s\\S]*\\/\\/# debugId=)/m;\n\n/**\n * Reads an existing `//# debugId=…` comment from the bundle source.\n * Returns `null` when no debug ID comment is present — the caller is\n * expected to generate and inject one.\n */\nexport function readDebugIdFromJs(content: string): string | null {\n const match = SPEC_LAST_DEBUG_ID_RE.exec(content);\n return match?.[1] ?? null;\n}\n\n/**\n * Inserts a `//# debugId=…` comment into the chunk. Idempotent: if a\n * spec-compliant comment is already present (e.g. webpack 5.104+ with\n * `SourceMapDevToolPlugin({ debugIds: true })`, turbopack with\n * `experimental.turbopack.debugIds`, or any other tool) it's\n * overwritten with the supplied debugId — callers that read the\n * existing id via `readDebugIdFromJs` first get an idempotent no-op.\n *\n * Otherwise the comment is appended just before the existing\n * `//# sourceMappingURL=…` line so the browser still resolves the map.\n */\nexport function injectDebugIdIntoJs(content: string, debugId: string): string {\n const debugIdComment = `//# debugId=${debugId}`;\n\n if (SPEC_LAST_DEBUG_ID_RE.test(content)) {\n return content.replace(SPEC_LAST_DEBUG_ID_RE, debugIdComment);\n }\n\n const match = SOURCEMAPPING_RE.exec(content);\n if (match) {\n const before = content.slice(0, match.index).trimEnd();\n const sourceMappingLine = match[0];\n return `${before}\\n${debugIdComment}\\n${sourceMappingLine}`;\n }\n\n return `${content}\\n${debugIdComment}`;\n}\n\n/**\n * Adds `debugId` to the source-map JSON. Idempotent: writes both\n * `debugId` (TC39 spec field) and `debug_id` (legacy variant some\n * older Sentry tooling emits) so manifests stay readable across the\n * ecosystem. Re-running with the same id produces identical output.\n */\nexport function injectDebugIdIntoMap(content: string, debugId: string): string {\n const json = JSON.parse(content) as Record<string, unknown>;\n json[\"debugId\"] = debugId;\n return JSON.stringify(json);\n}\n\n/**\n * Webpack-mode discovery: walks the dist tree, parses each `.js`\n * chunk's `//# sourceMappingURL=…` comment to find its paired `.map`,\n * and ensures both carry the same `debugId`.\n *\n * Idempotent w.r.t. debug-id state on disk:\n * - If the chunk already carries a `//# debugId=…` comment (webpack\n * 5.104+ with `SourceMapDevToolPlugin({ debugIds: true })`, or a\n * third-party tool that already injected one) we reuse it.\n * - Otherwise we generate a fresh UUID and inject it into both files.\n *\n * The \"reuse if present\" branch matches the strategy in Sentry's\n * webpack plugin (`addDebugIdToBundleSource` in\n * `bundler-plugin-core/src/debug-id-upload.ts`) and means our\n * discovery works transparently when bundlers natively emit debugIds.\n */\nexport async function discoverWebpack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const jsPaths = await walkDistTrees(absDistDir, \".js\");\n\n const pairs = new Map<\n string,\n {\n mapAbs: string;\n jsAbs: string;\n jsPublic: string;\n jsContent: string;\n existingDebugId: string | null;\n }\n >();\n\n for (const jsAbs of jsPaths) {\n const content = await readFile(jsAbs, \"utf8\");\n const match = SOURCEMAPPING_RE.exec(content);\n if (!match?.[1]) {\n continue;\n }\n\n const jsDir = jsAbs.slice(0, jsAbs.lastIndexOf(\"/\") + 1);\n const mapRef = decodeURIComponent(match[1]);\n const mapAbs = `${jsDir}${mapRef}`;\n const jsPublic = toPublicPath(relative(opts.projectDir, jsAbs), relDistDir);\n const mapPublic = toPublicPath(\n relative(opts.projectDir, mapAbs),\n relDistDir\n );\n\n pairs.set(mapPublic, {\n mapAbs,\n jsAbs,\n jsPublic,\n jsContent: content,\n existingDebugId: readDebugIdFromJs(content),\n });\n }\n\n const files = await Promise.all(\n Array.from(\n pairs.entries(),\n async ([mapPublic, pair]): Promise<SourceMapFile | null> => {\n const mapContent = await readFile(pair.mapAbs, \"utf8\").catch(\n () => null\n );\n if (mapContent === null) {\n return null;\n }\n\n const debugId = pair.existingDebugId ?? randomUUID();\n\n // Skip the rewrite when the bundler already injected the\n // canonical debug-id comment + source-map field (webpack\n // native debugIds, turbopack, etc.). Re-running with the\n // same id is a no-op anyway, but skipping the I/O is faster\n // and keeps file mtimes stable for incremental builds.\n if (!pair.existingDebugId) {\n const injectedJs = injectDebugIdIntoJs(pair.jsContent, debugId);\n await writeFile(pair.jsAbs, injectedJs, \"utf8\");\n }\n\n const mapJson = JSON.parse(mapContent) as Record<string, unknown>;\n const finalMap =\n mapJson[\"debugId\"] === debugId\n ? mapContent\n : injectDebugIdIntoMap(mapContent, debugId);\n if (finalMap !== mapContent) {\n await writeFile(pair.mapAbs, finalMap, \"utf8\");\n }\n\n return {\n absolute: pair.mapAbs,\n path: mapPublic,\n content: finalMap,\n hash: createHash(\"sha256\").update(finalMap).digest(\"hex\"),\n debugId,\n chunkUrl: pair.jsPublic,\n };\n }\n )\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: pairs.size,\n };\n}\n"],"mappings":"mMAOA,MAAM,iBAAmB,wCASnB,sBACJ,0DAOF,SAAgB,kBAAkB,QAAgC,CAEhE,OADc,sBAAsB,KAAK,OAC9B,IAAI,IAAM,IACvB,CAaA,SAAgB,oBAAoB,QAAiB,QAAyB,CAC5E,IAAM,eAAiB,eAAe,UAEtC,GAAI,sBAAsB,KAAK,OAAO,EACpC,OAAO,QAAQ,QAAQ,sBAAuB,cAAc,EAG9D,IAAM,MAAQ,iBAAiB,KAAK,OAAO,EAO3C,OANI,MAGK,GAFQ,QAAQ,MAAM,EAAG,MAAM,KAAK,EAAE,QAE9B,EAAE,IAAI,eAAe,IADV,MAAM,KAI3B,GAAG,QAAQ,IAAI,gBACxB,CAQA,SAAgB,qBAAqB,QAAiB,QAAyB,CAC7E,IAAM,KAAO,KAAK,MAAM,OAAO,EAE/B,MADA,MAAK,QAAa,QACX,KAAK,UAAU,IAAI,CAC5B,CAkBA,eAAsB,gBAAgB,KAG2B,CAC/D,IAAM,WAAa,eAAe,KAAK,WAAY,KAAK,OAAO,EACzD,WAAa,SAAS,KAAK,WAAY,UAAU,EAEjD,QAAU,MAAM,cAAc,WAAY,KAAK,EAE/C,MAAQ,IAAI,IAWlB,IAAK,IAAM,SAAS,QAAS,CAC3B,IAAM,QAAU,MAAM,SAAS,MAAO,MAAM,EACtC,MAAQ,iBAAiB,KAAK,OAAO,EAC3C,GAAI,CAAC,QAAQ,GACX,SAKF,IAAM,OAAS,GAFD,MAAM,MAAM,EAAG,MAAM,YAAY,GAAG,EAAI,CAEhC,IADP,mBAAmB,MAAM,EACT,IACzB,SAAW,aAAa,SAAS,KAAK,WAAY,KAAK,EAAG,UAAU,EACpE,UAAY,aAChB,SAAS,KAAK,WAAY,MAAM,EAChC,UACF,EAEA,MAAM,IAAI,UAAW,CACnB,OACA,MACA,SACA,UAAW,QACX,gBAAiB,kBAAkB,OAAO,CAC5C,CAAC,CACH,CAgDA,MAAO,CACL,OAHa,MA5CK,QAAQ,IAC1B,MAAM,KACJ,MAAM,QAAQ,EACd,MAAO,CAAC,UAAW,QAAyC,CAC1D,IAAM,WAAa,MAAM,SAAS,KAAK,OAAQ,MAAM,EAAE,UAC/C,IACR,EACA,GAAI,aAAe,KACjB,OAAO,KAGT,IAAM,QAAU,KAAK,iBAAmB,WAAW,EAOnD,GAAI,CAAC,KAAK,gBAAiB,CACzB,IAAM,WAAa,oBAAoB,KAAK,UAAW,OAAO,EAC9D,MAAM,UAAU,KAAK,MAAO,WAAY,MAAM,CAChD,CAGA,IAAM,SADU,KAAK,MAAM,UAEnB,EAAE,UAAe,QACnB,WACA,qBAAqB,WAAY,OAAO,EAK9C,OAJI,WAAa,YACf,MAAM,UAAU,KAAK,OAAQ,SAAU,MAAM,EAGxC,CACL,SAAU,KAAK,OACf,KAAM,UACN,QAAS,SACT,KAAM,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK,EACxD,QACA,SAAU,KAAK,QACjB,CACF,CACF,CACF,GAEqB,OAAQ,GAA0B,IAAM,IAG/C,EACZ,gBAAiB,MAAM,IACzB,CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { NextBuildBundler } from "../detect-bundler.mjs";
|
|
1
2
|
import { injectDebugIdIntoJs, injectDebugIdIntoMap } from "./discover-webpack.mjs";
|
|
2
|
-
import { ManifestBundler } from "@interfere/types/data/source-maps";
|
|
3
3
|
|
|
4
4
|
//#region src/internal/build/source-maps/discover.d.ts
|
|
5
5
|
interface SourceMapFile {
|
|
@@ -25,11 +25,11 @@ interface DiscoveryResult {
|
|
|
25
25
|
* Single entry point for source-map discovery. The pipeline calls this
|
|
26
26
|
* with the active bundler from `detectActiveBundler()`; new bundlers (e.g.
|
|
27
27
|
* rspack) drop in here as additional cases without touching the pipeline.
|
|
28
|
-
*
|
|
29
|
-
* pipeline and
|
|
28
|
+
* Other manifest bundlers (for Vite, CLI, etc.) live outside the Next
|
|
29
|
+
* build pipeline and should use their own discovery implementation.
|
|
30
30
|
*/
|
|
31
31
|
declare function discoverSourceMaps(opts: {
|
|
32
|
-
bundler:
|
|
32
|
+
bundler: NextBuildBundler;
|
|
33
33
|
projectDir: string;
|
|
34
34
|
distDir: string;
|
|
35
35
|
}): Promise<DiscoveryResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"discover.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"mappings":";;;;UAKiB,aAAA;EAAA,SACN,QAAA;;AADX;;;;;;WASW,QAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;AAAA;AAAA,UAGM,eAAA;EAAA,SACN,KAAA,EAAO,aAAa;EAAA,SACpB,eAAA;AAAA;;;;;AAAe;AAU1B;;iBAAsB,kBAAA,CAAmB,IAAA;EACvC,OAAA,EAAS,gBAAA;EACT,UAAA;EACA,OAAA;AAAA,IACE,OAAA,CAAQ,eAAA"}
|
|
@@ -1,26 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { discoverTurbopack } from "./discover-turbopack.mjs";
|
|
3
|
-
import { discoverWebpack, injectDebugIdIntoJs, injectDebugIdIntoMap } from "./discover-webpack.mjs";
|
|
4
|
-
//#region src/internal/build/source-maps/discover.ts
|
|
5
|
-
/**
|
|
6
|
-
* Single entry point for source-map discovery. The pipeline calls this
|
|
7
|
-
* with the active bundler from `detectActiveBundler()`; new bundlers (e.g.
|
|
8
|
-
* rspack) drop in here as additional cases without touching the pipeline.
|
|
9
|
-
* `"tsc"` is excluded — non-bundler producers live outside the Next build
|
|
10
|
-
* pipeline and go through `@interfere/cli` instead.
|
|
11
|
-
*/
|
|
12
|
-
async function discoverSourceMaps(opts) {
|
|
13
|
-
const distDir = normalizeDistDir(opts.distDir);
|
|
14
|
-
switch (opts.bundler) {
|
|
15
|
-
case "webpack": return discoverWebpack({
|
|
16
|
-
projectDir: opts.projectDir,
|
|
17
|
-
distDir
|
|
18
|
-
});
|
|
19
|
-
case "turbopack": return discoverTurbopack({
|
|
20
|
-
projectDir: opts.projectDir,
|
|
21
|
-
distDir
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
export { discoverSourceMaps, injectDebugIdIntoJs, injectDebugIdIntoMap };
|
|
1
|
+
import{normalizeDistDir}from"./paths.mjs";import{discoverTurbopack}from"./discover-turbopack.mjs";import{discoverWebpack,injectDebugIdIntoJs,injectDebugIdIntoMap}from"./discover-webpack.mjs";async function discoverSourceMaps(opts){let distDir=normalizeDistDir(opts.distDir);switch(opts.bundler){case`webpack`:return discoverWebpack({projectDir:opts.projectDir,distDir});case`turbopack`:return discoverTurbopack({projectDir:opts.projectDir,distDir})}}export{discoverSourceMaps,injectDebugIdIntoJs,injectDebugIdIntoMap};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"discover.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"sourcesContent":["import type { NextBuildBundler } from \"../detect-bundler.js\";\nimport { discoverTurbopack } from \"./discover-turbopack.js\";\nimport { discoverWebpack } from \"./discover-webpack.js\";\nimport { normalizeDistDir } from \"./paths.js\";\n\nexport interface SourceMapFile {\n readonly absolute: string;\n /**\n * Public URL the runtime will load this chunk from. ALWAYS populated\n * for both bundlers — turbopack discovery walks JS chunks (in addition\n * to .map files) so it can record this. Lifted onto the manifest as\n * `chunkUrl`; server-side suffix-matching pairs `frame.fileName` to\n * this field by content-hashed filename.\n */\n readonly chunkUrl: string;\n readonly content: string;\n readonly debugId: string;\n readonly hash: string;\n readonly path: string;\n}\n\nexport interface DiscoveryResult {\n readonly files: SourceMapFile[];\n readonly sourceFileCount: number;\n}\n\n/**\n * Single entry point for source-map discovery. The pipeline calls this\n * with the active bundler from `detectActiveBundler()`; new bundlers (e.g.\n * rspack) drop in here as additional cases without touching the pipeline.\n * Other manifest bundlers (for Vite, CLI, etc.) live outside the Next\n * build pipeline and should use their own discovery implementation.\n */\nexport async function discoverSourceMaps(opts: {\n bundler: NextBuildBundler;\n projectDir: string;\n distDir: string;\n}): Promise<DiscoveryResult> {\n const distDir = normalizeDistDir(opts.distDir);\n switch (opts.bundler) {\n case \"webpack\":\n return discoverWebpack({ projectDir: opts.projectDir, distDir });\n case \"turbopack\":\n return discoverTurbopack({ projectDir: opts.projectDir, distDir });\n }\n}\n\nexport {\n injectDebugIdIntoJs,\n injectDebugIdIntoMap,\n} from \"./discover-webpack.js\";\n"],"mappings":"+LAiCA,eAAsB,mBAAmB,KAIZ,CAC3B,IAAM,QAAU,iBAAiB,KAAK,OAAO,EAC7C,OAAQ,KAAK,QAAb,CACE,IAAK,UACH,OAAO,gBAAgB,CAAE,WAAY,KAAK,WAAY,OAAQ,CAAC,EACjE,IAAK,YACH,OAAO,kBAAkB,CAAE,WAAY,KAAK,WAAY,OAAQ,CAAC,CACrE,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"mappings":";;;;iBAKsB,iBAAA,CAAkB,KAAA,EAAO,aAAA,KAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"mappings":";;;;iBAKsB,iBAAA,CAAkB,KAAA,EAAO,aAAA,KAAkB,OAAO"}
|
|
@@ -1,18 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { uploadSourceMaps } from "./upload.mjs";
|
|
3
|
-
import { unlink } from "node:fs/promises";
|
|
4
|
-
//#region src/internal/build/source-maps/index.ts
|
|
5
|
-
async function cleanupSourceMaps(files) {
|
|
6
|
-
const results = await Promise.allSettled(files.map((f) => unlink(f.absolute)));
|
|
7
|
-
const failures = [];
|
|
8
|
-
for (const [i, r] of results.entries()) {
|
|
9
|
-
if (r.status !== "rejected") continue;
|
|
10
|
-
const err = r.reason;
|
|
11
|
-
if (err.code === "ENOENT") continue;
|
|
12
|
-
const file = files[i];
|
|
13
|
-
failures.push(`${file?.absolute ?? "<unknown>"}: ${err.code ?? err.message ?? String(err)}`);
|
|
14
|
-
}
|
|
15
|
-
if (failures.length > 0) log.warn("Source-map cleanup left files on disk", failures);
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
export { cleanupSourceMaps, uploadSourceMaps };
|
|
1
|
+
import{log}from"../../logger.mjs";import{uploadSourceMaps}from"./upload.mjs";import{unlink}from"node:fs/promises";async function cleanupSourceMaps(files){let results=await Promise.allSettled(files.map(f=>unlink(f.absolute))),failures=[];for(let[i,r]of results.entries()){if(r.status!==`rejected`)continue;let err=r.reason;if(err.code===`ENOENT`)continue;let file=files[i];failures.push(`${file?.absolute??`<unknown>`}: ${err.code??err.message??String(err)}`)}failures.length>0&&log.warn(`Source-map cleanup left files on disk`,failures)}export{cleanupSourceMaps,uploadSourceMaps};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"sourcesContent":["import { unlink } from \"node:fs/promises\";\n\nimport { log } from \"../../logger.js\";\nimport type { SourceMapFile } from \"./discover.js\";\n\nexport async function cleanupSourceMaps(files: SourceMapFile[]): Promise<void> {\n // ENOENT is the only failure we silently absorb — a missing file just\n // means the upload-then-cleanup race lost. Anything else (perm, IO,\n // EBUSY) is a real signal: the source map is now stranded on the\n // customer's CDN and we surface it via a single aggregated warning so\n // an operator can investigate without the build failing outright.\n const results = await Promise.allSettled(files.map((f) => unlink(f.absolute)));\n const failures: string[] = [];\n for (const [i, r] of results.entries()) {\n if (r.status !== \"rejected\") {\n continue;\n }\n const err = r.reason as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") {\n continue;\n }\n const file = files[i];\n failures.push(\n `${file?.absolute ?? \"<unknown>\"}: ${err.code ?? err.message ?? String(err)}`\n );\n }\n if (failures.length > 0) {\n log.warn(\"Source-map cleanup left files on disk\", failures);\n }\n}\n\nexport { uploadSourceMaps } from \"./upload.js\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"sourcesContent":["import { unlink } from \"node:fs/promises\";\n\nimport { log } from \"../../logger.js\";\nimport type { SourceMapFile } from \"./discover.js\";\n\nexport async function cleanupSourceMaps(files: SourceMapFile[]): Promise<void> {\n // ENOENT is the only failure we silently absorb — a missing file just\n // means the upload-then-cleanup race lost. Anything else (perm, IO,\n // EBUSY) is a real signal: the source map is now stranded on the\n // customer's CDN and we surface it via a single aggregated warning so\n // an operator can investigate without the build failing outright.\n const results = await Promise.allSettled(files.map((f) => unlink(f.absolute)));\n const failures: string[] = [];\n for (const [i, r] of results.entries()) {\n if (r.status !== \"rejected\") {\n continue;\n }\n const err = r.reason as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") {\n continue;\n }\n const file = files[i];\n failures.push(\n `${file?.absolute ?? \"<unknown>\"}: ${err.code ?? err.message ?? String(err)}`\n );\n }\n if (failures.length > 0) {\n log.warn(\"Source-map cleanup left files on disk\", failures);\n }\n}\n\nexport { uploadSourceMaps } from \"./upload.js\";\n"],"mappings":"kHAKA,eAAsB,kBAAkB,MAAuC,CAM7E,IAAM,QAAU,MAAM,QAAQ,WAAW,MAAM,IAAK,GAAM,OAAO,EAAE,QAAQ,CAAC,CAAC,EACvE,SAAqB,CAAC,EAC5B,IAAK,GAAM,CAAC,EAAG,KAAM,QAAQ,QAAQ,EAAG,CACtC,GAAI,EAAE,SAAW,WACf,SAEF,IAAM,IAAM,EAAE,OACd,GAAI,IAAI,OAAS,SACf,SAEF,IAAM,KAAO,MAAM,GACnB,SAAS,KACP,GAAG,MAAM,UAAY,YAAY,IAAI,IAAI,MAAQ,IAAI,SAAW,OAAO,GAAG,GAC5E,CACF,CACI,SAAS,OAAS,GACpB,IAAI,KAAK,wCAAyC,QAAQ,CAE9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"mappings":";;AAUA;;;iBAAgB,gBAAA,CAAiB,
|
|
1
|
+
{"version":3,"file":"paths.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"mappings":";;AAUA;;;iBAAgB,gBAAA,CAAiB,OAAiB;AAAA;AASlD;;;;AATkD,iBASlC,cAAA,CAAe,UAAA,UAAoB,OAAe;AASlE;;;;AAAyD;AAAzD,iBAAgB,YAAA,CAAa,GAAA,UAAa,OAAe;;;;;;;;iBAkBnC,aAAA,CACpB,UAAA,UACA,MAAA,sBACC,OAAO"}
|
|
@@ -1,49 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { readdir } from "node:fs/promises";
|
|
3
|
-
//#region src/internal/build/source-maps/paths.ts
|
|
4
|
-
const NEXT_PUBLIC_PREFIX = "_next/";
|
|
5
|
-
const NEXT_DIST_PREFIX = ".next/";
|
|
6
|
-
/**
|
|
7
|
-
* Strips Windows path separators and leading `./` segments so the rest of
|
|
8
|
-
* the discovery code can assume POSIX-style paths relative to `projectDir`.
|
|
9
|
-
*/
|
|
10
|
-
function normalizeDistDir(distDir = ".next") {
|
|
11
|
-
return distDir.replaceAll("\\", "/").replace(/^(\.\/)+/, "");
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Resolves an absolute filesystem path for the build's `distDir`. Accepts
|
|
15
|
-
* either an absolute path (passed through) or a path relative to
|
|
16
|
-
* `projectDir`.
|
|
17
|
-
*/
|
|
18
|
-
function resolveDistDir(projectDir, distDir) {
|
|
19
|
-
return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Maps an on-disk path (relative to `projectDir`) to the URL path Next.js
|
|
23
|
-
* will serve it at. Both `_next/` and `.next/` shapes resolve to the public
|
|
24
|
-
* `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.
|
|
25
|
-
*/
|
|
26
|
-
function toPublicPath(rel, distDir) {
|
|
27
|
-
const p = rel.replaceAll("\\", "/");
|
|
28
|
-
if (p.startsWith(`${distDir}/`)) return `${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length + 1)}`;
|
|
29
|
-
if (p.startsWith(NEXT_DIST_PREFIX)) return `${NEXT_PUBLIC_PREFIX}${p.slice(6)}`;
|
|
30
|
-
return p;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Recursively collects files under `<absDistDir>/static` and
|
|
34
|
-
* `<absDistDir>/server` matching the given suffix. Both subtrees are
|
|
35
|
-
* optional — partial builds (e.g. server-only chunks during ISR) commonly
|
|
36
|
-
* leave one missing, so a missing directory is treated as empty rather
|
|
37
|
-
* than fatal.
|
|
38
|
-
*/
|
|
39
|
-
async function walkDistTrees(absDistDir, suffix) {
|
|
40
|
-
return (await Promise.all(["static", "server"].map(async (subtree) => {
|
|
41
|
-
const root = join(absDistDir, subtree);
|
|
42
|
-
const entries = await readdir(root, { recursive: true }).catch(() => []);
|
|
43
|
-
const out = [];
|
|
44
|
-
for (const entry of entries) if (typeof entry === "string" && entry.endsWith(suffix)) out.push(join(root, entry));
|
|
45
|
-
return out;
|
|
46
|
-
}))).flat();
|
|
47
|
-
}
|
|
48
|
-
//#endregion
|
|
49
|
-
export { normalizeDistDir, resolveDistDir, toPublicPath, walkDistTrees };
|
|
1
|
+
import{isAbsolute,join,resolve}from"node:path";import{readdir}from"node:fs/promises";const NEXT_PUBLIC_PREFIX=`_next/`;function normalizeDistDir(distDir=`.next`){return distDir.replaceAll(`\\`,`/`).replace(/^(\.\/)+/,``)}function resolveDistDir(projectDir,distDir){return isAbsolute(distDir)?distDir:resolve(projectDir,distDir)}function toPublicPath(rel,distDir){let p=rel.replaceAll(`\\`,`/`);return p.startsWith(`${distDir}/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length+1)}`:p.startsWith(`.next/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(6)}`:p}async function walkDistTrees(absDistDir,suffix){return(await Promise.all([`static`,`server`].map(async subtree=>{let root=join(absDistDir,subtree),entries=await readdir(root,{recursive:!0}).catch(()=>[]),out=[];for(let entry of entries)typeof entry==`string`&&entry.endsWith(suffix)&&out.push(join(root,entry));return out}))).flat()}export{normalizeDistDir,resolveDistDir,toPublicPath,walkDistTrees};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nconst NEXT_PUBLIC_PREFIX = \"_next/\";\nconst NEXT_DIST_PREFIX = \".next/\";\n\n/**\n * Strips Windows path separators and leading `./` segments so the rest of\n * the discovery code can assume POSIX-style paths relative to `projectDir`.\n */\nexport function normalizeDistDir(distDir = \".next\"): string {\n return distDir.replaceAll(\"\\\\\", \"/\").replace(/^(\\.\\/)+/, \"\");\n}\n\n/**\n * Resolves an absolute filesystem path for the build's `distDir`. Accepts\n * either an absolute path (passed through) or a path relative to\n * `projectDir`.\n */\nexport function resolveDistDir(projectDir: string, distDir: string): string {\n return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);\n}\n\n/**\n * Maps an on-disk path (relative to `projectDir`) to the URL path Next.js\n * will serve it at. Both `_next/` and `.next/` shapes resolve to the public\n * `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.\n */\nexport function toPublicPath(rel: string, distDir: string): string {\n const p = rel.replaceAll(\"\\\\\", \"/\");\n if (p.startsWith(`${distDir}/`)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length + 1)}`;\n }\n if (p.startsWith(NEXT_DIST_PREFIX)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(NEXT_DIST_PREFIX.length)}`;\n }\n return p;\n}\n\n/**\n * Recursively collects files under `<absDistDir>/static` and\n * `<absDistDir>/server` matching the given suffix. Both subtrees are\n * optional — partial builds (e.g. server-only chunks during ISR) commonly\n * leave one missing, so a missing directory is treated as empty rather\n * than fatal.\n */\nexport async function walkDistTrees(\n absDistDir: string,\n suffix: \".js\" | \".js.map\"\n): Promise<string[]> {\n const subtrees = [\"static\", \"server\"] as const;\n\n const results = await Promise.all(\n subtrees.map(async (subtree) => {\n const root = join(absDistDir, subtree);\n const entries = await readdir(root, { recursive: true }).catch(\n () => [] as string[]\n );\n const out: string[] = [];\n for (const entry of entries) {\n if (typeof entry === \"string\" && entry.endsWith(suffix)) {\n out.push(join(root, entry));\n }\n }\n return out;\n })\n );\n\n return results.flat();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nconst NEXT_PUBLIC_PREFIX = \"_next/\";\nconst NEXT_DIST_PREFIX = \".next/\";\n\n/**\n * Strips Windows path separators and leading `./` segments so the rest of\n * the discovery code can assume POSIX-style paths relative to `projectDir`.\n */\nexport function normalizeDistDir(distDir = \".next\"): string {\n return distDir.replaceAll(\"\\\\\", \"/\").replace(/^(\\.\\/)+/, \"\");\n}\n\n/**\n * Resolves an absolute filesystem path for the build's `distDir`. Accepts\n * either an absolute path (passed through) or a path relative to\n * `projectDir`.\n */\nexport function resolveDistDir(projectDir: string, distDir: string): string {\n return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);\n}\n\n/**\n * Maps an on-disk path (relative to `projectDir`) to the URL path Next.js\n * will serve it at. Both `_next/` and `.next/` shapes resolve to the public\n * `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.\n */\nexport function toPublicPath(rel: string, distDir: string): string {\n const p = rel.replaceAll(\"\\\\\", \"/\");\n if (p.startsWith(`${distDir}/`)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length + 1)}`;\n }\n if (p.startsWith(NEXT_DIST_PREFIX)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(NEXT_DIST_PREFIX.length)}`;\n }\n return p;\n}\n\n/**\n * Recursively collects files under `<absDistDir>/static` and\n * `<absDistDir>/server` matching the given suffix. Both subtrees are\n * optional — partial builds (e.g. server-only chunks during ISR) commonly\n * leave one missing, so a missing directory is treated as empty rather\n * than fatal.\n */\nexport async function walkDistTrees(\n absDistDir: string,\n suffix: \".js\" | \".js.map\"\n): Promise<string[]> {\n const subtrees = [\"static\", \"server\"] as const;\n\n const results = await Promise.all(\n subtrees.map(async (subtree) => {\n const root = join(absDistDir, subtree);\n const entries = await readdir(root, { recursive: true }).catch(\n () => [] as string[]\n );\n const out: string[] = [];\n for (const entry of entries) {\n if (typeof entry === \"string\" && entry.endsWith(suffix)) {\n out.push(join(root, entry));\n }\n }\n return out;\n })\n );\n\n return results.flat();\n}\n"],"mappings":"qFAGA,MAAM,mBAAqB,SAO3B,SAAgB,iBAAiB,QAAU,QAAiB,CAC1D,OAAO,QAAQ,WAAW,KAAM,GAAG,EAAE,QAAQ,WAAY,EAAE,CAC7D,CAOA,SAAgB,eAAe,WAAoB,QAAyB,CAC1E,OAAO,WAAW,OAAO,EAAI,QAAU,QAAQ,WAAY,OAAO,CACpE,CAOA,SAAgB,aAAa,IAAa,QAAyB,CACjE,IAAM,EAAI,IAAI,WAAW,KAAM,GAAG,EAOlC,OANI,EAAE,WAAW,GAAG,QAAQ,EAAE,EACrB,GAAG,qBAAqB,EAAE,MAAM,QAAQ,OAAS,CAAC,IAEvD,EAAE,WAAW,QAAgB,EACxB,GAAG,qBAAqB,EAAE,MAAM,CAAuB,IAEzD,CACT,CASA,eAAsB,cACpB,WACA,OACmB,CAmBnB,OAAO,MAhBe,QAAQ,IAC5B,CAHgB,SAAU,QAGnB,EAAE,IAAI,KAAO,UAAY,CAC9B,IAAM,KAAO,KAAK,WAAY,OAAO,EAC/B,QAAU,MAAM,QAAQ,KAAM,CAAE,UAAW,EAAK,CAAC,EAAE,UACjD,CAAC,CACT,EACM,IAAgB,CAAC,EACvB,IAAK,IAAM,SAAS,QACd,OAAO,OAAU,UAAY,MAAM,SAAS,MAAM,GACpD,IAAI,KAAK,KAAK,KAAM,KAAK,CAAC,EAG9B,OAAO,GACT,CAAC,CACH,GAEe,KAAK,CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/upload.ts"],"mappings":";;;;;;UAciB,YAAA;EACf,SAAA;EACA,
|
|
1
|
+
{"version":3,"file":"upload.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/upload.ts"],"mappings":";;;;;;UAciB,YAAA;EACf,SAAA;EACA,UAAU;AAAA;AAAA,UAGF,YAAA;EACR,MAAA;EACA,OAAA,EAAS,eAAA;EACT,UAAA,EAAY,eAAA;EACZ,UAAA,EAAY,UAAA;EACZ,WAAA,EAAa,WAAA;AAAA;;;;;;;;;;;;;;iBAgBO,gBAAA,CAAA;EACpB,MAAA;EACA,OAAA;EACA,UAAA;EACA,UAAA;EACA;AAAA,GACC,YAAA,GAAe,OAAA,CAAQ,YAAA;AAAA,UAoEhB,iBAAA;EACR,iBAAA;EACA,QAAA;EACA,OAAA;EACA,eAAA;AAAA;AAAA,iBAyBc,eAAA,CAAgB,OAAA,WAAkB,iBAAiB"}
|