npm package diff

Package: @forge/bundler

Versions: 4.20.1-next.6 - 4.20.1-next.7

Removed: package/out/config/node.js

Removed: package/out/config/node.d.ts.map

Removed: package/out/config/node.d.ts

Added: package/out/nativeui.js

Added: package/out/runtime.js

Added: package/out/wrapper-provider.js

Added: package/out/nativeui.d.ts.map

Added: package/out/runtime.d.ts.map

Added: package/out/wrapper-provider.d.ts.map

Added: package/out/nativeui.d.ts

Added: package/out/runtime.d.ts

Added: package/out/wrapper-provider.d.ts

Modified: package/out/config/common.js

Index: package/out/config/common.js
===================================================================
--- package/out/config/common.js
+++ package/out/config/common.js
@@ -23,13 +23,13 @@
 function resolveStubPath(stubName) {
     return (0, exports.resolveModulePath)(`../stubs/${stubName}`);
 }
 exports.resolveStubPath = resolveStubPath;
-const getDevToolConfig = (config) => {
-    if (!config.isWatchMode) {
+const getDevToolConfig = ({ watchMode }) => {
+    if (!watchMode) {
         return 'source-map';
     }
-    return config.isDebugMode ? 'inline-source-map' : 'cheap-source-map';
+    return watchMode === 'debug' ? 'inline-source-map' : 'cheap-source-map';
 };
 exports.getDevToolConfig = getDevToolConfig;
 const geti18nRule = (i18nConfig) => {
     const i18nResources = i18nConfig.resources || [];
@@ -47,28 +47,30 @@
         }
     };
 };
 exports.geti18nRule = geti18nRule;
-const getCommonWebpackConfig = (entrypoints, config) => {
+const getCommonWebpackConfig = (args) => {
     if (!require.main) {
         throw new Error(text_1.Text.noExecutableFile);
     }
+    const { entryPoints, appDirectory } = args;
     const resolvedEntryPoints = {};
-    for (const entrypoint of entrypoints) {
+    for (const entrypoint of entryPoints) {
         resolvedEntryPoints[entrypoint.name] = path_1.default.resolve(entrypoint.path);
     }
+    const outputDir = args.watchMode === 'debug' ? path_1.default.resolve(cli_shared_1.TUNNEL_BUNDLE_DIRECTORY) : (0, cli_shared_1.tmpDir)('dist');
     return {
         entry: resolvedEntryPoints,
         mode: 'production',
         optimization: {
             minimize: false
         },
-        devtool: (0, exports.getDevToolConfig)(config),
+        devtool: (0, exports.getDevToolConfig)(args),
         output: {
             libraryTarget: 'commonjs',
             globalObject: 'this',
             filename: '[name].js',
-            path: config.outputDir
+            path: outputDir
         },
         node: {
             __dirname: true
         },
@@ -132,10 +134,10 @@
                                     jsx: 'react',
                                     jsxFactory: 'ForgeUI.createElement',
                                     sourceMap: true
                                 },
-                                configFile: new tsconfig_interactor_1.TSConfigInteractor(new cli_shared_1.FileSystemReader(), config.appDirectory).getTSConfigPath(),
-                                context: config.appDirectory,
+                                configFile: new tsconfig_interactor_1.TSConfigInteractor(new cli_shared_1.FileSystemReader(), appDirectory).getTSConfigPath(),
+                                context: appDirectory,
                                 onlyCompileBundledFiles: true
                             }
                         }
                     ]

Modified: package/out/index.js

Index: package/out/index.js
===================================================================
--- package/out/index.js
+++ package/out/index.js
@@ -1,20 +1,22 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.getSandboxedRuntimeBuildConfig = exports.LocalWrapperProvider = exports.getWrapperProvider = exports.getNodeRuntimeBuildConfig = exports.getNativeUiBuildConfig = exports.getEntryPoints = exports.runLinter = exports.handleWebpackCompilationResult = exports.getCompiler = exports.nativeUiBundle = exports.getNodeBundler = exports.getSandboxBundler = void 0;
+exports.LocalWrapperProvider = exports.getWrapperProvider = exports.getNativeUiBuildConfig = exports.getEntryPoints = exports.runLinter = exports.handleWebpackCompilationResult = exports.getCompiler = exports.BundlerError = exports.NODE_RUNTIME_VERSION_FILE = exports.NodeBundler = exports.SandboxBundler = exports.NativeUIBundler = void 0;
+var nativeui_1 = require("./nativeui");
+Object.defineProperty(exports, "NativeUIBundler", { enumerable: true, get: function () { return nativeui_1.NativeUIBundler; } });
+var runtime_1 = require("./runtime");
+Object.defineProperty(exports, "SandboxBundler", { enumerable: true, get: function () { return runtime_1.SandboxBundler; } });
+Object.defineProperty(exports, "NodeBundler", { enumerable: true, get: function () { return runtime_1.NodeBundler; } });
+Object.defineProperty(exports, "NODE_RUNTIME_VERSION_FILE", { enumerable: true, get: function () { return runtime_1.NODE_RUNTIME_VERSION_FILE; } });
+var types_1 = require("./types");
+Object.defineProperty(exports, "BundlerError", { enumerable: true, get: function () { return types_1.BundlerError; } });
 var webpack_1 = require("./webpack");
-Object.defineProperty(exports, "getSandboxBundler", { enumerable: true, get: function () { return webpack_1.getSandboxBundler; } });
-Object.defineProperty(exports, "getNodeBundler", { enumerable: true, get: function () { return webpack_1.getNodeBundler; } });
-Object.defineProperty(exports, "nativeUiBundle", { enumerable: true, get: function () { return webpack_1.nativeUiBundle; } });
 Object.defineProperty(exports, "getCompiler", { enumerable: true, get: function () { return webpack_1.getCompiler; } });
 Object.defineProperty(exports, "handleWebpackCompilationResult", { enumerable: true, get: function () { return webpack_1.handleWebpackCompilationResult; } });
 Object.defineProperty(exports, "runLinter", { enumerable: true, get: function () { return webpack_1.runLinter; } });
 var common_1 = require("./config/common");
 Object.defineProperty(exports, "getEntryPoints", { enumerable: true, get: function () { return common_1.getEntryPoints; } });
-var nativeui_1 = require("./config/nativeui");
-Object.defineProperty(exports, "getNativeUiBuildConfig", { enumerable: true, get: function () { return nativeui_1.getNativeUiBuildConfig; } });
-var node_1 = require("./config/node");
-Object.defineProperty(exports, "getNodeRuntimeBuildConfig", { enumerable: true, get: function () { return node_1.getNodeRuntimeBuildConfig; } });
-Object.defineProperty(exports, "getWrapperProvider", { enumerable: true, get: function () { return node_1.getWrapperProvider; } });
-Object.defineProperty(exports, "LocalWrapperProvider", { enumerable: true, get: function () { return node_1.LocalWrapperProvider; } });
-var sandbox_1 = require("./config/sandbox");
-Object.defineProperty(exports, "getSandboxedRuntimeBuildConfig", { enumerable: true, get: function () { return sandbox_1.getSandboxedRuntimeBuildConfig; } });
+var nativeui_2 = require("./config/nativeui");
+Object.defineProperty(exports, "getNativeUiBuildConfig", { enumerable: true, get: function () { return nativeui_2.getNativeUiBuildConfig; } });
+var wrapper_provider_1 = require("./wrapper-provider");
+Object.defineProperty(exports, "getWrapperProvider", { enumerable: true, get: function () { return wrapper_provider_1.getWrapperProvider; } });
+Object.defineProperty(exports, "LocalWrapperProvider", { enumerable: true, get: function () { return wrapper_provider_1.LocalWrapperProvider; } });

Modified: package/out/config/sandbox.js

Index: package/out/config/sandbox.js
===================================================================
--- package/out/config/sandbox.js
+++ package/out/config/sandbox.js
@@ -42,10 +42,10 @@
         stream: (0, common_1.resolveModulePath)('readable-stream'),
         'supports-color': (0, common_1.resolveModulePath)('supports-color/index.js')
     };
 };
-const getSandboxedRuntimeBuildConfig = (entrypoints, config) => {
-    const webpackConfig = (0, common_1.getCommonWebpackConfig)(entrypoints, config);
+const getSandboxedRuntimeBuildConfig = (args) => {
+    const webpackConfig = (0, common_1.getCommonWebpackConfig)(args);
     const sandboxedConfigPlugins = [
         new webpack_1.default.ProvidePlugin({
             Buffer: [(0, common_1.resolveModulePath)('buffer/'), 'Buffer'],
             path: (0, common_1.resolveModulePath)('path-browserify'),

Modified: package/out/types.js

Index: package/out/types.js
===================================================================
--- package/out/types.js
+++ package/out/types.js
@@ -1,2 +1,7 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
+exports.BundlerError = void 0;
+const cli_shared_1 = require("@forge/cli-shared");
+class BundlerError extends cli_shared_1.UserError {
+}
+exports.BundlerError = BundlerError;

Modified: package/out/webpack.js

Index: package/out/webpack.js
===================================================================
--- package/out/webpack.js
+++ package/out/webpack.js
@@ -1,16 +1,12 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.nativeUiBundle = exports.getNodeBundler = exports.getSandboxBundler = exports.createBundler = exports.runLinter = exports.getMetadata = exports.getCompiler = exports.handleWebpackCompilationResult = void 0;
+exports.WebpackBundler = exports.runLinter = 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 webpack_1 = tslib_1.__importDefault(require("webpack"));
 const cli_shared_1 = require("@forge/cli-shared");
 const lint_1 = require("@forge/lint");
-const nativeui_1 = require("./config/nativeui");
-const node_1 = require("./config/node");
-const sandbox_1 = require("./config/sandbox");
 const text_1 = require("./text");
 function handleWebpackCompilationResult(logger, err, stats) {
     if (err) {
         throw err;
@@ -60,19 +56,8 @@
         });
         return Array.from(filteredModuleNames);
     }
 }
-function getMetadata(config, stats) {
-    const metadata = {};
-    if (stats) {
-        metadata.modules = getNodeModuleNames(stats);
-    }
-    if (config.name === node_1.NODE_WEBPACK_CONFIG_NAME && config.output?.path) {
-        metadata.nodeRuntimeVersion = (0, fs_1.readFileSync)(path_1.default.join(config.output.path, node_1.NODE_RUNTIME_VERSION_FILE)).toString();
-    }
-    return metadata;
-}
-exports.getMetadata = getMetadata;
 const runLinter = async (logger = { info: console.log }, fileSystemReader = new cli_shared_1.FileSystemReader(), fileSystemWriter = new cli_shared_1.FileSystemWriter()) => {
     logger.info(`\n${cli_shared_1.Text.tunnel.preBundleTask(cli_shared_1.Text.lint.running)}`);
     const exclude = [...(await (0, cli_shared_1.listGitIgnoreFiles)(fileSystemReader)), '.git', 'node_modules'];
     const configFile = new cli_shared_1.ConfigFile(fileSystemReader, fileSystemWriter);
@@ -98,48 +83,74 @@
         logger.info(cli_shared_1.Text.tunnel.lintFailed + '\n');
     }
 };
 exports.runLinter = runLinter;
-function createBundler(getBuildConfig) {
-    return (logger, appDirectory, endpoints) => {
-        const outputDir = (0, cli_shared_1.tmpDir)('dist');
-        const config = getBuildConfig(endpoints, { isWatchMode: false, appDirectory, outputDir });
+class WebpackBundler {
+    logger;
+    constructor(logger) {
+        this.logger = logger;
+    }
+    getOutput(config, stats) {
+        const outputDir = config.output.path;
+        const metadata = {};
+        if (stats) {
+            metadata.modules = getNodeModuleNames(stats);
+        }
+        return { outputDir, metadata };
+    }
+    async runCompiler(config) {
         const compiler = getCompiler(config);
         return new Promise((resolve, reject) => {
             compiler.run((compilerError, stats) => {
                 try {
-                    handleWebpackCompilationResult(logger, compilerError, stats);
+                    handleWebpackCompilationResult(this.logger, compilerError, stats);
                     compiler.close((closeError) => {
                         if (closeError) {
                             reject(closeError);
                         }
                     });
-                    resolve({ outputDir, metadata: getMetadata(config, stats) });
+                    resolve(this.getOutput(config, stats));
                 }
                 catch (err) {
                     reject(err);
                 }
             });
         });
-    };
-}
-exports.createBundler = createBundler;
-const getSandboxBundler = () => createBundler(sandbox_1.getSandboxedRuntimeBuildConfig);
-exports.getSandboxBundler = getSandboxBundler;
-const getNodeBundler = (wrapperProvider) => createBundler((0, node_1.getNodeRuntimeBuildConfig)(wrapperProvider));
-exports.getNodeBundler = getNodeBundler;
-const nativeUiBundle = (logger, appDirectory, entrypoints, i18nConfig) => {
-    const config = (0, nativeui_1.getNativeUiBuildConfig)(entrypoints, i18nConfig);
-    const compiler = getCompiler(config);
-    return new Promise((resolve, reject) => {
-        compiler.run((compilerError, stats) => {
-            try {
-                handleWebpackCompilationResult(logger, compilerError, stats);
-                resolve({ outputDir: config.output.path });
+    }
+    async bundle(args) {
+        const config = this.getConfig(args);
+        return await this.runCompiler(config);
+    }
+    async watch(args, watch) {
+        const config = this.getConfig(args);
+        const compiler = getCompiler(config);
+        let isFirstRun = true;
+        compiler.hooks.watchRun.tapAsync('watchRun', async (_, watchRunCallback) => {
+            if (!isFirstRun) {
+                await watch.onBuildWillStart();
             }
-            catch (err) {
-                reject(err);
-            }
+            watchRunCallback();
         });
-    });
-};
-exports.nativeUiBundle = nativeUiBundle;
+        return new Promise((resolve, reject) => {
+            const watching = compiler.watch({ poll: 1000 }, async (compilerError, stats) => {
+                try {
+                    handleWebpackCompilationResult(this.logger, compilerError, stats);
+                    this.logger.info(cli_shared_1.LogColor.trace(args.successMessage));
+                    const result = this.getOutput(config, stats);
+                    if (isFirstRun) {
+                        isFirstRun = false;
+                        resolve({ result, stop: () => watching.close(() => void 0) });
+                    }
+                    else {
+                        await watch.onBuildFinished(null, result);
+                    }
+                }
+                catch (err) {
+                    await watch.onBuildFinished(err);
+                    isFirstRun = false;
+                    reject(err);
+                }
+            });
+        });
+    }
+}
+exports.WebpackBundler = WebpackBundler;

Modified: package/package.json

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/bundler",
-  "version": "4.20.1-next.6",
+  "version": "4.20.1-next.7",
   "description": "Default bundler for Forge apps",
   "license": "UNLICENSED",
   "author": "Atlassian",
   "main": "out/index.js",

Modified: package/out/config/common.d.ts.map

Index: package/out/config/common.d.ts.map
===================================================================
--- package/out/config/common.d.ts.map
+++ package/out/config/common.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/config/common.ts"],"names":[],"mappings":";AAEA,OAAgB,EAAE,aAAa,IAAI,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAoB,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK/C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oBAAY,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAOhE;AAED,eAAO,MAAM,iBAAiB,eAAgB,MAAM,KAAG,MAEtD,CAAC;AAEF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,eAAO,MAAM,gBAAgB,WAAY,aAAa,KAAG,MASxD,CAAC;AAEF,oBAAY,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,oBAAY,mBAAmB,GAAG,cAAc,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;AAC5F,aAAK,mBAAmB,GAAG,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAClE,oBAAY,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,oBAAY,mBAAmB,GAAG,cAAc,CAAC,aAAa,EAAE,QAAQ,GAAG,SAAS,CAAC,GACnF,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GACrC,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GACrC,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAElC,eAAO,MAAM,WAAW,eAAgB,YAAY;;;;;+DAIe;YAAE,QAAQ;gBAAE,QAAQ,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE;;CAalG,CAAC;AAEF,eAAO,MAAM,sBAAsB,gBAAiB,UAAU,EAAE,UAAU,aAAa,KAAG,mBAwGzF,CAAC"}
\ No newline at end of file
+{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/config/common.ts"],"names":[],"mappings":";AAEA,OAAgB,EAAE,aAAa,IAAI,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAqD,MAAM,mBAAmB,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAI/C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAOhE;AAED,eAAO,MAAM,iBAAiB,eAAgB,MAAM,KAAG,MAEtD,CAAC;AAEF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,eAAO,MAAM,gBAAgB,kBAAmB,KAAK,WAAW,EAAE,WAAW,CAAC,KAAG,MAShF,CAAC;AAEF,oBAAY,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,oBAAY,mBAAmB,GAAG,cAAc,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;AAC5F,aAAK,mBAAmB,GAAG,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAClE,oBAAY,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,oBAAY,mBAAmB,GAAG,cAAc,CAAC,aAAa,EAAE,QAAQ,GAAG,SAAS,CAAC,GACnF,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GACrC,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GACrC,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAElC,eAAO,MAAM,WAAW,eAAgB,YAAY;;;;;+DAIe;YAAE,QAAQ;gBAAE,QAAQ,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE;;CAalG,CAAC;AAEF,eAAO,MAAM,sBAAsB,SAAU,WAAW,KAAG,mBA8G1D,CAAC"}
\ No newline at end of file

Modified: package/out/index.d.ts.map

Index: package/out/index.d.ts.map
===================================================================
--- package/out/index.d.ts.map
+++ package/out/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,WAAW,EACX,8BAA8B,EAC9B,SAAS,EACV,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
\ No newline at end of file

Modified: package/out/config/nativeui.d.ts.map

Index: package/out/config/nativeui.d.ts.map
===================================================================
--- package/out/config/nativeui.d.ts.map
+++ package/out/config/nativeui.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"nativeui.d.ts","sourceRoot":"","sources":["../../src/config/nativeui.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAe,MAAM,UAAU,CAAC;AAExE,aAAK,cAAc,GAAG,aAAa,GAAG,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AAE5E,eAAO,MAAM,sBAAsB,gBAAiB,UAAU,EAAE,eAAe,YAAY,KAAG,cAyE7F,CAAC"}
\ No newline at end of file
+{"version":3,"file":"nativeui.d.ts","sourceRoot":"","sources":["../../src/config/nativeui.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAe,MAAM,UAAU,CAAC;AAE5D,aAAK,cAAc,GAAG,aAAa,GAAG,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AAE5E,eAAO,MAAM,sBAAsB,gBAAiB,UAAU,EAAE,eAAe,YAAY,KAAG,cAyE7F,CAAC"}
\ No newline at end of file

Modified: package/out/config/sandbox.d.ts.map

Index: package/out/config/sandbox.d.ts.map
===================================================================
--- package/out/config/sandbox.d.ts.map
+++ package/out/config/sandbox.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/config/sandbox.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,UAAU,EAIX,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AA0DjE,eAAO,MAAM,8BAA8B,gBAC5B,UAAU,EAAE,UACjB,aAAa,KACpB,mBAwEF,CAAC"}
\ No newline at end of file
+{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/config/sandbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAA8D,MAAM,UAAU,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AA0DjE,eAAO,MAAM,8BAA8B,SAAU,WAAW,KAAG,mBAwElE,CAAC"}
\ No newline at end of file

Modified: package/out/types.d.ts.map

Index: package/out/types.d.ts.map
===================================================================
--- package/out/types.d.ts.map
+++ package/out/types.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,oBAAY,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,oBAAY,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEzD,oBAAY,OAAO,GAAG,CACpB,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,UAAU,EAAE,EAC1B,UAAU,CAAC,EAAE,YAAY,KACtB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,IAAI,CAAC;CACd"}
\ No newline at end of file
+{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,oBAAY,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,oBAAY,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;AAE7E,oBAAY,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjD,oBAAY,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,oBAAY,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B,CAAC;AAEF,oBAAY,gBAAgB,GAAG,WAAW,GAAG;IAC3C,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,oBAAY,YAAY,GAAG;IACzB,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAC1G,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,IAAI,CAAC;CACd;AAED,oBAAY,kBAAkB,GAAG,cAAc,GAAG;IAChD,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,oBAAY,OAAO,GAAG;IACpB,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjF,CAAC;AAEF,qBAAa,YAAa,SAAQ,SAAS;CAAG"}
\ No newline at end of file

Modified: package/out/webpack.d.ts.map

Index: package/out/webpack.d.ts.map
===================================================================
--- package/out/webpack.d.ts.map
+++ package/out/webpack.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../src/webpack.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAEL,gBAAgB,EAGhB,gBAAgB,EAIjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAA2B,UAAU,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjF,OAAO,EAIL,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEjE,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,EAC7B,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,SAAS,GAC/B,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAkChC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAE3E;AAqBD,wBAAgB,WAAW,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,eAAe,CAY/F;AAED,eAAO,MAAM,SAAS,YAEZ,UAAU,+EAGjB,QAAQ,IAAI,CA+Bd,CAAC;AAEF,wBAAgB,aAAa,CAC3B,cAAc,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,aAAa,EAAE,aAAa,KAAK,mBAAmB,GAC/F,OAAO,CAyBT;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,OAA6D,CAAC;AACpG,eAAO,MAAM,cAAc,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,OACR,CAAC;AAE5D,eAAO,MAAM,cAAc,EAAE,OAqB5B,CAAC"}
\ No newline at end of file
+{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../src/webpack.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAEL,gBAAgB,EAGhB,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA2B,UAAU,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EACL,OAAO,EACP,YAAY,EAEZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,EAC7B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC,GAAG,SAAS,GAC7E,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAkChC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAE3E;AAqBD,eAAO,MAAM,SAAS,YAEZ,UAAU,+EAGjB,QAAQ,IAAI,CA+Bd,CAAC;AAEF,oBAAY,gBAAgB,GAAG,OAAO,CAAC,aAAa,GAAG;IAAE,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAEvF,8BAAsB,cAAe,YAAW,OAAO;IACzC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY;gBAApB,MAAM,EAAE,YAAY;IAEnD,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,aAAa;cAWlE,WAAW,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAsB7E,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB;IAEjD,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAKjD,KAAK,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAsCtF"}
\ No newline at end of file

Modified: package/CHANGELOG.md

Large diffs are not rendered by default.

Modified: package/out/config/common.d.ts

Index: package/out/config/common.d.ts
===================================================================
--- package/out/config/common.d.ts
+++ package/out/config/common.d.ts
@@ -1,22 +1,13 @@
 /// <reference types="node" />
 import { Configuration as WebpackConfig, ModuleOptions } from 'webpack';
 import { Handler } from '@forge/cli-shared';
 import { Translations } from '@forge/manifest';
-export interface ConfigBuilder {
-    isWatchMode: boolean;
-    isDebugMode?: boolean;
-    appDirectory: string;
-    outputDir: string;
-}
-export declare type EntryPoint = {
-    name: string;
-    path: string;
-};
+import { BundlerArgs, EntryPoint } from '../types';
 export declare function getEntryPoints(handlers: Handler[]): EntryPoint[];
 export declare const resolveModulePath: (moduleName: string) => string;
 export declare function resolveStubPath(stubName: string): string;
-export declare const getDevToolConfig: (config: ConfigBuilder) => string;
+export declare const getDevToolConfig: ({ watchMode }: Pick<BundlerArgs, 'watchMode'>) => string;
 export declare type RequiredFields<T, F extends keyof T> = T & Required<Pick<T, F>>;
 export declare type CommonOutputOptions = RequiredFields<Required<WebpackConfig>['output'], 'path'>;
 declare type CommonModuleOptions = RequiredFields<ModuleOptions, 'rules'>;
 export declare type WebpackEntries = Record<string, string>;
@@ -32,7 +23,7 @@
             };
         }) => string;
     };
 };
-export declare const getCommonWebpackConfig: (entrypoints: EntryPoint[], config: ConfigBuilder) => CommonWebpackConfig;
+export declare const getCommonWebpackConfig: (args: BundlerArgs) => CommonWebpackConfig;
 export {};
 //# sourceMappingURL=common.d.ts.map
\ No newline at end of file

Modified: package/out/index.d.ts

Index: package/out/index.d.ts
===================================================================
--- package/out/index.d.ts
+++ package/out/index.d.ts
@@ -1,7 +1,8 @@
-export { Bundler, WatcherMonitor, BundlerOutput } from './types';
-export { getSandboxBundler, getNodeBundler, nativeUiBundle, getCompiler, handleWebpackCompilationResult, runLinter } from './webpack';
-export { EntryPoint, getEntryPoints } from './config/common';
+export { NativeUIBundler, NativeUIBundleResult } from './nativeui';
+export { SandboxBundler, NodeBundler, NODE_RUNTIME_VERSION_FILE } from './runtime';
+export { Bundler, BundlerError, BundlerOutput, BundlerWatch, EntryPoint, WatcherMonitor } from './types';
+export { getCompiler, handleWebpackCompilationResult, runLinter } from './webpack';
+export { getEntryPoints } from './config/common';
 export { getNativeUiBuildConfig } from './config/nativeui';
-export { getNodeRuntimeBuildConfig, getWrapperProvider, LocalWrapperProvider } from './config/node';
-export { getSandboxedRuntimeBuildConfig } from './config/sandbox';
+export { getWrapperProvider, LocalWrapperProvider } from './wrapper-provider';
 //# sourceMappingURL=index.d.ts.map
\ No newline at end of file

Modified: package/out/config/nativeui.d.ts

Index: package/out/config/nativeui.d.ts
===================================================================
--- package/out/config/nativeui.d.ts
+++ package/out/config/nativeui.d.ts
@@ -1,7 +1,8 @@
 import { Configuration as WebpackConfig } from 'webpack';
 import { Translations } from '@forge/manifest';
-import { CommonOutputOptions, EntryPoint } from './common';
+import { EntryPoint } from '../types';
+import { CommonOutputOptions } from './common';
 declare type NativeUIConfig = WebpackConfig & Record<'output', CommonOutputOptions>;
 export declare const getNativeUiBuildConfig: (entrypoints: EntryPoint[], i18nConfig?: Translations) => NativeUIConfig;
 export {};
 //# sourceMappingURL=nativeui.d.ts.map
\ No newline at end of file

Modified: package/out/config/sandbox.d.ts

Index: package/out/config/sandbox.d.ts
===================================================================
--- package/out/config/sandbox.d.ts
+++ package/out/config/sandbox.d.ts
@@ -1,4 +1,5 @@
-import { CommonWebpackConfig, ConfigBuilder, EntryPoint } from './common';
+import { CommonWebpackConfig } from './common';
+import { BundlerArgs } from '../types';
 export declare const SANDBOXED_WEBPACK_CONFIG_NAME = "sandboxed-runtime";
-export declare const getSandboxedRuntimeBuildConfig: (entrypoints: EntryPoint[], config: ConfigBuilder) => CommonWebpackConfig;
+export declare const getSandboxedRuntimeBuildConfig: (args: BundlerArgs) => CommonWebpackConfig;
 //# sourceMappingURL=sandbox.d.ts.map
\ No newline at end of file

Modified: package/out/types.d.ts

Index: package/out/types.d.ts
===================================================================
--- package/out/types.d.ts
+++ package/out/types.d.ts
@@ -1,17 +1,42 @@
-import { Logger } from '@forge/cli-shared';
+import { Logger, UserError } from '@forge/cli-shared';
 import { Translations } from '@forge/manifest';
-import { EntryPoint } from './config/common';
 export declare type BundlerMetadata = {
     modules?: string[];
     nodeRuntimeVersion?: string;
 };
 export interface BundlerOutput {
     outputDir: string;
     metadata?: BundlerMetadata;
 }
-export declare type BundleLogger = Pick<Logger, 'info' | 'warn'>;
-export declare type Bundler = (logger: BundleLogger, appDirectory: string, endpointPath: EntryPoint[], i18nConfig?: Translations) => Promise<BundlerOutput>;
+export declare type BundleLogger = Pick<Logger, 'trace' | 'debug' | 'info' | 'warn'>;
+export declare type BundlerWatchMode = 'watch' | 'debug';
+export declare type EntryPoint = {
+    name: string;
+    path: string;
+};
+export declare type BundlerArgs = {
+    appDirectory: string;
+    entryPoints: EntryPoint[];
+    i18nConfig?: Translations;
+    watchMode?: BundlerWatchMode;
+};
+export declare type BundlerWatchArgs = BundlerArgs & {
+    successMessage: string;
+};
+export declare type BundlerWatch = {
+    onBuildWillStart: () => Promise<void>;
+    onBuildFinished: ((err: null, result: BundlerOutput) => Promise<void>) & ((err: Error) => Promise<void>);
+};
 export interface WatcherMonitor {
     stop(): void;
 }
+export declare type BundlerWatchOutput = WatcherMonitor & {
+    result: BundlerOutput;
+};
+export declare type Bundler = {
+    bundle(args: BundlerArgs): Promise<BundlerOutput>;
+    watch(args: BundlerWatchArgs, watch: BundlerWatch): Promise<BundlerWatchOutput>;
+};
+export declare class BundlerError extends UserError {
+}
 //# sourceMappingURL=types.d.ts.map
\ No newline at end of file

Modified: package/out/webpack.d.ts

Index: package/out/webpack.d.ts
===================================================================
--- package/out/webpack.d.ts
+++ package/out/webpack.d.ts
@@ -1,15 +1,21 @@
 import webpack from 'webpack';
 import { FileSystemReader, FileSystemWriter } from '@forge/cli-shared';
 import { LintLogger } from '@forge/lint';
-import { CommonWebpackConfig, ConfigBuilder, EntryPoint } from './config/common';
-import { WrapperProvider } from './config/node';
-import { Bundler, BundleLogger, BundlerMetadata } from './types';
-export declare function handleWebpackCompilationResult(logger: BundleLogger, err: Error | null | undefined, stats: webpack.Stats | undefined): asserts stats is webpack.Stats;
+import { CommonOutputOptions } from './config/common';
+import { Bundler, BundleLogger, BundlerOutput, BundlerArgs, BundlerWatch, BundlerWatchArgs, BundlerWatchOutput } from './types';
+export declare function handleWebpackCompilationResult(logger: BundleLogger, err: Error | null | undefined, stats: Pick<webpack.Stats, 'hasErrors' | 'hasWarnings' | 'toJson'> | undefined): asserts stats is webpack.Stats;
 export declare function getCompiler(config: webpack.Configuration): webpack.Compiler;
-export declare function getMetadata(config: CommonWebpackConfig, stats?: webpack.Stats): BundlerMetadata;
 export declare const runLinter: (logger?: LintLogger, fileSystemReader?: FileSystemReader, fileSystemWriter?: FileSystemWriter) => Promise<void>;
-export declare function createBundler(getBuildConfig: (entrypoints: EntryPoint[], configBuilder: ConfigBuilder) => CommonWebpackConfig): Bundler;
-export declare const getSandboxBundler: () => Bundler;
-export declare const getNodeBundler: (wrapperProvider: WrapperProvider) => Bundler;
-export declare const nativeUiBundle: Bundler;
+export declare type ConfigWithOutput = webpack.Configuration & {
+    output: CommonOutputOptions;
+};
+export declare abstract class WebpackBundler implements Bundler {
+    protected readonly logger: BundleLogger;
+    constructor(logger: BundleLogger);
+    protected getOutput(config: ConfigWithOutput, stats: webpack.Stats): BundlerOutput;
+    protected runCompiler(config: ConfigWithOutput): Promise<BundlerOutput>;
+    abstract getConfig(args: BundlerArgs): ConfigWithOutput;
+    bundle(args: BundlerArgs): Promise<BundlerOutput>;
+    watch(args: BundlerWatchArgs, watch: BundlerWatch): Promise<BundlerWatchOutput>;
+}
 //# sourceMappingURL=webpack.d.ts.map
\ No newline at end of file