npm package diff

Package: @forge/bundler

Versions: 4.19.7-next.14 - 4.20.0-next.15

Modified:package/out/config/node.js

Index: package/out/config/node.js
===================================================================
--- package/out/config/node.js
+++ package/out/config/node.js
@@ -5,8 +5,9 @@
 const cheerio_1 = tslib_1.__importDefault(require("cheerio"));
 const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
 const cli_shared_1 = require("@forge/cli-shared");
 const common_1 = require("./common");
+const path_1 = tslib_1.__importDefault(require("path"));
 exports.NODE_WEBPACK_CONFIG_NAME = 'node-runtime';
 exports.NODE_WEBPACK_USER_CODE_DIR = 'bundled';
 exports.NODE_RUNTIME_VERSION_FILE = 'runtime.json';
 var RuntimeCDN;
@@ -34,76 +35,106 @@
         super(requestId, message);
     }
 }
 exports.ParseWrapperCDNIndexError = ParseWrapperCDNIndexError;
+var ScriptType;
+(function (ScriptType) {
+    ScriptType["WRAPPER"] = "wrapper";
+    ScriptType["LOADER"] = "loader";
+})(ScriptType || (ScriptType = {}));
 class LocalWrapperProvider {
     filesystemReader;
-    path;
-    constructor(filesystemReader, path) {
+    runtimePath;
+    constructor(filesystemReader, runtimePath) {
         this.filesystemReader = filesystemReader;
-        this.path = path;
+        this.runtimePath = runtimePath;
     }
     async getNodeRuntimeWrapper() {
-        const wrapper = await this.filesystemReader.readFileAsync(this.path);
+        const wrapper = await this.filesystemReader.readFileAsync(path_1.default.join(this.runtimePath, 'dist/wrapper.js'));
         if (!wrapper) {
             throw new LocalWrapperNotFoundError();
         }
         return {
             script: wrapper,
-            version: 'local'
+            version: 'local-wrapper'
         };
     }
+    async getNodeRuntimeLoader() {
+        const loader = await this.filesystemReader.readFileAsync(path_1.default.join(this.runtimePath, 'dist/loader.js'));
+        if (!loader) {
+            throw new LocalWrapperNotFoundError();
+        }
+        return {
+            script: loader,
+            version: 'local-loader'
+        };
+    }
 }
 exports.LocalWrapperProvider = LocalWrapperProvider;
 class NetworkWrapperProvider {
+    statsigService;
     wrapper;
+    loader;
     cdnUrl;
-    constructor() {
+    constructor(statsigService) {
+        this.statsigService = statsigService;
         this.cdnUrl = (0, cli_shared_1.getEnvironmentConfig)(RuntimeCDN);
     }
-    async getWrapperPathFromIndex(htmlContent, requestId) {
+    async getScriptPathFromIndex(htmlContent, requestId, scriptType) {
         const html = cheerio_1.default.load(htmlContent);
-        const wrapperPath = html('script')?.get()?.[0]?.attribs['src'];
-        if (typeof wrapperPath !== 'string') {
-            throw new ParseWrapperCDNIndexError('Unable to parse source of runtime component.', requestId);
+        const scriptPath = html('script')
+            ?.get()
+            ?.find((asset) => asset.attribs['src']?.includes(scriptType))?.attribs['src'];
+        if (typeof scriptPath !== 'string') {
+            throw new ParseWrapperCDNIndexError(`Unable to parse source of runtime ${scriptType}.`, requestId);
         }
-        return new URL(wrapperPath, this.cdnUrl).toString();
+        return new URL(scriptPath, this.cdnUrl).toString();
     }
-    async getNodeRuntimeWrapper() {
-        if (this.wrapper) {
-            return this.wrapper;
-        }
+    getFileFromCDN = async (scriptType) => {
         try {
             const indexResponse = await (0, node_fetch_1.default)(this.cdnUrl);
             if (!indexResponse.ok) {
                 throw new WrapperNetworkError(`Failed to fetch runtime component: ${this.cdnUrl} ${indexResponse.status}.`, (0, cli_shared_1.getAtlassianTraceId)(indexResponse.headers));
             }
-            const wrapperUrl = await this.getWrapperPathFromIndex(await indexResponse.text(), (0, cli_shared_1.getAtlassianTraceId)(indexResponse.headers));
-            const response = await (0, node_fetch_1.default)(wrapperUrl);
+            const scriptUrl = await this.getScriptPathFromIndex(await indexResponse.text(), (0, cli_shared_1.getAtlassianTraceId)(indexResponse.headers), scriptType);
+            const response = await (0, node_fetch_1.default)(scriptUrl);
             if (!response.ok) {
-                throw new WrapperNetworkError(`Failed to fetch runtime component: ${wrapperUrl.toString()} ${response.status}.`, (0, cli_shared_1.getAtlassianTraceId)(response.headers));
+                throw new WrapperNetworkError(`Failed to fetch runtime component: ${scriptUrl.toString()} ${response.status}.`, (0, cli_shared_1.getAtlassianTraceId)(response.headers));
             }
             const script = await response.text();
-            this.wrapper = {
+            return {
                 script,
-                version: new URL(wrapperUrl).pathname
+                version: new URL(scriptUrl).pathname
             };
-            return this.wrapper;
         }
         catch (e) {
             if (e instanceof ParseWrapperCDNIndexError) {
                 throw e;
             }
             throw new WrapperNetworkError(e instanceof Error ? e.message : 'Networking error when retrieving runtime component, retry the command.');
         }
+    };
+    async getNodeRuntimeWrapper() {
+        if (!this.wrapper) {
+            this.wrapper = await this.getFileFromCDN(ScriptType.WRAPPER);
+        }
+        return this.wrapper;
     }
+    async getNodeRuntimeLoader() {
+        if (!this.loader) {
+            if (await this.statsigService.testForgeCliBundleRuntimeLoaderGate()) {
+                this.loader = await this.getFileFromCDN(ScriptType.LOADER);
+            }
+        }
+        return this.loader;
+    }
 }
 exports.NetworkWrapperProvider = NetworkWrapperProvider;
-const getWrapperProvider = ({ fileSystemReader }) => {
-    if (process.env.FORGE_WRAPPER_PATH) {
-        return new LocalWrapperProvider(fileSystemReader, process.env.FORGE_WRAPPER_PATH);
+const getWrapperProvider = ({ fileSystemReader, statsigService }) => {
+    if (process.env.FORGE_RUNTIME_PATH) {
+        return new LocalWrapperProvider(fileSystemReader, process.env.FORGE_RUNTIME_PATH);
     }
-    return new NetworkWrapperProvider();
+    return new NetworkWrapperProvider(statsigService);
 };
 exports.getWrapperProvider = getWrapperProvider;
 const getNodeRuntimeBuildConfig = (wrapperProvider) => (entrypoints, config) => {
     const webpackConfig = (0, common_1.getCommonWebpackConfig)(entrypoints, config);
@@ -125,14 +156,25 @@
         apply: (compiler) => {
             compiler.hooks.make.tapPromise('AfterEmitPlugin', async (compilation) => {
                 const { RawSource } = compiler.webpack.sources;
                 const wrapper = await wrapperProvider.getNodeRuntimeWrapper();
-                const source = new RawSource(wrapper.script);
-                for (const entrypoint of entrypoints) {
-                    compilation.emitAsset(`${entrypoint.name}.cjs`, source);
+                const loader = await wrapperProvider.getNodeRuntimeLoader();
+                if (loader) {
+                    const loaderSource = new RawSource(loader.script);
+                    for (const entrypoint of entrypoints) {
+                        compilation.emitAsset(`${entrypoint.name}.cjs`, loaderSource);
+                    }
+                    const wrapperSource = new RawSource(wrapper.script);
+                    compilation.emitAsset('__forge_wrapper__.cjs', wrapperSource);
                 }
+                else {
+                    const source = new RawSource(wrapper.script);
+                    for (const entrypoint of entrypoints) {
+                        compilation.emitAsset(`${entrypoint.name}.cjs`, source);
+                    }
+                }
                 compilation.emitAsset(exports.NODE_RUNTIME_VERSION_FILE, new RawSource(JSON.stringify({
-                    version: wrapper.version
+                    version: loader ? loader.version : wrapper.version
                 }, null, 2)));
             });
         }
     });

Modified:package/package.json

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/bundler",
-  "version": "4.19.7-next.14",
+  "version": "4.20.0-next.15",
   "description": "Default bundler for Forge apps",
   "license": "UNLICENSED",
   "author": "Atlassian",
   "main": "out/index.js",
@@ -20,12 +20,12 @@
     "@babel/plugin-transform-react-jsx": "^7.23.4",
     "@babel/preset-typescript": "^7.23.3",
     "@forge/api": "4.1.1-next.0",
     "@forge/babel-plugin-transform-ui": "1.1.19-next.0",
-    "@forge/cli-shared": "6.3.0-next.13",
+    "@forge/cli-shared": "6.3.0-next.14",
     "@forge/i18n": "0.0.2-next.0",
-    "@forge/lint": "5.6.0-next.14",
-    "@forge/manifest": "8.0.0-next.10",
+    "@forge/lint": "5.6.0-next.15",
+    "@forge/manifest": "8.0.0-next.11",
     "@forge/util": "1.4.5-next.0",
     "assert": "^2.1.0",
     "babel-loader": "^8.3.0",
     "browserify-zlib": "^0.2.0",

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

Index: package/out/config/node.d.ts.map
===================================================================
--- package/out/config/node.d.ts.map
+++ package/out/config/node.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/config/node.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAA6C,MAAM,mBAAmB,CAAC;AAEtH,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAA0C,MAAM,UAAU,CAAC;AAElH,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD,eAAO,MAAM,0BAA0B,YAAY,CAAC;AACpD,eAAO,MAAM,yBAAyB,iBAAiB,CAAC;AAWxD,qBAAa,yBAA0B,SAAQ,SAAS;;CAIvD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAGhD;AAED,qBAAa,yBAA0B,SAAQ,SAAS;gBAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;CAG3D;AAED,oBAAY,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;CACjD;AAED,qBAAa,oBAAqB,YAAW,eAAe;IAExD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,MAAM;IAEzB,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC;CAUtD;AAED,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,OAAO,CAAC,OAAO,CAA4B;IAC3C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;;YAKX,uBAAuB;IAS/B,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC;CAuCtD;AAED,eAAO,MAAM,kBAAkB;sBAA8C,gBAAgB;mDAQ5F,CAAC;AAEF,eAAO,MAAM,yBAAyB,oBAClB,eAAe,mBACnB,UAAU,EAAE,UAAU,aAAa,KAAG,mBA4DnD,CAAC"}
\ No newline at end of file
+{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/config/node.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,SAAS,EAGT,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAA0C,MAAM,UAAU,CAAC;AAIlH,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD,eAAO,MAAM,0BAA0B,YAAY,CAAC;AACpD,eAAO,MAAM,yBAAyB,iBAAiB,CAAC;AAWxD,qBAAa,yBAA0B,SAAQ,SAAS;;CAIvD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAGhD;AAED,qBAAa,yBAA0B,SAAQ,SAAS;gBAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;CAG3D;AAED,oBAAY,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAChD,oBAAoB,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CAC5D;AAOD,qBAAa,oBAAqB,YAAW,eAAe;IAExD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW;gBADX,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,MAAM;IAEhC,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC;IAW/C,oBAAoB,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;CAUjE;AAED,qBAAa,sBAAuB,YAAW,eAAe;IAKhD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc;IAJ7D,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,MAAM,CAA4B;IAC1C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEM,cAAc,EAAE,cAAc;YAI/C,sBAAsB;IAgBpC,OAAO,CAAC,cAAc,CAmCpB;IAEI,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC;IAO/C,oBAAoB,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;CAQjE;AAED,eAAO,MAAM,kBAAkB;sBAIX,gBAAgB;oBAClB,cAAc;mDAS/B,CAAC;AAEF,eAAO,MAAM,yBAAyB,oBAClB,eAAe,mBACnB,UAAU,EAAE,UAAU,aAAa,KAAG,mBAuEnD,CAAC"}
\ No newline at end of file

Modified:package/CHANGELOG.md

too-big

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

Index: package/out/config/node.d.ts
===================================================================
--- package/out/config/node.d.ts
+++ package/out/config/node.d.ts
@@ -1,5 +1,5 @@
-import { BaseError, FileSystemReader, UserError } from '@forge/cli-shared';
+import { BaseError, FileSystemReader, UserError, StatsigService } from '@forge/cli-shared';
 import { CommonWebpackConfig, ConfigBuilder, EntryPoint } from './common';
 export declare const NODE_WEBPACK_CONFIG_NAME = "node-runtime";
 export declare const NODE_WEBPACK_USER_CODE_DIR = "bundled";
 export declare const NODE_RUNTIME_VERSION_FILE = "runtime.json";
@@ -11,29 +11,36 @@
 }
 export declare class ParseWrapperCDNIndexError extends BaseError {
     constructor(message: string, requestId: string | undefined);
 }
-export declare type WrapperScript = {
+export declare type RuntimeScript = {
     script: string;
     version: string;
 };
 export interface WrapperProvider {
-    getNodeRuntimeWrapper(): Promise<WrapperScript>;
+    getNodeRuntimeWrapper(): Promise<RuntimeScript>;
+    getNodeRuntimeLoader(): Promise<RuntimeScript | undefined>;
 }
 export declare class LocalWrapperProvider implements WrapperProvider {
     private readonly filesystemReader;
-    private readonly path;
-    constructor(filesystemReader: FileSystemReader, path: string);
-    getNodeRuntimeWrapper(): Promise<WrapperScript>;
+    private readonly runtimePath;
+    constructor(filesystemReader: FileSystemReader, runtimePath: string);
+    getNodeRuntimeWrapper(): Promise<RuntimeScript>;
+    getNodeRuntimeLoader(): Promise<RuntimeScript | undefined>;
 }
 export declare class NetworkWrapperProvider implements WrapperProvider {
+    protected readonly statsigService: StatsigService;
     private wrapper;
+    private loader;
     protected cdnUrl: string;
-    constructor();
-    private getWrapperPathFromIndex;
-    getNodeRuntimeWrapper(): Promise<WrapperScript>;
+    constructor(statsigService: StatsigService);
+    private getScriptPathFromIndex;
+    private getFileFromCDN;
+    getNodeRuntimeWrapper(): Promise<RuntimeScript>;
+    getNodeRuntimeLoader(): Promise<RuntimeScript | undefined>;
 }
-export declare const getWrapperProvider: ({ fileSystemReader }: {
+export declare const getWrapperProvider: ({ fileSystemReader, statsigService }: {
     fileSystemReader: FileSystemReader;
+    statsigService: StatsigService;
 }) => LocalWrapperProvider | NetworkWrapperProvider;
 export declare const getNodeRuntimeBuildConfig: (wrapperProvider: WrapperProvider) => (entrypoints: EntryPoint[], config: ConfigBuilder) => CommonWebpackConfig;
 //# sourceMappingURL=node.d.ts.map
\ No newline at end of file