{"version":3,"file":"webpack.mjs","names":[],"sources":["../../src/webpack.ts"],"sourcesContent":["import type { Compiler } from 'webpack';\nimport { fileURLToPath } from 'url';\nimport { dirname, resolve } from 'path';\nimport { createHash } from 'crypto';\nimport {\n    type CodeTransformerPluginOptions,\n} from './core.js';\nimport { serializeInstrumentations } from './instrumentation-serde.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// dist/esm/webpack.mjs → dist/cjs/webpack-loader.cjs\n// dist/cjs/webpack.cjs → dist/cjs/webpack-loader.cjs\nconst LOADER_PATH = resolve(__dirname, '..', 'cjs', 'webpack-loader.cjs');\nconst DIAGNOSTICS_STATE_KEY = '__codeTransformerWebpackDiagnostics';\n\nexport interface CodeTransformerWebpackPluginOptions extends CodeTransformerPluginOptions {\n    /**\n     * The loader webpack should run, as a resolved path or a specifier\n     * resolvable from the compiler's context. Defaults to this package's own\n     * loader.\n     *\n     * Point this at a loader module built with `createLoader` from the\n     * `/webpack-loader-factory` export when loader options cannot carry\n     * `customTransforms` — under Turbopack, or with worker-based loaders such\n     * as `thread-loader`, which serialize them.\n     */\n    loaderPath?: string;\n    /**\n     * An arbitrary string folded into the loader's cache key, for use with\n     * `cache: { type: 'filesystem' }`.\n     *\n     * The key already covers the instrumentations and the source text of every\n     * custom transform, so editing either invalidates cached modules. What it\n     * cannot see is data a transform reads without naming it — a captured\n     * variable, or a module-scope table of snippets. Bump this when such data\n     * changes, or derive it from the data itself.\n     */\n    cacheVersion?: string;\n}\n\n/**\n * A stable identity for a set of loader options.\n *\n * Webpack keys a loader by its ruleset ident, not by the contents of its\n * options, so with `cache: { type: 'filesystem' }` a changed config would\n * otherwise reuse modules built by the previous one. Deriving the ident from\n * the options makes the module identifier change with them.\n *\n * A transform's captured variables are invisible to `toString`, so a factory\n * that returns textually identical functions for different inputs still hashes\n * the same. `cacheVersion` is the escape hatch for that; binding the transforms\n * with `createLoader` is the other, since webpack tracks the loader file's own\n * contents.\n */\nfunction loaderIdent(\n    options: {\n        instrumentations: unknown;\n        dcModule?: string;\n        customTransforms?: Record<string, (...args: any[]) => void>;\n    },\n    cacheVersion?: string,\n): string {\n    const hash = createHash('sha256');\n\n    hash.update(JSON.stringify(options.instrumentations));\n    hash.update(options.dcModule ?? '');\n    hash.update(cacheVersion ?? '');\n\n    for (const name of Object.keys(options.customTransforms ?? {}).sort()) {\n        hash.update(name);\n        hash.update(String(options.customTransforms?.[name]));\n    }\n\n    return `code-transformer-${hash.digest('hex').slice(0, 16)}`;\n}\n\ntype DiagnosticsState = {\n    transformedModules: Set<string>;\n    failedModules: Set<string>;\n};\n\n/**\n * Asset names of the chunk holding each entry module. Deliberately not\n * `entrypoint.getFiles()`, which also lists the initial chunks an entry\n * depends on, and not `compilation.getAssets()`, which lists async chunks too.\n */\nfunction entryAssetNames(compilation: any): Set<string> {\n    const names = new Set<string>();\n\n    for (const entrypoint of compilation.entrypoints.values()) {\n        const chunk = entrypoint.getEntrypointChunk?.();\n\n        for (const file of chunk?.files ?? []) {\n            names.add(file);\n        }\n    }\n\n    return names;\n}\n\nclass CodeTransformerWebpackPlugin {\n    private readonly options: CodeTransformerWebpackPluginOptions;\n\n    constructor(options: CodeTransformerWebpackPluginOptions) {\n        this.options = options;\n    }\n\n    apply(compiler: Compiler) {\n        const webpack = (compiler as any).webpack;\n\n        compiler.options.module = compiler.options.module || ({ rules: [] } as any);\n        compiler.options.module.rules = compiler.options.module.rules || [];\n\n        // Pass only what the loader reads. Webpack hands loader options to the\n        // loader by reference, so `customTransforms` arrives intact; everything\n        // else stays JSON-serializable, keeping the options usable as-is by\n        // bundlers that serialize them (e.g. Turbopack) when no custom\n        // transforms are configured.\n        const loaderOptions = {\n            instrumentations: serializeInstrumentations(this.options.instrumentations),\n            ...(this.options.dcModule ? { dcModule: this.options.dcModule } : {}),\n            ...(this.options.customTransforms\n                ? { customTransforms: this.options.customTransforms }\n                : {}),\n        };\n\n        compiler.options.module.rules.unshift({\n            test: /\\.(c|m)?jsx?$|\\.tsx?$/,\n            enforce: 'pre',\n            use: [\n                {\n                    loader: this.options.loaderPath ?? LOADER_PATH,\n                    options: loaderOptions,\n                    // Without this webpack derives the ident from the rule's\n                    // position, so a persistent cache survives a config change.\n                    ident: loaderIdent(loaderOptions, this.options.cacheVersion),\n                },\n            ],\n        });\n\n        if (this.options.injectDiagnostics) {\n            const ConcatSource = webpack?.sources?.ConcatSource;\n\n            if (ConcatSource && webpack?.Compilation) {\n                compiler.hooks.thisCompilation.tap('code-transformer', (compilation: any) => {\n                    compilation[DIAGNOSTICS_STATE_KEY] = {\n                        transformedModules: new Set<string>(),\n                        failedModules: new Set<string>(),\n                    } satisfies DiagnosticsState;\n\n                    compilation.hooks.processAssets.tap(\n                        {\n                            name: 'code-transformer',\n                            stage: webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,\n                        },\n                        () => {\n                            const state: DiagnosticsState | undefined = compilation[DIAGNOSTICS_STATE_KEY];\n\n                            if (!state) {\n                                return;\n                            }\n\n                            const injectCode = this.options.injectDiagnostics?.({\n                                transformedModules: Array.from(state.transformedModules),\n                                failedModules: Array.from(state.failedModules),\n                            });\n\n                            if (!injectCode) {\n                                return;\n                            }\n\n                            for (const assetName of entryAssetNames(compilation)) {\n                                if (!/\\.(js|ts|jsx|tsx|mjs|cjs)(\\?[^?]*)?(#[^#]*)?$/.test(assetName)) {\n                                    continue;\n                                }\n\n                                compilation.updateAsset(\n                                    assetName,\n                                    (source: any) => new ConcatSource(injectCode, source),\n                                );\n                            }\n                        },\n                    );\n                });\n            }\n        }\n    }\n}\n\nexport default function codeTransformerWebpack(\n    options: CodeTransformerWebpackPluginOptions,\n): CodeTransformerWebpackPlugin {\n    return new CodeTransformerWebpackPlugin(options);\n}\n\nexport type { CodeTransformerPluginOptions } from './core.js';\n"],"mappings":";;;;;AAaA,IAAM,cAAc,QAJF,QAAQ,cAAc,OAAO,KAAK,GAAG,CAI3B,GAAW,MAAM,OAAO,oBAAoB;AACxE,IAAM,wBAAwB;;;;;;;;;;;;;;;AAyC9B,SAAS,YACL,SAKA,cACM;CACN,MAAM,OAAO,WAAW,QAAQ;CAEhC,KAAK,OAAO,KAAK,UAAU,QAAQ,gBAAgB,CAAC;CACpD,KAAK,OAAO,QAAQ,YAAY,EAAE;CAClC,KAAK,OAAO,gBAAgB,EAAE;CAE9B,KAAK,MAAM,QAAQ,OAAO,KAAK,QAAQ,oBAAoB,CAAC,CAAC,EAAE,KAAK,GAAG;EACnE,KAAK,OAAO,IAAI;EAChB,KAAK,OAAO,OAAO,QAAQ,mBAAmB,KAAK,CAAC;CACxD;CAEA,OAAO,oBAAoB,KAAK,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC7D;;;;;;AAYA,SAAS,gBAAgB,aAA+B;CACpD,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,cAAc,YAAY,YAAY,OAAO,GAAG;EACvD,MAAM,QAAQ,WAAW,qBAAqB;EAE9C,KAAK,MAAM,QAAQ,OAAO,SAAS,CAAC,GAChC,MAAM,IAAI,IAAI;CAEtB;CAEA,OAAO;AACX;AAEA,IAAM,+BAAN,MAAmC;CAG/B,YAAY,SAA8C;EACtD,KAAK,UAAU;CACnB;CAEA,MAAM,UAAoB;EACtB,MAAM,UAAW,SAAiB;EAElC,SAAS,QAAQ,SAAS,SAAS,QAAQ,UAAW,EAAE,OAAO,CAAC,EAAE;EAClE,SAAS,QAAQ,OAAO,QAAQ,SAAS,QAAQ,OAAO,SAAS,CAAC;EAOlE,MAAM,gBAAgB;GAClB,kBAAkB,0BAA0B,KAAK,QAAQ,gBAAgB;GACzE,GAAI,KAAK,QAAQ,WAAW,EAAE,UAAU,KAAK,QAAQ,SAAS,IAAI,CAAC;GACnE,GAAI,KAAK,QAAQ,mBACX,EAAE,kBAAkB,KAAK,QAAQ,iBAAiB,IAClD,CAAC;EACX;EAEA,SAAS,QAAQ,OAAO,MAAM,QAAQ;GAClC,MAAM;GACN,SAAS;GACT,KAAK,CACD;IACI,QAAQ,KAAK,QAAQ,cAAc;IACnC,SAAS;IAGT,OAAO,YAAY,eAAe,KAAK,QAAQ,YAAY;GAC/D,CACJ;EACJ,CAAC;EAED,IAAI,KAAK,QAAQ,mBAAmB;GAChC,MAAM,eAAe,SAAS,SAAS;GAEvC,IAAI,gBAAgB,SAAS,aACzB,SAAS,MAAM,gBAAgB,IAAI,qBAAqB,gBAAqB;IACzE,YAAY,yBAAyB;KACjC,oCAAoB,IAAI,IAAY;KACpC,+BAAe,IAAI,IAAY;IACnC;IAEA,YAAY,MAAM,cAAc,IAC5B;KACI,MAAM;KACN,OAAO,QAAQ,YAAY;IAC/B,SACM;KACF,MAAM,QAAsC,YAAY;KAExD,IAAI,CAAC,OACD;KAGJ,MAAM,aAAa,KAAK,QAAQ,oBAAoB;MAChD,oBAAoB,MAAM,KAAK,MAAM,kBAAkB;MACvD,eAAe,MAAM,KAAK,MAAM,aAAa;KACjD,CAAC;KAED,IAAI,CAAC,YACD;KAGJ,KAAK,MAAM,aAAa,gBAAgB,WAAW,GAAG;MAClD,IAAI,CAAC,gDAAgD,KAAK,SAAS,GAC/D;MAGJ,YAAY,YACR,YACC,WAAgB,IAAI,aAAa,YAAY,MAAM,CACxD;KACJ;IACJ,CACJ;GACJ,CAAC;EAET;CACJ;AACJ;AAEA,SAAwB,uBACpB,SAC4B;CAC5B,OAAO,IAAI,6BAA6B,OAAO;AACnD"}