{"version":3,"file":"transform.cjs","names":["getByteSize","getChunkId"],"sources":["../src/transform.ts"],"sourcesContent":["import path from 'path';\nimport type {\n Stats,\n AssetStats,\n ChunkStats,\n ModuleStats,\n} from 'rollup-plugin-stats/extract';\n\nimport { getByteSize, getChunkId } from './utils';\n\n// https://github.com/relative-ci/bundle-stats/blob/master/packages/plugin-webpack-filter/src/index.ts\nexport type WebpackStatsFilteredAsset = {\n name: string;\n size?: number;\n};\n\nexport interface WebpackStatsFilteredChunk {\n id: number | string;\n entry: boolean;\n initial: boolean;\n files?: Array;\n names?: Array;\n}\n\nexport interface WebpackStatsFilteredModule {\n name: string;\n size?: number;\n chunks: Array;\n}\n\nexport interface WebpackStatsFilteredConcatenatedModule {\n name: string;\n size?: number;\n}\n\nexport interface WebpackStatsFilteredRootModule extends WebpackStatsFilteredModule {\n modules?: Array;\n}\n\nexport interface WebpackStatsFiltered {\n builtAt: number;\n hash?: string;\n assets: Array;\n chunks: Array;\n modules: Array;\n}\n\nexport type ChunksIssuers = Record>;\n\n/**\n * Recursivily check if a chunk is async based on the chunks issuers\n */\nexport const lookupChunkAsync = (\n chunksIssuers: ChunksIssuers,\n chunk: ChunkStats,\n processedChunks: Array = []\n): boolean => {\n // When the chunks are having a circular dependency, return true to continue the recursive check\n if (processedChunks.includes(chunk.fileName)) {\n return true;\n }\n\n if (chunk.isEntry) {\n return false;\n }\n\n if (chunk.isDynamicEntry) {\n return true;\n }\n\n const chunkIssuers = chunksIssuers[chunk.fileName];\n\n /**\n * A sync chunk without issuer chunks, is sync\n */\n if (!chunkIssuers) {\n return false;\n }\n\n const syncChunksIssuers = chunkIssuers.filter((chunkIssuer) => {\n return chunkIssuer.isDynamicEntry === false;\n });\n\n /**\n * A sync chunk with all the chunk issuer async, is async\n */\n if (syncChunksIssuers.length === 0) {\n return true;\n }\n\n /**\n * Recursively lookup for sync loads on the 2nd level issuers\n * - if at least one issuer is sync, the chunk is sync\n * - if none of the issuers are sync, the chunk is async\n */\n let isAsync = true;\n\n for (let i = 0; i < syncChunksIssuers.length && isAsync; i++) {\n isAsync = lookupChunkAsync(chunksIssuers, syncChunksIssuers[i], [\n ...processedChunks,\n chunk.fileName,\n ]);\n }\n\n return isAsync;\n};\n\ntype AssetSource = ChunkStats | AssetStats;\ntype ChunkSource = ChunkStats;\ntype ModuleSource = { fileName: string } & ModuleStats;\n\n/**\n * Store transformed sources\n */\nclass TransformSources {\n constructor() {\n this.entries = {};\n }\n\n entries: Record = {};\n\n push(id: string, source: AssetSource | ChunkSource | ModuleSource) {\n this.entries[id] = source;\n }\n\n /**\n * Get asset source\n */\n getByAsset = (asset: WebpackStatsFilteredAsset): AssetSource => {\n return this.entries[asset.name] as AssetSource;\n };\n\n /**\n * Get chunk source\n */\n getByChunk = (chunk: WebpackStatsFilteredChunk): ChunkSource => {\n return this.entries[chunk.id] as ChunkSource;\n };\n\n /**\n * Get module source\n */\n getByModule = (module: WebpackStatsFilteredModule): ModuleSource => {\n return this.entries[module.name] as ModuleSource;\n };\n}\n\nexport type TransformCallback = (\n stats: WebpackStatsFiltered,\n sources: TransformSources,\n bundle: Stats\n) => WebpackStatsFiltered;\n\nconst defaultTransform: TransformCallback = (stats) => stats;\n\nexport type BundleTransformOptions = {\n /**\n * Extract module original size or rendered size\n * default: false\n */\n moduleOriginalSize?: boolean;\n /**\n * Callback function to access and mutate the resulting stats after the transformation\n */\n transform?: TransformCallback;\n};\n\nexport const bundleToWebpackStats = (\n bundle: Stats,\n pluginOptions?: BundleTransformOptions\n): WebpackStatsFiltered => {\n const options = {\n moduleOriginalSize: false,\n ...pluginOptions,\n } satisfies BundleTransformOptions;\n const { moduleOriginalSize, transform = defaultTransform } = options;\n\n const assets: Array = [];\n const chunks: Array = [];\n const moduleByFileName: Record = {};\n const sources = new TransformSources();\n const chunksIssuers: ChunksIssuers = {};\n\n const entries = Object.values(bundle);\n\n // Collect metadata\n entries.forEach((entry) => {\n if (entry.type === 'chunk') {\n entry.imports?.forEach((chunkImportFileName) => {\n // Skip circular references\n if (\n chunksIssuers[entry.fileName]?.find(\n (chunkIssuer) => chunkIssuer.fileName === chunkImportFileName\n )\n ) {\n return;\n }\n\n if (!chunksIssuers[chunkImportFileName]) {\n chunksIssuers[chunkImportFileName] = [];\n }\n\n chunksIssuers[chunkImportFileName].push(entry);\n });\n }\n });\n\n // Process data\n entries.forEach((entry) => {\n if (entry.type === 'chunk') {\n assets.push({\n name: entry.fileName,\n size: getByteSize(entry.code),\n });\n sources.push(entry.fileName, entry);\n\n const chunkId = getChunkId(entry);\n const chunkAsync = lookupChunkAsync(chunksIssuers, entry);\n\n chunks.push({\n id: chunkId,\n entry: entry.isEntry,\n initial: !chunkAsync,\n files: [entry.fileName],\n names: [entry.name],\n });\n sources.push(chunkId, entry);\n\n Object.entries(entry.modules).forEach(([modulePath, moduleInfo]) => {\n // Remove unexpected rollup null prefix\n const normalizedModulePath = modulePath.replace('\\u0000', '');\n\n const relativeModulePath = path.relative(\n process.cwd(),\n normalizedModulePath\n );\n\n // Match webpack output - add current directory prefix for child modules\n const relativeModulePathWithPrefix = relativeModulePath.match(/^\\.\\./)\n ? relativeModulePath\n : `.${path.sep}${relativeModulePath}`;\n\n const moduleEntry = moduleByFileName[relativeModulePathWithPrefix];\n\n if (moduleEntry) {\n moduleEntry.chunks.push(chunkId);\n } else {\n moduleByFileName[relativeModulePathWithPrefix] = {\n name: relativeModulePathWithPrefix,\n size: moduleOriginalSize\n ? moduleInfo.originalLength\n : moduleInfo.renderedLength,\n chunks: [chunkId],\n };\n sources.push(relativeModulePathWithPrefix, {\n fileName: modulePath,\n ...moduleInfo,\n });\n }\n });\n } else if (entry.type === 'asset') {\n assets.push({\n name: entry.fileName,\n size: getByteSize(entry.source),\n });\n sources.push(entry.fileName, entry);\n } else {\n // noop for unknown types\n }\n });\n\n const stats: WebpackStatsFiltered = {\n builtAt: Date.now(),\n assets,\n chunks,\n modules: Object.values(moduleByFileName),\n };\n\n let result: WebpackStatsFiltered;\n\n try {\n result = transform(stats, sources, bundle);\n } catch (error) {\n console.error(\n 'Custom transform failed! Returning stats without any transforms.',\n error\n );\n result = stats;\n }\n\n return result;\n};\n"],"mappings":";;;;;;;;;;AAoDA,MAAa,oBACX,eACA,OACA,kBAAiC,EAAE,KACvB;AAEZ,KAAI,gBAAgB,SAAS,MAAM,SAAS,CAC1C,QAAO;AAGT,KAAI,MAAM,QACR,QAAO;AAGT,KAAI,MAAM,eACR,QAAO;CAGT,MAAM,eAAe,cAAc,MAAM;;;;AAKzC,KAAI,CAAC,aACH,QAAO;CAGT,MAAM,oBAAoB,aAAa,QAAQ,gBAAgB;AAC7D,SAAO,YAAY,mBAAmB;GACtC;;;;AAKF,KAAI,kBAAkB,WAAW,EAC/B,QAAO;;;;;;CAQT,IAAI,UAAU;AAEd,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,UAAU,SAAS,IACvD,WAAU,iBAAiB,eAAe,kBAAkB,IAAI,CAC9D,GAAG,iBACH,MAAM,SACP,CAAC;AAGJ,QAAO;;;;;AAUT,IAAM,mBAAN,MAAuB;CACrB,cAAc;AACZ,OAAK,UAAU,EAAE;;CAGnB,UAAmC,EAAE;CAErC,KAAK,IAAY,QAAkD;AACjE,OAAK,QAAQ,MAAM;;;;;CAMrB,cAAc,UAAkD;AAC9D,SAAO,KAAK,QAAQ,MAAM;;;;;CAM5B,cAAc,UAAkD;AAC9D,SAAO,KAAK,QAAQ,MAAM;;;;;CAM5B,eAAe,WAAqD;AAClE,SAAO,KAAK,QAAQ,OAAO;;;AAU/B,MAAM,oBAAuC,UAAU;AAcvD,MAAa,wBACX,QACA,kBACyB;CAKzB,MAAM,EAAE,oBAAoB,YAAY,qBAJxB;EACd,oBAAoB;EACpB,GAAG;EACJ;CAGD,MAAM,SAA2C,EAAE;CACnD,MAAM,SAA2C,EAAE;CACnD,MAAM,mBAA+D,EAAE;CACvE,MAAM,UAAU,IAAI,kBAAkB;CACtC,MAAM,gBAA+B,EAAE;CAEvC,MAAM,UAAU,OAAO,OAAO,OAAO;AAGrC,SAAQ,SAAS,UAAU;AACzB,MAAI,MAAM,SAAS,QACjB,OAAM,SAAS,SAAS,wBAAwB;AAE9C,OACE,cAAc,MAAM,WAAW,MAC5B,gBAAgB,YAAY,aAAa,oBAC3C,CAED;AAGF,OAAI,CAAC,cAAc,qBACjB,eAAc,uBAAuB,EAAE;AAGzC,iBAAc,qBAAqB,KAAK,MAAM;IAC9C;GAEJ;AAGF,SAAQ,SAAS,UAAU;AACzB,MAAI,MAAM,SAAS,SAAS;AAC1B,UAAO,KAAK;IACV,MAAM,MAAM;IACZ,MAAMA,0BAAY,MAAM,KAAK;IAC9B,CAAC;AACF,WAAQ,KAAK,MAAM,UAAU,MAAM;GAEnC,MAAM,UAAUC,yBAAW,MAAM;GACjC,MAAM,aAAa,iBAAiB,eAAe,MAAM;AAEzD,UAAO,KAAK;IACV,IAAI;IACJ,OAAO,MAAM;IACb,SAAS,CAAC;IACV,OAAO,CAAC,MAAM,SAAS;IACvB,OAAO,CAAC,MAAM,KAAK;IACpB,CAAC;AACF,WAAQ,KAAK,SAAS,MAAM;AAE5B,UAAO,QAAQ,MAAM,QAAQ,CAAC,SAAS,CAAC,YAAY,gBAAgB;IAElE,MAAM,uBAAuB,WAAW,QAAQ,MAAU,GAAG;IAE7D,MAAM,qBAAqB,aAAK,SAC9B,QAAQ,KAAK,EACb,qBACD;IAGD,MAAM,+BAA+B,mBAAmB,MAAM,QAAQ,GAClE,qBACA,IAAI,aAAK,MAAM;IAEnB,MAAM,cAAc,iBAAiB;AAErC,QAAI,YACF,aAAY,OAAO,KAAK,QAAQ;SAC3B;AACL,sBAAiB,gCAAgC;MAC/C,MAAM;MACN,MAAM,qBACF,WAAW,iBACX,WAAW;MACf,QAAQ,CAAC,QAAQ;MAClB;AACD,aAAQ,KAAK,8BAA8B;MACzC,UAAU;MACV,GAAG;MACJ,CAAC;;KAEJ;aACO,MAAM,SAAS,SAAS;AACjC,UAAO,KAAK;IACV,MAAM,MAAM;IACZ,MAAMD,0BAAY,MAAM,OAAO;IAChC,CAAC;AACF,WAAQ,KAAK,MAAM,UAAU,MAAM;;GAIrC;CAEF,MAAM,QAA8B;EAClC,SAAS,KAAK,KAAK;EACnB;EACA;EACA,SAAS,OAAO,OAAO,iBAAiB;EACzC;CAED,IAAI;AAEJ,KAAI;AACF,WAAS,UAAU,OAAO,SAAS,OAAO;UACnC,OAAO;AACd,UAAQ,MACN,oEACA,MACD;AACD,WAAS;;AAGX,QAAO"}