npm package diff

Package: @forge/bundler

Versions: 6.1.2-next.1 - 6.1.2-next.0-experimental-8a53773

File: package/out/webpack.js

Index: package/out/webpack.js
===================================================================
--- package/out/webpack.js
+++ package/out/webpack.js
@@ -1,11 +1,16 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.WebpackBundler = exports.getCompiler = exports.handleWebpackCompilationResult = void 0;
 const tslib_1 = require("tslib");
+const fs_1 = require("fs");
+const path_1 = tslib_1.__importDefault(require("path"));
+const parser = tslib_1.__importStar(require("@babel/parser"));
+const traverse_1 = tslib_1.__importDefault(require("@babel/traverse"));
 const webpack_1 = tslib_1.__importDefault(require("webpack"));
 const cli_shared_1 = require("@forge/cli-shared");
 const text_1 = require("./text");
+const types_1 = require("./types");
 function handleWebpackCompilationResult(logger, err, stats) {
     if (err) {
         throw err;
     }
@@ -35,38 +40,113 @@
 function getCompiler(config) {
     return (0, webpack_1.default)(config);
 }
 exports.getCompiler = getCompiler;
-function getNodeModuleNames(stats) {
-    const { modules } = stats.toJson({ modules: true });
-    if (modules) {
-        const filteredModuleNames = new Set();
-        modules
-            .map((m) => m.name || '')
-            .forEach((name) => {
-            const parts = name.match(/^\.\/node_modules\/([^/]+)\/([^/]+)/);
-            if (parts) {
-                const module = parts[1][0] === '@' ? `${parts[1]}/${parts[2]}` : parts[1];
-                filteredModuleNames.add(module);
+function moduleFromPath(name) {
+    const depMatch = name.match(/^\.\/node_modules\/([^/]+)\/([^/]+)/);
+    if (depMatch) {
+        const moduleName = depMatch[1][0] === '@' ? `${depMatch[1]}/${depMatch[2]}` : depMatch[1];
+        return { type: 'dependency', package: moduleName };
+    }
+    const externalMatch = name.match(/^external "(?:node:)?([^:"]+)"$/);
+    if (externalMatch) {
+        return { type: 'dependency', package: externalMatch[1].split('/')[0] };
+    }
+    if (name.startsWith('webpack/runtime/')) {
+        return { type: 'internal' };
+    }
+    if (!name.includes('.js') && !name.includes('.ts')) {
+        throw new Error(`Unknown module type for ${JSON.stringify(name)}.`);
+    }
+    return { type: 'local', path: name };
+}
+function processModule(metadata, module) {
+    if (module.modules) {
+        for (const subModule of module.modules) {
+            processModule(metadata, subModule);
+        }
+        return;
+    }
+    if (!module.name) {
+        throw new Error('Module name is missing');
+    }
+    const packedModule = moduleFromPath(module.name);
+    const issuerModule = module.issuerName ? moduleFromPath(module.issuerName) : undefined;
+    if (packedModule.type === 'local') {
+        const ext = path_1.default.extname(packedModule.path);
+        if (ext.match(/^\.[cm]?jsx?$/)) {
+            metadata.jsFiles++;
+        }
+        else if (ext.match(/^\.[cm]?tsx?$/)) {
+            metadata.tsFiles++;
+        }
+        else if (ext === '.json') {
+            return;
+        }
+        const source = (0, fs_1.readFileSync)(packedModule.path, 'utf8');
+        const ast = parser.parse(source, {
+            sourceType: 'module',
+            plugins: ['typescript', 'jsx']
+        });
+        (0, traverse_1.default)(ast, {
+            ImportDeclaration: (path) => {
+                let from = path.node.source.value;
+                if (from.startsWith('@forge/')) {
+                    from = from.replace('@forge/', '');
+                    for (const specifier of path.node.specifiers) {
+                        let member;
+                        switch (specifier.type) {
+                            case 'ImportDefaultSpecifier':
+                                member = specifier.local.name;
+                                break;
+                            case 'ImportNamespaceSpecifier':
+                                member = specifier.local.name;
+                                break;
+                            case 'ImportSpecifier':
+                                switch (specifier.imported.type) {
+                                    case 'Identifier':
+                                        member = specifier.imported.name;
+                                        break;
+                                    case 'StringLiteral':
+                                        member = specifier.imported.value;
+                                        break;
+                                }
+                        }
+                        metadata.sdkImports.add(`${from}.${member}`);
+                    }
+                }
             }
-            else if (name.includes('unsupported.js')) {
-                filteredModuleNames.add(name.slice(name.indexOf('?')));
-            }
         });
-        return Array.from(filteredModuleNames);
     }
+    if (issuerModule?.type === 'local' && packedModule.type === 'dependency') {
+        metadata.dependencies.add(packedModule.package);
+    }
 }
+function getMetadata(stats) {
+    const { modules } = stats.toJson({ modules: true });
+    const metadata = (0, types_1.emptyMetadata)();
+    for (const module of modules ?? []) {
+        processModule(metadata, module);
+    }
+    let packageJson;
+    try {
+        const packageFile = (0, fs_1.readFileSync)('package.json', 'utf8');
+        packageJson = JSON.parse(packageFile);
+    }
+    catch { }
+    if (packageJson?.type === 'module') {
+        metadata.esm = true;
+    }
+    return metadata;
+}
 class WebpackBundler {
     logger;
     constructor(logger) {
         this.logger = logger;
     }
     async getOutput(config, stats) {
         const outputDir = config.output.path;
-        const metadata = {};
-        if (stats) {
-            metadata.modules = getNodeModuleNames(stats);
-        }
+        const metadata = getMetadata(stats);
         return { outputDir, metadata };
     }
     async runCompiler(config) {
         const compiler = getCompiler(config);