diff --git a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts index d211a93b4..f670e0ea0 100644 --- a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts +++ b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts @@ -5,10 +5,10 @@ import { Snippet } from "../../../src/Snippet"; import { utlRemoveSessionStorage } from "@microsoft/applicationinsights-common"; export class AISKUSizeCheck extends AITestClass { - private readonly MAX_RAW_SIZE = 135; - private readonly MAX_BUNDLE_SIZE = 135; - private readonly MAX_RAW_DEFLATE_SIZE = 54; - private readonly MAX_BUNDLE_DEFLATE_SIZE = 54; + private readonly MAX_RAW_SIZE = 140; + private readonly MAX_BUNDLE_SIZE = 140; + private readonly MAX_RAW_DEFLATE_SIZE = 56; + private readonly MAX_BUNDLE_DEFLATE_SIZE = 56; private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js"; // Automatically updated by version scripts private readonly currentVer = "3.0.9"; diff --git a/AISKU/Tests/Unit/src/GlobalTestHooks.Test.ts b/AISKU/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/AISKU/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/AISKU/Tests/Unit/src/aiskuunittests.ts b/AISKU/Tests/Unit/src/aiskuunittests.ts index d2056151e..39a168f4e 100644 --- a/AISKU/Tests/Unit/src/aiskuunittests.ts +++ b/AISKU/Tests/Unit/src/aiskuunittests.ts @@ -2,6 +2,7 @@ import { AISKUSizeCheck } from "./AISKUSize.Tests"; import { ApplicationInsightsTests } from './applicationinsights.e2e.tests'; import { ApplicationInsightsFetchTests } from './applicationinsights.e2e.fetch.tests'; import { CdnPackagingChecks } from './CdnPackaging.tests'; +import { GlobalTestHooks } from './GlobalTestHooks.Test'; import { SanitizerE2ETests } from './sanitizer.e2e.tests'; import { ValidateE2ETests } from './validate.e2e.tests'; import { SenderE2ETests } from './sender.e2e.tests'; @@ -10,6 +11,7 @@ import { CdnThrottle} from "./CdnThrottle.tests"; import { ThrottleSentMessage } from "./ThrottleSentMessage.tests"; export function runTests() { + new GlobalTestHooks().registerTests(); new AISKUSizeCheck().registerTests(); new ApplicationInsightsTests().registerTests(); new ApplicationInsightsFetchTests().registerTests(); diff --git a/AISKULight/Tests/Unit/src/GlobalTestHooks.Test.ts b/AISKULight/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/AISKULight/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/AISKULight/Tests/Unit/src/aiskuliteunittests.ts b/AISKULight/Tests/Unit/src/aiskuliteunittests.ts index 8b8a878cc..f1a132879 100644 --- a/AISKULight/Tests/Unit/src/aiskuliteunittests.ts +++ b/AISKULight/Tests/Unit/src/aiskuliteunittests.ts @@ -1,8 +1,10 @@ import { AISKULightSizeCheck } from "./AISKULightSize.Tests"; import { ApplicationInsightsDynamicConfigTests } from "./dynamicconfig.tests"; import { ApplicationInsightsConfigTests } from "./config.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new AISKULightSizeCheck().registerTests(); new ApplicationInsightsDynamicConfigTests().registerTests(); new ApplicationInsightsConfigTests().registerTests(); diff --git a/channels/1ds-post-js/test/Unit/src/GlobalTestHooks.Test.ts b/channels/1ds-post-js/test/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..730f8f2cd --- /dev/null +++ b/channels/1ds-post-js/test/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { _testHookMaxUnloadHooksCb } from "@microsoft/1ds-core-js"; +import { Assert } from "@microsoft/ai-test-framework"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/channels/1ds-post-js/test/Unit/src/post.unittests.ts b/channels/1ds-post-js/test/Unit/src/post.unittests.ts index d4b1b2f91..7ca5a404c 100644 --- a/channels/1ds-post-js/test/Unit/src/post.unittests.ts +++ b/channels/1ds-post-js/test/Unit/src/post.unittests.ts @@ -3,8 +3,10 @@ import { HttpManagerTest } from './HttpManagerTest'; import { KillSwitchTest } from './KillSwitchTest'; import { SerializerTest } from './SerializerTest'; import { FileSizeCheckTest } from "./FileSizeCheckTest" +import { GlobalTestHooks } from './GlobalTestHooks.Test'; export function registerTests() { + new GlobalTestHooks().registerTests(); new PostChannelTest("PostChannelTest").registerTests(); new HttpManagerTest("HttpManagerTest").registerTests(); new HttpManagerTest("HttpManagerTest", true).registerTests(); diff --git a/channels/applicationinsights-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/channels/applicationinsights-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/channels/applicationinsights-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/channels/applicationinsights-channel-js/Tests/Unit/src/aichannel.tests.ts b/channels/applicationinsights-channel-js/Tests/Unit/src/aichannel.tests.ts index 807b0d875..b4dd43ee5 100644 --- a/channels/applicationinsights-channel-js/Tests/Unit/src/aichannel.tests.ts +++ b/channels/applicationinsights-channel-js/Tests/Unit/src/aichannel.tests.ts @@ -1,7 +1,9 @@ import { SenderTests } from "./Sender.tests"; import { SampleTests } from "./Sample.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new SenderTests().registerTests(); new SampleTests().registerTests(); } \ No newline at end of file diff --git a/channels/offline-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/channels/offline-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/channels/offline-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/channels/tee-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/channels/tee-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/channels/tee-channel-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/channels/tee-channel-js/Tests/Unit/src/teechannel.tests.ts b/channels/tee-channel-js/Tests/Unit/src/teechannel.tests.ts index 5ccef728d..0b215eedc 100644 --- a/channels/tee-channel-js/Tests/Unit/src/teechannel.tests.ts +++ b/channels/tee-channel-js/Tests/Unit/src/teechannel.tests.ts @@ -1,5 +1,7 @@ import { TeeChannelCoreTests } from "./TeeChannelCore.Tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new TeeChannelCoreTests().registerTests(); } \ No newline at end of file diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/appinsights-analytics.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/appinsights-analytics.tests.ts index ae3bb504c..3e4b83ca7 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/appinsights-analytics.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/appinsights-analytics.tests.ts @@ -1,8 +1,10 @@ import { AnalyticsPluginTests } from './AnalyticsPlugin.tests'; import { TelemetryItemCreatorTests } from './TelemetryItemCreator.tests'; import { AnalyticsExtensionSizeCheck } from "./AnalyticsExtensionSize.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new AnalyticsPluginTests().registerTests(); new TelemetryItemCreatorTests().registerTests(); new AnalyticsExtensionSizeCheck().registerTests(); diff --git a/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/cfgsync.tests.ts b/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/cfgsync.tests.ts index 92792bdcf..4afb1b311 100644 --- a/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/cfgsync.tests.ts +++ b/extensions/applicationinsights-cfgsync-js/Tests/Unit/src/cfgsync.tests.ts @@ -1,7 +1,9 @@ import { CfgSyncHelperTests } from "./cfgsynchelper.tests"; import {CfgSyncPluginTests} from "./cfgsyncplugin.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new CfgSyncPluginTests().registerTests(); new CfgSyncHelperTests().registerTests(); } diff --git a/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/appinsights-clickanalytics.tests.ts b/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/appinsights-clickanalytics.tests.ts index 04374873b..ce06a18ae 100644 --- a/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/appinsights-clickanalytics.tests.ts +++ b/extensions/applicationinsights-clickanalytics-js/Tests/Unit/src/appinsights-clickanalytics.tests.ts @@ -1,5 +1,7 @@ import { ClickEventTest } from './ClickEventTest'; +import { GlobalTestHooks } from './GlobalTestHooks.Test'; export function runTests() { + new GlobalTestHooks().registerTests(); new ClickEventTest().registerTests(); } diff --git a/extensions/applicationinsights-dependencies-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-dependencies-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-dependencies-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-dependencies-js/Tests/Unit/src/dependencies.tests.ts b/extensions/applicationinsights-dependencies-js/Tests/Unit/src/dependencies.tests.ts index 3938bebb8..386bbfb16 100644 --- a/extensions/applicationinsights-dependencies-js/Tests/Unit/src/dependencies.tests.ts +++ b/extensions/applicationinsights-dependencies-js/Tests/Unit/src/dependencies.tests.ts @@ -1,6 +1,8 @@ import { AjaxTests, AjaxPerfTrackTests, AjaxFrozenTests } from "./ajax.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new AjaxTests().registerTests(); new AjaxPerfTrackTests().registerTests(); new AjaxFrozenTests().registerTests(); diff --git a/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/appinsights-perfmarkmeasure.tests.ts b/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/appinsights-perfmarkmeasure.tests.ts index 5a2d0c191..a5d266f63 100644 --- a/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/appinsights-perfmarkmeasure.tests.ts +++ b/extensions/applicationinsights-perfmarkmeasure-js/Tests/Unit/src/appinsights-perfmarkmeasure.tests.ts @@ -1,5 +1,7 @@ import { MarkMeasureTests } from './MarkMeasureTests'; +import { GlobalTestHooks } from './GlobalTestHooks.Test'; export function runTests() { + new GlobalTestHooks().registerTests(); new MarkMeasureTests().registerTests(); } diff --git a/extensions/applicationinsights-properties-js/Tests/Unit/src/GlobalTestHooks.Test.ts b/extensions/applicationinsights-properties-js/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/extensions/applicationinsights-properties-js/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/extensions/applicationinsights-properties-js/Tests/Unit/src/prop.tests.ts b/extensions/applicationinsights-properties-js/Tests/Unit/src/prop.tests.ts index b81d1977e..be2a55a3f 100644 --- a/extensions/applicationinsights-properties-js/Tests/Unit/src/prop.tests.ts +++ b/extensions/applicationinsights-properties-js/Tests/Unit/src/prop.tests.ts @@ -3,8 +3,10 @@ import { PropertiesTests } from "./properties.tests"; import { SessionManagerTests } from "./SessionManager.Tests"; import { PropertiesExtensionSizeCheck } from "./propertiesSize.tests"; import { TelemetryContextTests } from "./TelemetryContext.Tests"; +import { GlobalTestHooks } from './GlobalTestHooks.Test'; export function runTests() { + new GlobalTestHooks().registerTests(); new PropertiesTests().registerTests(); new SessionManagerTests(false).registerTests(); new SessionManagerTests(true).registerTests(); diff --git a/shared/1ds-core-js/src/Index.ts b/shared/1ds-core-js/src/Index.ts index be973c9b9..ace9ce569 100644 --- a/shared/1ds-core-js/src/Index.ts +++ b/shared/1ds-core-js/src/Index.ts @@ -67,7 +67,10 @@ export { IConfigCheckFn, IConfigDefaultCheck, IConfigDefaults, IConfigSetFn, IDynamicConfigHandler, IDynamicPropertyHandler, IWatchDetails, IWatcherHandler, WatcherFunction, createDynamicConfig, onConfigChange, getDynamicConfigHandler, blockDynamicConversion, forceDynamicConversion, - IPayloadData, IXHROverride, OnCompleteCallback, SendPOSTFunction + IPayloadData, IXHROverride, OnCompleteCallback, SendPOSTFunction, + + // Test Hooks + _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; export { diff --git a/shared/1ds-core-js/test/Unit/src/FileSizeCheckTest.ts b/shared/1ds-core-js/test/Unit/src/FileSizeCheckTest.ts index 5f7c0839d..2e1f35752 100644 --- a/shared/1ds-core-js/test/Unit/src/FileSizeCheckTest.ts +++ b/shared/1ds-core-js/test/Unit/src/FileSizeCheckTest.ts @@ -2,8 +2,8 @@ import { AITestClass } from "@microsoft/ai-test-framework"; import * as pako from 'pako'; export class FileSizeCheckTest extends AITestClass { - private readonly MAX_BUNDLE_SIZE = 60; - private readonly MAX_DEFLATE_SIZE = 26; + private readonly MAX_BUNDLE_SIZE = 66; + private readonly MAX_DEFLATE_SIZE = 28; private readonly bundleFilePath = "../bundle/es5/ms.core.min.js"; public testInitialize() { diff --git a/shared/1ds-core-js/test/Unit/src/GlobalTestHooks.Test.ts b/shared/1ds-core-js/test/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/shared/1ds-core-js/test/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/shared/1ds-core-js/test/Unit/src/core.unittests.ts b/shared/1ds-core-js/test/Unit/src/core.unittests.ts index 727a0db05..faa21219d 100644 --- a/shared/1ds-core-js/test/Unit/src/core.unittests.ts +++ b/shared/1ds-core-js/test/Unit/src/core.unittests.ts @@ -5,10 +5,12 @@ import { DynamicProtoTests } from './DynamicProtoTests'; import { UtilsTest } from './UtilsTest'; import { ValueSanitizerTests } from './ValueSanitizerTests'; import {FileSizeCheckTest} from './FileSizeCheckTest' +import { GlobalTestHooks } from './GlobalTestHooks.Test'; export function registerTests() { + new GlobalTestHooks().registerTests(); new CoreTest('CoreTest').registerTests(); new ESPromiseTests('ESPromiseTests').registerTests(); new ESPromiseSchedulerTests('ESPromiseSchedulerTests').registerTests(); diff --git a/shared/AppInsightsCommon/Tests/Unit/src/GlobalTestHooks.Test.ts b/shared/AppInsightsCommon/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..b67bf2fe7 --- /dev/null +++ b/shared/AppInsightsCommon/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "@microsoft/applicationinsights-core-js"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/shared/AppInsightsCommon/Tests/Unit/src/appinsights-common.tests.ts b/shared/AppInsightsCommon/Tests/Unit/src/appinsights-common.tests.ts index a05ddf193..f9ef32c0d 100644 --- a/shared/AppInsightsCommon/Tests/Unit/src/appinsights-common.tests.ts +++ b/shared/AppInsightsCommon/Tests/Unit/src/appinsights-common.tests.ts @@ -5,8 +5,10 @@ import { ConnectionStringParserTests } from "./ConnectionStringParser.tests"; import { SeverityLevelTests } from "./SeverityLevel.tests"; import { RequestHeadersTests } from "./RequestHeaders.tests"; import { ThrottleMgrTest } from "./ThrottleMgr.tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; export function runTests() { + new GlobalTestHooks().registerTests(); new ThrottleMgrTest().registerTests(); new ApplicationInsightsTests().registerTests(); new ExceptionTests().registerTests(); diff --git a/shared/AppInsightsCore/Tests/Unit/src/ApplicationInsightsCore.Tests.ts b/shared/AppInsightsCore/Tests/Unit/src/ApplicationInsightsCore.Tests.ts index 16a1c62f7..9865cf02e 100644 --- a/shared/AppInsightsCore/Tests/Unit/src/ApplicationInsightsCore.Tests.ts +++ b/shared/AppInsightsCore/Tests/Unit/src/ApplicationInsightsCore.Tests.ts @@ -19,7 +19,6 @@ export class ApplicationInsightsCoreTests extends AITestClass { } public registerTests() { - this.testCase({ name: "ApplicationInsightsCore: Initialization validates input", test: () => { @@ -849,6 +848,30 @@ export class ApplicationInsightsCoreTests extends AITestClass { } }); + this.testCase({ + name: 'Test Excessive unload hook detection - make sure calling getPerfMgr() does not cause excessive unload hook detection', + test: () => { + const appInsightsCore = new AppInsightsCore(); + const channelPlugin1 = new ChannelPlugin(); + channelPlugin1.priority = 1001; + + const theConfig = { + channels: [[channelPlugin1]], + endpointUrl: "https://dc.services.visualstudio.com/v2/track", + instrumentationKey: "", + extensionConfig: {} + }; + + appInsightsCore.initialize(theConfig, []); + Assert.equal(true, appInsightsCore.isInitialized(), "Core is initialized"); + + // Send lots of notifications + for (let lp = 0; lp < 100; lp++) { + Assert.equal(null, appInsightsCore.getPerfMgr()); + } + } + }); + function _createBuckets(num: number) { // Using helper function as TypeScript 2.5.3 is complaining about new Array(100).fill(0); let buckets: number[] = []; diff --git a/shared/AppInsightsCore/Tests/Unit/src/GlobalTestHooks.Test.ts b/shared/AppInsightsCore/Tests/Unit/src/GlobalTestHooks.Test.ts new file mode 100644 index 000000000..99e370c4a --- /dev/null +++ b/shared/AppInsightsCore/Tests/Unit/src/GlobalTestHooks.Test.ts @@ -0,0 +1,13 @@ +import { Assert } from "@microsoft/ai-test-framework"; +import { _testHookMaxUnloadHooksCb } from "../../../src/JavaScriptSDK/UnloadHookContainer"; +import { dumpObj } from "@nevware21/ts-utils"; + +export class GlobalTestHooks { + + public registerTests() { + // Set a global maximum + _testHookMaxUnloadHooksCb(20, (state: string, hooks: Array) => { + Assert.ok(false, "Max unload hooks exceeded [" + hooks.length + "] - " + state + " - " + dumpObj(hooks)); + }); + } +} diff --git a/shared/AppInsightsCore/Tests/Unit/src/aiunittests.ts b/shared/AppInsightsCore/Tests/Unit/src/aiunittests.ts index bf7b3a679..6fc31aebc 100644 --- a/shared/AppInsightsCore/Tests/Unit/src/aiunittests.ts +++ b/shared/AppInsightsCore/Tests/Unit/src/aiunittests.ts @@ -1,6 +1,7 @@ import '@microsoft/applicationinsights-shims'; import { ApplicationInsightsCoreTests } from "./ApplicationInsightsCore.Tests"; import { CookieManagerTests } from "./CookieManager.Tests"; +import { GlobalTestHooks } from "./GlobalTestHooks.Test"; import { HelperFuncTests } from './HelperFunc.Tests'; import { AppInsightsCoreSizeCheck } from "./AppInsightsCoreSize.Tests"; import { EventHelperTests } from "./EventHelper.Tests"; @@ -12,6 +13,7 @@ import { W3cTraceParentTests } from "./W3cTraceParentTests"; import { DynamicConfigTests } from "./DynamicConfig.Tests"; export function runTests() { + new GlobalTestHooks().registerTests(); new DynamicTests().registerTests(); new DynamicConfigTests().registerTests(); new ApplicationInsightsCoreTests().registerTests(); diff --git a/shared/AppInsightsCore/src/Config/DynamicConfig.ts b/shared/AppInsightsCore/src/Config/DynamicConfig.ts index ba5b4c8af..c10a85350 100644 --- a/shared/AppInsightsCore/src/Config/DynamicConfig.ts +++ b/shared/AppInsightsCore/src/Config/DynamicConfig.ts @@ -36,6 +36,8 @@ function _createAndUseHandler(state: _IDynamicConfigHandlerState, configHa } }; + objDefine(handler, "toJSON", { v: () => "WatcherHandler" + (handler.fn ? "" : "[X]") }); + state.use(handler, configHandler); return handler; diff --git a/shared/AppInsightsCore/src/JavaScriptSDK.Enums/LoggingEnums.ts b/shared/AppInsightsCore/src/JavaScriptSDK.Enums/LoggingEnums.ts index 5906bcd04..abe98b4c0 100644 --- a/shared/AppInsightsCore/src/JavaScriptSDK.Enums/LoggingEnums.ts +++ b/shared/AppInsightsCore/src/JavaScriptSDK.Enums/LoggingEnums.ts @@ -84,6 +84,7 @@ export const enum _eInternalMessageId { InvalidDurationValue = 45, TelemetryEnvelopeInvalid = 46, CreateEnvelopeError = 47, + MaxUnloadHookExceeded = 48, // User actionable CannotSerializeObject = 48, diff --git a/shared/AppInsightsCore/src/JavaScriptSDK/AppInsightsCore.ts b/shared/AppInsightsCore/src/JavaScriptSDK/AppInsightsCore.ts index aa7dbb85d..c0ef2bc4d 100644 --- a/shared/AppInsightsCore/src/JavaScriptSDK/AppInsightsCore.ts +++ b/shared/AppInsightsCore/src/JavaScriptSDK/AppInsightsCore.ts @@ -181,7 +181,7 @@ function _addDelayedCfgListener(listeners: { rm: () => void, w: WatcherFunction< let theListener = _findWatcher(listeners, newWatcher).l; if (!theListener) { - theListener ={ + theListener = { w: newWatcher, rm: () => { let fnd = _findWatcher(listeners, newWatcher); @@ -207,6 +207,36 @@ function _registerDelayedCfgListener(config: IConfiguration, listeners: { rm: () }); } +// Moved this outside of the closure to reduce the retained memory footprint +function _initDebugListener(configHandler: IDynamicConfigHandler, unloadContainer: IUnloadHookContainer, notificationManager: INotificationManager, debugListener: INotificationListener) { + // Will get recalled if any referenced config values are changed + unloadContainer.add(configHandler.watch((details) => { + let disableDbgExt = details.cfg.disableDbgExt; + + if (disableDbgExt === true && debugListener) { + // Remove any previously loaded debug listener + notificationManager.removeNotificationListener(debugListener); + debugListener = null; + } + + if (notificationManager && !debugListener && disableDbgExt !== true) { + debugListener = getDebugListener(details.cfg); + notificationManager.addNotificationListener(debugListener); + } + })); + + return debugListener +} + +// Moved this outside of the closure to reduce the retained memory footprint +function _createUnloadHook(unloadHook: IUnloadHook): IUnloadHook { + return objDefine({ + rm: () => { + unloadHook.rm(); + } + }, "toJSON", { v: () => "aicore::onCfgChange<" + JSON.stringify(unloadHook) + ">" }); +} + /** * @group Classes * @group Entrypoint @@ -317,7 +347,8 @@ export class AppInsightsCore im _notificationManager = notificationManager; - _initDebugListener(); + // Initialize the debug listener outside of the closure to reduce the retained memory footprint + _debugListener = _initDebugListener(_configHandler, _hookContainer, _notificationManager && _self.getNotifyMgr(), _debugListener); _initPerfManager(); _self.logger = logger; @@ -444,17 +475,6 @@ export class AppInsightsCore im }; _self.getPerfMgr = (): IPerfManager => { - if (!_perfManager && !_cfgPerfManager) { - _addUnloadHook(_configHandler.watch((details) => { - if (details.cfg.enablePerfMgr) { - let createPerfMgr = details.cfg.createPerfMgr; - if (isFunction(createPerfMgr)) { - _cfgPerfManager = createPerfMgr(_self, _self.getNotifyMgr()); - } - } - })); - } - return _perfManager || _cfgPerfManager || getGblPerfMgr(); }; @@ -726,11 +746,7 @@ export class AppInsightsCore im unloadHook = onConfigChange(_configHandler.cfg, handler, _self.logger); } - return { - rm: () => { - unloadHook.rm(); - } - } + return _createUnloadHook(unloadHook); }; _self.getWParam = () => { @@ -854,6 +870,8 @@ export class AppInsightsCore im _pluginVersionString = null; _pluginVersionStringArr = null; _forceStopInternalLogPoller = false; + _internalLogPoller = null; + _internalLogPollerListening = false; } function _createTelCtx(): IProcessTelemetryContext { @@ -1106,40 +1124,39 @@ export class AppInsightsCore im return true; } - function _initDebugListener() { - // Lazily ensure that the notification manager is created - !_notificationManager && _self.getNotifyMgr(); + function _initPerfManager() { + // Save the previous config based performance manager creator to avoid creating new perf manager instances if unchanged + let prevCfgPerfMgr: (core: IAppInsightsCore, notificationManager: INotificationManager) => IPerfManager; // Will get recalled if any referenced config values are changed _addUnloadHook(_configHandler.watch((details) => { - let disableDbgExt = details.cfg.disableDbgExt; + let enablePerfMgr = details.cfg.enablePerfMgr; + if (enablePerfMgr) { + let createPerfMgr = details.cfg.createPerfMgr; + if (prevCfgPerfMgr !== createPerfMgr) { + if (!createPerfMgr) { + createPerfMgr = _createPerfManager; + } - if (disableDbgExt === true && _debugListener) { - // Remove any previously loaded debug listener - _notificationManager.removeNotificationListener(_debugListener); - _debugListener = null; - } - - if (_notificationManager && !_debugListener && disableDbgExt !== true) { - _debugListener = getDebugListener(details.cfg); - _notificationManager.addNotificationListener(_debugListener); - } - })); - } + // Set the performance manager creation function if not defined + getSetValue(details.cfg, STR_CREATE_PERF_MGR, createPerfMgr); + prevCfgPerfMgr = createPerfMgr; - function _initPerfManager() { - // Will get recalled if any referenced config values are changed - _addUnloadHook(_configHandler.watch((details) => { - let enablePerfMgr = details.cfg.enablePerfMgr; + // Remove any existing config based performance manager + _cfgPerfManager = null; + } - if (!enablePerfMgr && _cfgPerfManager) { + // Only create the performance manager if it's not already created or manually set + if (!_perfManager && !_cfgPerfManager && isFunction(createPerfMgr)) { + // Create a new config based performance manager + _cfgPerfManager = createPerfMgr(_self, _self.getNotifyMgr()); + } + } else { // Remove any existing config based performance manager _cfgPerfManager = null; - } - - if (enablePerfMgr) { - // Set the performance manager creation function if not defined - getSetValue(details.cfg, STR_CREATE_PERF_MGR, _createPerfManager); + + // Clear the previous cached value so it can be GC'd + prevCfgPerfMgr = null; } })); } diff --git a/shared/AppInsightsCore/src/JavaScriptSDK/NotificationManager.ts b/shared/AppInsightsCore/src/JavaScriptSDK/NotificationManager.ts index 2e4377d7b..ef10fe78f 100644 --- a/shared/AppInsightsCore/src/JavaScriptSDK/NotificationManager.ts +++ b/shared/AppInsightsCore/src/JavaScriptSDK/NotificationManager.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import dynamicProto from "@microsoft/dynamicproto-js"; import { IPromise, createAllPromise, createPromise, doAwaitResponse } from "@nevware21/ts-async"; -import { arrForEach, arrIndexOf, objDefine, scheduleTimeout } from "@nevware21/ts-utils"; +import { ITimerHandler, arrForEach, arrIndexOf, objDefine, safe, scheduleTimeout } from "@nevware21/ts-utils"; import { createDynamicConfig } from "../Config/DynamicConfig"; import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration"; import { INotificationListener } from "../JavaScriptSDK.Interfaces/INotificationListener"; @@ -16,17 +16,37 @@ const defaultValues = { perfEvtsSendAll: false }; -function _runListeners(listeners: INotificationListener[], name: string, isAsync: boolean, callback: (listener: INotificationListener) => void) { +interface IAsyncNotifications { + h: ITimerHandler; + cb: Array<{ fn: (listener: INotificationListener) => void, arg: INotificationListener }> +} + +function _runScheduledListeners(asyncNotifications: IAsyncNotifications) { + asyncNotifications.h = null; + let callbacks = asyncNotifications.cb; + asyncNotifications.cb = []; + arrForEach(callbacks, (cb) => { + // Run the listener in a try-catch to ensure that a single listener failing doesn't prevent the others from running + safe(cb.fn, [cb.arg]); + }); +} + +// This function is used to combine the logic of running the listeners and handling the async notifications so that they don't +// create multiple timers if there are multiple async listeners. +function _runListeners(listeners: INotificationListener[], name: string, asyncNotifications: IAsyncNotifications | null, callback: (listener: INotificationListener) => void) { arrForEach(listeners, (listener) => { if (listener && listener[name]) { - if (isAsync) { - scheduleTimeout(() => callback(listener), 0); + if (asyncNotifications) { + // Schedule the callback to be called after the current call stack has cleared. + asyncNotifications.cb.push({ + fn: callback, + arg: listener + }); + + asyncNotifications.h = asyncNotifications.h || scheduleTimeout(_runScheduledListeners, 0, asyncNotifications); } else { - try { - callback(listener); - } catch (e) { - // Catch errors to ensure we don't block sending the requests - } + // Run the listener in a try-catch to ensure that a single listener failing doesn't prevent the others from running + safe(callback, [listener]); } } }); @@ -42,7 +62,11 @@ export class NotificationManager implements INotificationManager { let perfEvtsSendAll: boolean; let unloadHandler: IUnloadHook; let _listeners: INotificationListener[] = []; - + let _asyncNotifications: IAsyncNotifications = { + h: null, + cb: [] + }; + let cfgHandler = createDynamicConfig(config, defaultValues); unloadHandler = cfgHandler.watch((details) => { @@ -75,7 +99,7 @@ export class NotificationManager implements INotificationManager { * @param events - The array of events that have been sent. */ _self.eventsSent = (events: ITelemetryItem[]): void => { - _runListeners(_listeners, STR_EVENTS_SENT, true, (listener) => { + _runListeners(_listeners, STR_EVENTS_SENT, _asyncNotifications, (listener) => { listener.eventsSent(events); }); }; @@ -87,7 +111,7 @@ export class NotificationManager implements INotificationManager { * constant should be used to check the different values. */ _self.eventsDiscarded = (events: ITelemetryItem[], reason: number): void => { - _runListeners(_listeners, STR_EVENTS_DISCARDED, true, (listener) => { + _runListeners(_listeners, STR_EVENTS_DISCARDED, _asyncNotifications, (listener) => { listener.eventsDiscarded(events, reason); }); }; @@ -98,7 +122,7 @@ export class NotificationManager implements INotificationManager { * @param isAsync - A flag which identifies whether the requests are being sent in an async or sync manner. */ _self.eventsSendRequest = (sendReason: number, isAsync: boolean): void => { - _runListeners(_listeners, STR_EVENTS_SEND_REQUEST, isAsync, (listener) => { + _runListeners(_listeners, STR_EVENTS_SEND_REQUEST, isAsync ? _asyncNotifications : null, (listener) => { listener.eventsSendRequest(sendReason, isAsync); }); }; @@ -108,7 +132,7 @@ export class NotificationManager implements INotificationManager { // Send all events or only parent events if (perfEvtsSendAll || !perfEvent.isChildEvt()) { - _runListeners(_listeners, STR_PERF_EVENT, false, (listener) => { + _runListeners(_listeners, STR_PERF_EVENT, null, (listener) => { if (perfEvent.isAsync) { scheduleTimeout(() => listener.perfEvent(perfEvent), 0); } else { @@ -125,10 +149,15 @@ export class NotificationManager implements INotificationManager { unloadHandler && unloadHandler.rm(); unloadHandler = null; _listeners = []; + + // Clear any async listener + _asyncNotifications.h && _asyncNotifications.h.cancel(); + _asyncNotifications.h = null; + _asyncNotifications.cb = []; }; let waiting: IPromise[]; - _runListeners(_listeners, "unload", false, (listener) => { + _runListeners(_listeners, "unload", null, (listener) => { let asyncUnload = listener.unload(isAsync); if (asyncUnload) { if (!waiting) { diff --git a/shared/AppInsightsCore/src/JavaScriptSDK/UnloadHookContainer.ts b/shared/AppInsightsCore/src/JavaScriptSDK/UnloadHookContainer.ts index 6afbd7b6b..32895ed0f 100644 --- a/shared/AppInsightsCore/src/JavaScriptSDK/UnloadHookContainer.ts +++ b/shared/AppInsightsCore/src/JavaScriptSDK/UnloadHookContainer.ts @@ -7,6 +7,9 @@ import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger import { ILegacyUnloadHook, IUnloadHook } from "../JavaScriptSDK.Interfaces/IUnloadHook"; import { _throwInternal } from "./DiagnosticLogger"; +let _maxHooks: number | undefined; +let _hookAddMonitor: (state: string, hooks: Array) => void | undefined; + /** * Interface which identifiesAdd this hook so that it is automatically removed during unloading * @param hooks - The single hook or an array of IInstrumentHook objects @@ -16,6 +19,17 @@ export interface IUnloadHookContainer { run: (logger?: IDiagnosticLogger) => void; } +/** + * Test hook for setting the maximum number of unload hooks and calling a monitor function when the hooks are added or removed + * This allows for automatic test failure when the maximum number of unload hooks is exceeded + * @param maxHooks - The maximum number of unload hooks + * @param addMonitor - The monitor function to call when hooks are added or removed + */ +export function _testHookMaxUnloadHooksCb(maxHooks?: number, addMonitor?: (state: string, hooks: Array) => void) { + _maxHooks = maxHooks; + _hookAddMonitor = addMonitor; +} + /** * Create a IUnloadHookContainer which can be used to remember unload hook functions to be executed during the component unloading * process. @@ -37,11 +51,18 @@ export function createUnloadHookContainer(): IUnloadHookContainer { _throwInternal(logger, eLoggingSeverity.WARNING, _eInternalMessageId.PluginException, "Unloading:" + dumpObj(e)); } }); + + if (_maxHooks && oldHooks.length > _maxHooks) { + _hookAddMonitor ? _hookAddMonitor("doUnload", oldHooks) : _throwInternal(null, eLoggingSeverity.CRITICAL, _eInternalMessageId.MaxUnloadHookExceeded, "Max unload hooks exceeded. An excessive number of unload hooks has been detected."); + } } function _addHook(hooks: IUnloadHook | IUnloadHook[] | Iterator | ILegacyUnloadHook | ILegacyUnloadHook[] | Iterator) { if (hooks) { arrAppend(_hooks, hooks); + if (_maxHooks && _hooks.length > _maxHooks) { + _hookAddMonitor ? _hookAddMonitor("Add", _hooks) : _throwInternal(null, eLoggingSeverity.CRITICAL, _eInternalMessageId.MaxUnloadHookExceeded, "Max unload hooks exceeded. An excessive number of unload hooks has been detected."); + } } } diff --git a/shared/AppInsightsCore/src/applicationinsights-core-js.ts b/shared/AppInsightsCore/src/applicationinsights-core-js.ts index 781ebac73..926a06b5e 100644 --- a/shared/AppInsightsCore/src/applicationinsights-core-js.ts +++ b/shared/AppInsightsCore/src/applicationinsights-core-js.ts @@ -81,7 +81,7 @@ export { getDebugListener, getDebugExt } from "./JavaScriptSDK/DbgExtensionUtils export { TelemetryInitializerFunction, ITelemetryInitializerHandler, ITelemetryInitializerContainer } from "./JavaScriptSDK.Interfaces/ITelemetryInitializers"; export { createUniqueNamespace } from "./JavaScriptSDK/DataCacheHelper"; export { UnloadHandler, IUnloadHandlerContainer, createUnloadHandlerContainer } from "./JavaScriptSDK/UnloadHandlerContainer"; -export { IUnloadHookContainer, createUnloadHookContainer } from "./JavaScriptSDK/UnloadHookContainer"; +export { IUnloadHookContainer, createUnloadHookContainer, _testHookMaxUnloadHooksCb } from "./JavaScriptSDK/UnloadHookContainer"; export { ITelemetryUpdateState } from "./JavaScriptSDK.Interfaces/ITelemetryUpdateState"; export { ITelemetryUnloadState } from "./JavaScriptSDK.Interfaces/ITelemetryUnloadState"; export { IDistributedTraceContext } from "./JavaScriptSDK.Interfaces/IDistributedTraceContext"; diff --git a/tools/release-tools/setVersion.js b/tools/release-tools/setVersion.js index 6242850f8..23ec50d00 100644 --- a/tools/release-tools/setVersion.js +++ b/tools/release-tools/setVersion.js @@ -391,29 +391,41 @@ function shouldProcess(name) { return false; } +function setPublishTag(package, publishTag) { + if (publishTag !== (package.publishConfig || {}).tag) { + if (!package.publishConfig) { + package.publishConfig = {}; + } + + package.publishConfig.tag = publishTag; + + return true; + } + + return false; +} + function updatePublishConfig(package, newVersion) { let details = getVersionDetails(newVersion); let majorVersion = package.version.split(".")[0]; - - if (!package.publishConfig) { - package.publishConfig = {}; - } + let minorVersion = package.version.split(".")[1]; + let changed = false; if (!details.type || details.type === "release") { // Set the publishing release tag if (majorVersion !== "0") { - package.publishConfig.tag = "release" + majorVersion; - } else { - package.publishConfig.tag = "alpha"; + changed |= setPublishTag(package, "release" + majorVersion); + //} else { + // changed |= setPublishTag(package, "alpha"); } } else { // Set the publishing tag if (details.type === "nightly" || details.type === "dev" || details.type === "beta" || details.type === "alpha") { console.log(` Type - [${details.type}] - ${majorVersion}`); - package.publishConfig.tag = details.type + (majorVersion !== "0" ? majorVersion : ""); + changed |= setPublishTag(package, details.type + (majorVersion !== "0" ? majorVersion : "")); } else { console.log(` Type - [${details.type}]`); - package.publishConfig.tag = details.type; + changed |= setPublishTag(package, details.type); } console.log(` Tag - [${package.publishConfig.tag}]`); @@ -422,7 +434,10 @@ function updatePublishConfig(package, newVersion) { if (package.publishConfig && Object.keys(package.publishConfig).length === 0) { // Nothing left so remove it delete package.publishConfig; + changed = true; } + + return changed; } function updateDependencies(target, orgVersion, newVersion) { @@ -519,6 +534,16 @@ const setPackageJsonRelease = () => { } }); } + } else if (updatePublishConfig(package, newVersion)) { + console.log(" Name - " + package.name + " Publish tag set: " + (package.publishConfig || {}).tag || ""); + changed = true; + + if (!testOnly) { + // Rewrite the file + const newContent = JSON.stringify(package, null, 4) + "\n"; + fs.writeFileSync(theFilename, newContent); + changed = true; + } } else { console.log(" Name - " + package.name + " Version: " + currentVersion + " => Skipped"); }