npm package diff

Package: @forge/cli

Versions: 11.3.1 - 11.4.0-next.1-experimental-01f8230

File: package/out/command-line/controller/install-controller.js

Index: package/out/command-line/controller/install-controller.js
===================================================================
--- package/out/command-line/controller/install-controller.js
+++ package/out/command-line/controller/install-controller.js
@@ -16,16 +16,18 @@
     installAppSiteCommand;
     installationService;
     installView;
     supportedProductsService;
-    constructor(appConfigProvider, configFile, ui, installAppSiteCommand, installationService, installView, supportedProductsService) {
+    statsigService;
+    constructor(appConfigProvider, configFile, ui, installAppSiteCommand, installationService, installView, supportedProductsService, statsigService) {
         this.appConfigProvider = appConfigProvider;
         this.configFile = configFile;
         this.ui = ui;
         this.installAppSiteCommand = installAppSiteCommand;
         this.installationService = installationService;
         this.installView = installView;
         this.supportedProductsService = supportedProductsService;
+        this.statsigService = statsigService;
     }
     async securityPrompt(site) {
         this.ui.info(cli_shared_1.Text.install.security.banner(site.host));
         let isTrustedApp = true;
@@ -216,10 +218,17 @@
         if (!scopesConfirmationResult)
             return;
         const successfulProducts = [];
         const failedProducts = [];
+        const isInstallationsWarningsEnabled = await this.statsigService.enableInstallationWarnings();
         for (const product of products) {
             try {
+                if (isInstallationsWarningsEnabled &&
+                    (await this.isNonProductionAppInstallationAttempt(site, product, environmentType))) {
+                    this.ui.warn(cli_shared_1.Text.install.devAppInstallWarning);
+                    if (!nonInteractive && !(await this.ui.confirm(cli_shared_1.Text.install.devAppInstallConfirm)))
+                        return;
+                }
                 const isAlreadyUpdated = await this.installOrUpgrade(upgrade, environment, environmentType, site, product, id, text, validLicense, overrides);
                 if (isAlreadyUpdated) {
                     this.ui.info(cli_shared_1.Text.upgrade.alreadyUpdated.banner(environment, (0, cli_shared_1.productDisplayName)(product), site.host));
                 }
@@ -245,8 +254,33 @@
         if (failedProducts.length) {
             throw new cli_shared_1.PartialInstallationError(cli_shared_1.Text.error.partialInstallation(failedProducts));
         }
     }
+    getEntitlementOfferingName(entitlementOffering) {
+        if (!entitlementOffering)
+            return undefined;
+        if ('currentEdition' in entitlementOffering) {
+            return entitlementOffering.currentEdition?.toLowerCase();
+        }
+        else if ('offering' in entitlementOffering) {
+            return entitlementOffering.offering?.name?.toLowerCase();
+        }
+        return undefined;
+    }
+    async isNonProductionAppInstallationAttempt(site, product, environmentType) {
+        if (environmentType === cli_shared_1.AppEnvironmentType.Production)
+            return false;
+        try {
+            const entitlementOffering = await this.installationService.getEntitlementOfferingProduct(site, product);
+            const entitlementOfferingName = this.getEntitlementOfferingName(entitlementOffering);
+            if (!entitlementOfferingName)
+                return false;
+            return !(entitlementOfferingName?.includes('free') || entitlementOfferingName?.includes('developer'));
+        }
+        catch (error) {
+            return false;
+        }
+    }
     extractManifestData = (manifestEgressEntries, permissions) => {
         const manifestEgressAddresses = (0, cli_shared_1.flatMap)(manifestEgressEntries, ({ domains }) => domains ?? []);
         const manifestScopes = new Set(permissions?.scopes ?? []);
         return { manifestEgressAddresses, manifestScopes };
@@ -361,4 +395,5 @@
         return requiredProducts.every((requiredProduct) => installations.some((installation) => installation.site.includes(site) && installation.product.toLowerCase() === requiredProduct.toLowerCase()));
     };
 }
 exports.InstallController = InstallController;
+//# sourceMappingURL=install-controller.js.map
\ No newline at end of file