@ms-cloudpack/cli 0.75.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAS3F;;GAEG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC,GAAG;IACnG;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;CAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAgBf"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAU3F;;GAEG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC,GAAG;IACnG;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;CAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -8,6 +8,7 @@ import { runPrerequisites } from '../../utilities/runPrerequisites.js';
8
8
  import { getFilteredPackages } from '../../utilities/getFilteredPackages.js';
9
9
  import { optimizeDependencies } from './optimizeDependencies.js';
10
10
  import { bulletedList } from '@ms-cloudpack/task-reporter';
11
+ import { SequentialPromiseExecutor } from '../../utilities/sequentialPromiseExecutor.js';
11
12
  /**
12
13
  * Init execution function.
13
14
  */
@@ -29,6 +30,7 @@ async function initApp(options, context) {
29
30
  const { match } = initOptions;
30
31
  const { config, resolveMap } = context.session;
31
32
  const { appPath } = config;
33
+ const executor = new SequentialPromiseExecutor();
32
34
  // Ensure config.generated.packageSettings is initialized.
33
35
  config.generated.packageSettings ??= [];
34
36
  let isExitingPrematurely = false;
@@ -65,6 +67,9 @@ async function initApp(options, context) {
65
67
  const priority = priorityMap.get(packagePath) ?? 0;
66
68
  // Lower priority of this package path by 1.
67
69
  priorityMap.set(packagePath, priority - 1);
70
+ // Use the sequential executor to run the evaluation to avoid concurrency issues.
71
+ executor
72
+ .execute(packagePath, () =>
68
73
  // Evaluate this path, but don't await - when we're done, we'll re-enqueue newly discovered paths.
69
74
  evaluatePath({
70
75
  ...options,
@@ -74,7 +79,7 @@ async function initApp(options, context) {
74
79
  // as we'll re-evaluate packages if they are different since we use a different task id.
75
80
  shouldForce: !isMultiApp && shouldForce,
76
81
  priority,
77
- }, context)
82
+ }, context))
78
83
  .then(({ pathsToEvaluate, pathsToRefresh, shouldExit }) => {
79
84
  pending--;
80
85
  if (shouldExit) {
@@ -118,6 +123,8 @@ async function initApp(options, context) {
118
123
  isExitingPrematurely = true;
119
124
  summaryData.recordException({ packagePath: appPath, error, source: 'init', context: 'running init' });
120
125
  });
126
+ // Clear the executor so that it doesn't hold onto any references to the promises.
127
+ executor.clear();
121
128
  // Log the resolve map to a file if requested. Do this *after* the main init process in case
122
129
  // any additional deps were discovered and added.
123
130
  if (initOptions.logResolveMap) {
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EnsurePackageBundledContext } from '@ms-cloudpack/api-server';\nimport type { PackageImporterContext } from '@ms-cloudpack/common-types';\nimport type { InitOptions } from './types/InitOptions.js';\n\nimport { createPartialApiContext } from '@ms-cloudpack/api-server';\nimport { writeGeneratedConfig } from '@ms-cloudpack/config';\nimport type { InitSummaryData } from './InitSummaryData.js';\nimport { evaluatePath } from './evaluatePath.js';\nimport { verifyExports } from './verifyExports.js';\nimport type { AppCommandContext, CommandActionParams } from '../../types/CommandAction.js';\nimport path from 'path';\nimport { writeJson } from '@ms-cloudpack/json-utilities';\nimport { runPrerequisites } from '../../utilities/runPrerequisites.js';\nimport { getFilteredPackages } from '../../utilities/getFilteredPackages.js';\nimport { optimizeDependencies } from './optimizeDependencies.js';\nimport { bulletedList } from '@ms-cloudpack/task-reporter';\nimport type { InitAppOptions } from './types/InitAppOptions.js';\n\n/**\n * Init execution function.\n */\nexport async function init(\n params: Pick<CommandActionParams<InitOptions>, keyof AppCommandContext | 'options' | 'isMultiApp'> & {\n /**\n * App summary object, created ahead of time so that a partial summary can be generated\n * if the process is interrupted.\n */\n summaryData: InitSummaryData;\n },\n): Promise<void> {\n const { options: initOptions, summaryData, isMultiApp, config, telemetryClient } = params;\n\n await telemetryClient.tracer.startActiveSpan('INIT_APP', async (span) => {\n // Run prerequisites for the app.\n await runPrerequisites(params);\n\n // If --reset is specified, reset the generated config.\n if (initOptions.reset) {\n config.generated = {};\n }\n\n const context = await createPartialApiContext(params);\n\n await initApp({ span, summaryData, initOptions, isMultiApp }, context);\n });\n}\n\nasync function initApp(options: InitAppOptions, context: EnsurePackageBundledContext): Promise<void> {\n const { initOptions, summaryData, span, isMultiApp } = options;\n const { match } = initOptions;\n const { config, resolveMap } = context.session;\n const { appPath } = config;\n\n // Ensure config.generated.packageSettings is initialized.\n config.generated.packageSettings ??= [];\n\n let isExitingPrematurely = false;\n\n await new Promise<void>((resolve) => {\n let pending = 0;\n const visitedSet = new Set<string>();\n const refreshPaths = new Set<string>();\n const priorityMap = new Map<string, number>();\n\n // Start with the app path or requested matches\n const initialPaths = match ? getFilteredPackages(resolveMap, match) : [appPath];\n if (!initialPaths.length) {\n summaryData.addErrors(appPath, [{ text: `No packages found matching ${match}`, source: 'init' }]);\n resolve();\n }\n\n enqueuePaths(new Map(initialPaths.map((packagePath) => [packagePath, undefined])));\n\n /**\n * Enqueue more paths.\n * @param newPaths Mapping from package path to importer context.\n */\n function enqueuePaths(newPaths: Map<string, PackageImporterContext | undefined>): void {\n if (isExitingPrematurely) {\n return;\n }\n\n // Iterate through the given paths.\n for (const [packagePath, importerContext] of newPaths) {\n if (visitedSet.has(packagePath)) {\n console.debug(`Skipping ${packagePath} as it has already been visited.`);\n continue;\n }\n\n visitedSet.add(packagePath);\n pending++;\n\n const shouldForce = refreshPaths.delete(packagePath);\n\n // Get the priority value for this package path, defaults to 0.\n const priority = priorityMap.get(packagePath) ?? 0;\n // Lower priority of this package path by 1.\n priorityMap.set(packagePath, priority - 1);\n\n // Evaluate this path, but don't await - when we're done, we'll re-enqueue newly discovered paths.\n evaluatePath(\n {\n ...options,\n packagePath,\n importerContext,\n // No need to force if we're in a multi-app scenario\n // as we'll re-evaluate packages if they are different since we use a different task id.\n shouldForce: !isMultiApp && shouldForce,\n priority,\n },\n context,\n )\n .then(({ pathsToEvaluate, pathsToRefresh, shouldExit }) => {\n pending--;\n\n if (shouldExit) {\n isExitingPrematurely = true;\n } else if (pathsToEvaluate?.size) {\n // If there are packages that need to be rebuilt, delete them from the visited set to re-enqueue them\n // and add them to the refresh set so that on re-enqueuing we pass the `shouldRerun` flag through\n // on single app runs.\n pathsToRefresh?.forEach((refreshPath) => {\n refreshPaths.add(refreshPath);\n visitedSet.delete(refreshPath);\n });\n\n // Try to enqueue the new paths.\n console.debug(\n `Enqueuing paths found from ${packagePath}:\\n` +\n bulletedList(\n [...pathsToEvaluate].map(([newPath, newContext]) => `${newPath} ${JSON.stringify(newContext)}`),\n ),\n );\n enqueuePaths(pathsToEvaluate);\n }\n\n // If nothing is pending after this call, we're complete.\n if (!pending) {\n resolve();\n }\n })\n .catch((error: unknown) => {\n // Record the exception as an init error for the package.\n // This gives better context than a stack trace which could have come from any package.\n let prefix = 'evaluating package';\n if (importerContext) {\n prefix += ` (context: ${JSON.stringify(importerContext, null, 2).replace(/\\s+/g, ' ')})`;\n }\n summaryData.recordException({ packagePath, error, source: 'init', context: prefix });\n\n // Don't immediately stop evaluation, but don't enqueue more paths.\n isExitingPrematurely = true;\n });\n }\n }\n }).catch((error: unknown) => {\n // If there's an error thrown from some other part of the promise besides evaluatePath (not likely),\n // record it as an init error for the app instead of allowing it to propagate.\n // This allows the overall init summary and any other errors to be logged as usual.\n isExitingPrematurely = true;\n summaryData.recordException({ packagePath: appPath, error, source: 'init', context: 'running init' });\n });\n\n // Log the resolve map to a file if requested. Do this *after* the main init process in case\n // any additional deps were discovered and added.\n if (initOptions.logResolveMap) {\n console.log('\\nWriting resolve map to `resolve-map.json`.');\n await writeJson(path.join(appPath, 'resolve-map.json'), resolveMap);\n }\n\n if (isExitingPrematurely) {\n span.setAttribute('isExitingPrematurely', true);\n } else {\n // Only do extra checks if there's not a major error already\n if (config.features?.optimizeDependencies) {\n // Conditionally scan dependency usage so that we can populate\n // include/excludeDependencies automatically, ensuring the dep list\n // is both minimal (remove unused deps) and complete (include\n // specific devDeps.)\n const excludedDependenciesChanges = await optimizeDependencies(summaryData.getResults(), context);\n summaryData.recordGeneratedChanges(excludedDependenciesChanges);\n }\n\n if (config.features?.verifyExports) {\n const packageResults = await verifyExports(summaryData.getResults(), context);\n for (const [packagePath, errors] of Object.entries(packageResults)) {\n summaryData.addErrors(packagePath, errors);\n }\n }\n }\n\n // The feature \"removeUnusedExports\" doesn't (yet) write summary changes, but we still\n // want to write the generated config if that featureFlag is on.\n const hasSummaryChanges = config.features?.removeUnusedExports || summaryData.hasChanges();\n\n if (!initOptions.check && hasSummaryChanges) {\n // Update the generated config: either write it if there are settings, or delete it if it\n // previously existed but is no longer needed.\n const generatedResult = await writeGeneratedConfig(config.generated, appPath);\n if (generatedResult === 'deleted') {\n summaryData.deletedGeneratedConfig = true;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EnsurePackageBundledContext } from '@ms-cloudpack/api-server';\nimport type { PackageImporterContext } from '@ms-cloudpack/common-types';\nimport type { InitOptions } from './types/InitOptions.js';\n\nimport { createPartialApiContext } from '@ms-cloudpack/api-server';\nimport { writeGeneratedConfig } from '@ms-cloudpack/config';\nimport type { InitSummaryData } from './InitSummaryData.js';\nimport { evaluatePath } from './evaluatePath.js';\nimport { verifyExports } from './verifyExports.js';\nimport type { AppCommandContext, CommandActionParams } from '../../types/CommandAction.js';\nimport path from 'path';\nimport { writeJson } from '@ms-cloudpack/json-utilities';\nimport { runPrerequisites } from '../../utilities/runPrerequisites.js';\nimport { getFilteredPackages } from '../../utilities/getFilteredPackages.js';\nimport { optimizeDependencies } from './optimizeDependencies.js';\nimport { bulletedList } from '@ms-cloudpack/task-reporter';\nimport type { InitAppOptions } from './types/InitAppOptions.js';\nimport { SequentialPromiseExecutor } from '../../utilities/sequentialPromiseExecutor.js';\n\n/**\n * Init execution function.\n */\nexport async function init(\n params: Pick<CommandActionParams<InitOptions>, keyof AppCommandContext | 'options' | 'isMultiApp'> & {\n /**\n * App summary object, created ahead of time so that a partial summary can be generated\n * if the process is interrupted.\n */\n summaryData: InitSummaryData;\n },\n): Promise<void> {\n const { options: initOptions, summaryData, isMultiApp, config, telemetryClient } = params;\n\n await telemetryClient.tracer.startActiveSpan('INIT_APP', async (span) => {\n // Run prerequisites for the app.\n await runPrerequisites(params);\n\n // If --reset is specified, reset the generated config.\n if (initOptions.reset) {\n config.generated = {};\n }\n\n const context = await createPartialApiContext(params);\n\n await initApp({ span, summaryData, initOptions, isMultiApp }, context);\n });\n}\n\nasync function initApp(options: InitAppOptions, context: EnsurePackageBundledContext): Promise<void> {\n const { initOptions, summaryData, span, isMultiApp } = options;\n const { match } = initOptions;\n const { config, resolveMap } = context.session;\n const { appPath } = config;\n const executor = new SequentialPromiseExecutor();\n\n // Ensure config.generated.packageSettings is initialized.\n config.generated.packageSettings ??= [];\n\n let isExitingPrematurely = false;\n\n await new Promise<void>((resolve) => {\n let pending = 0;\n const visitedSet = new Set<string>();\n const refreshPaths = new Set<string>();\n const priorityMap = new Map<string, number>();\n\n // Start with the app path or requested matches\n const initialPaths = match ? getFilteredPackages(resolveMap, match) : [appPath];\n if (!initialPaths.length) {\n summaryData.addErrors(appPath, [{ text: `No packages found matching ${match}`, source: 'init' }]);\n resolve();\n }\n\n enqueuePaths(new Map(initialPaths.map((packagePath) => [packagePath, undefined])));\n\n /**\n * Enqueue more paths.\n * @param newPaths Mapping from package path to importer context.\n */\n function enqueuePaths(newPaths: Map<string, PackageImporterContext | undefined>): void {\n if (isExitingPrematurely) {\n return;\n }\n\n // Iterate through the given paths.\n for (const [packagePath, importerContext] of newPaths) {\n if (visitedSet.has(packagePath)) {\n console.debug(`Skipping ${packagePath} as it has already been visited.`);\n continue;\n }\n\n visitedSet.add(packagePath);\n pending++;\n\n const shouldForce = refreshPaths.delete(packagePath);\n\n // Get the priority value for this package path, defaults to 0.\n const priority = priorityMap.get(packagePath) ?? 0;\n // Lower priority of this package path by 1.\n priorityMap.set(packagePath, priority - 1);\n\n // Use the sequential executor to run the evaluation to avoid concurrency issues.\n executor\n .execute(packagePath, () =>\n // Evaluate this path, but don't await - when we're done, we'll re-enqueue newly discovered paths.\n evaluatePath(\n {\n ...options,\n packagePath,\n importerContext,\n // No need to force if we're in a multi-app scenario\n // as we'll re-evaluate packages if they are different since we use a different task id.\n shouldForce: !isMultiApp && shouldForce,\n priority,\n },\n context,\n ),\n )\n .then(({ pathsToEvaluate, pathsToRefresh, shouldExit }) => {\n pending--;\n\n if (shouldExit) {\n isExitingPrematurely = true;\n } else if (pathsToEvaluate?.size) {\n // If there are packages that need to be rebuilt, delete them from the visited set to re-enqueue them\n // and add them to the refresh set so that on re-enqueuing we pass the `shouldRerun` flag through\n // on single app runs.\n pathsToRefresh?.forEach((refreshPath) => {\n refreshPaths.add(refreshPath);\n visitedSet.delete(refreshPath);\n });\n\n // Try to enqueue the new paths.\n console.debug(\n `Enqueuing paths found from ${packagePath}:\\n` +\n bulletedList(\n [...pathsToEvaluate].map(([newPath, newContext]) => `${newPath} ${JSON.stringify(newContext)}`),\n ),\n );\n enqueuePaths(pathsToEvaluate);\n }\n\n // If nothing is pending after this call, we're complete.\n if (!pending) {\n resolve();\n }\n })\n .catch((error: unknown) => {\n // Record the exception as an init error for the package.\n // This gives better context than a stack trace which could have come from any package.\n let prefix = 'evaluating package';\n if (importerContext) {\n prefix += ` (context: ${JSON.stringify(importerContext, null, 2).replace(/\\s+/g, ' ')})`;\n }\n summaryData.recordException({ packagePath, error, source: 'init', context: prefix });\n\n // Don't immediately stop evaluation, but don't enqueue more paths.\n isExitingPrematurely = true;\n });\n }\n }\n }).catch((error: unknown) => {\n // If there's an error thrown from some other part of the promise besides evaluatePath (not likely),\n // record it as an init error for the app instead of allowing it to propagate.\n // This allows the overall init summary and any other errors to be logged as usual.\n isExitingPrematurely = true;\n summaryData.recordException({ packagePath: appPath, error, source: 'init', context: 'running init' });\n });\n\n // Clear the executor so that it doesn't hold onto any references to the promises.\n executor.clear();\n\n // Log the resolve map to a file if requested. Do this *after* the main init process in case\n // any additional deps were discovered and added.\n if (initOptions.logResolveMap) {\n console.log('\\nWriting resolve map to `resolve-map.json`.');\n await writeJson(path.join(appPath, 'resolve-map.json'), resolveMap);\n }\n\n if (isExitingPrematurely) {\n span.setAttribute('isExitingPrematurely', true);\n } else {\n // Only do extra checks if there's not a major error already\n if (config.features?.optimizeDependencies) {\n // Conditionally scan dependency usage so that we can populate\n // include/excludeDependencies automatically, ensuring the dep list\n // is both minimal (remove unused deps) and complete (include\n // specific devDeps.)\n const excludedDependenciesChanges = await optimizeDependencies(summaryData.getResults(), context);\n summaryData.recordGeneratedChanges(excludedDependenciesChanges);\n }\n\n if (config.features?.verifyExports) {\n const packageResults = await verifyExports(summaryData.getResults(), context);\n for (const [packagePath, errors] of Object.entries(packageResults)) {\n summaryData.addErrors(packagePath, errors);\n }\n }\n }\n\n // The feature \"removeUnusedExports\" doesn't (yet) write summary changes, but we still\n // want to write the generated config if that featureFlag is on.\n const hasSummaryChanges = config.features?.removeUnusedExports || summaryData.hasChanges();\n\n if (!initOptions.check && hasSummaryChanges) {\n // Update the generated config: either write it if there are settings, or delete it if it\n // previously existed but is no longer needed.\n const generatedResult = await writeGeneratedConfig(config.generated, appPath);\n if (generatedResult === 'deleted') {\n summaryData.deletedGeneratedConfig = true;\n }\n }\n}\n"]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Class for executing promises sequentially by ID.
3
+ * Ensures that operations with the same ID are processed in order.
4
+ * Automatically cleans up completed operations to prevent memory leaks.
5
+ */
6
+ export declare class SequentialPromiseExecutor {
7
+ /**
8
+ * Map tracking the last operation promise for each ID
9
+ */
10
+ operations: Map<string, Promise<unknown>>;
11
+ /**
12
+ * Execute a promise-returning function, ensuring sequential execution for the same ID.
13
+ * Automatically removes the promise from tracking once it completes.
14
+ */
15
+ execute<T>(id: string, execute: () => Promise<T>): Promise<T>;
16
+ /**
17
+ * Clear all tracked operations for all IDs.
18
+ * This is still useful for forcibly clearing all operations when needed.
19
+ */
20
+ clear(): void;
21
+ }
22
+ //# sourceMappingURL=sequentialPromiseExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequentialPromiseExecutor.d.ts","sourceRoot":"","sources":["../../src/utilities/sequentialPromiseExecutor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,yBAAyB;IACpC;;OAEG;IACI,UAAU,gCAAuC;IAExD;;;OAGG;IACU,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiC1E;;;OAGG;IACI,KAAK,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Class for executing promises sequentially by ID.
3
+ * Ensures that operations with the same ID are processed in order.
4
+ * Automatically cleans up completed operations to prevent memory leaks.
5
+ */
6
+ export class SequentialPromiseExecutor {
7
+ /**
8
+ * Map tracking the last operation promise for each ID
9
+ */
10
+ operations = new Map();
11
+ /**
12
+ * Execute a promise-returning function, ensuring sequential execution for the same ID.
13
+ * Automatically removes the promise from tracking once it completes.
14
+ */
15
+ async execute(id, execute) {
16
+ // Get the promise for the last operation with this ID, or a resolved promise if none
17
+ const lastOperation = this.operations.get(id) || Promise.resolve();
18
+ // Create a new operation that starts after the previous one finishes
19
+ const operation = lastOperation
20
+ // Suppress errors from previous operations to prevent chain breakage
21
+ .catch((err) => {
22
+ console.debug(`Ignoring error from previous operation on ${id}: ${err instanceof Error ? err.stack : err}`);
23
+ })
24
+ .then(execute); // Execute the new operation and use its return value
25
+ // Set up cleanup when this operation completes (success or failure)
26
+ const cleanupOperation = operation
27
+ // Ensure cleanup happens even if operation fails
28
+ .catch((err) => {
29
+ console.debug(`Ignoring error cleaning operation on ${id}: ${err instanceof Error ? err.stack : err}`);
30
+ })
31
+ .finally(() => {
32
+ // Only clean up if this is still the current operation for this ID
33
+ if (this.operations.get(id) === cleanupOperation) {
34
+ this.operations.delete(id);
35
+ }
36
+ });
37
+ // Update the last operation for this ID with the operation that includes cleanup
38
+ this.operations.set(id, cleanupOperation);
39
+ // Return the original operation without the cleanup logic to avoid creating
40
+ // a circular reference that might prevent garbage collection
41
+ return operation;
42
+ }
43
+ /**
44
+ * Clear all tracked operations for all IDs.
45
+ * This is still useful for forcibly clearing all operations when needed.
46
+ */
47
+ clear() {
48
+ this.operations.clear();
49
+ }
50
+ }
51
+ //# sourceMappingURL=sequentialPromiseExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequentialPromiseExecutor.js","sourceRoot":"","sources":["../../src/utilities/sequentialPromiseExecutor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,yBAAyB;IACpC;;OAEG;IACI,UAAU,GAAG,IAAI,GAAG,EAA4B,CAAC;IAExD;;;OAGG;IACI,KAAK,CAAC,OAAO,CAAI,EAAU,EAAE,OAAyB;QAC3D,qFAAqF;QACrF,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAEnE,qEAAqE;QACrE,MAAM,SAAS,GAAG,aAAa;YAC7B,qEAAqE;aACpE,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9G,CAAC,CAAC;aACD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,qDAAqD;QAEvE,oEAAoE;QACpE,MAAM,gBAAgB,GAAG,SAAS;YAChC,iDAAiD;aAChD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACzG,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,mEAAmE;YACnE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,gBAAgB,EAAE,CAAC;gBACjD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEL,iFAAiF;QACjF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAE1C,4EAA4E;QAC5E,6DAA6D;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,KAAK;QACV,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF","sourcesContent":["/**\n * Class for executing promises sequentially by ID.\n * Ensures that operations with the same ID are processed in order.\n * Automatically cleans up completed operations to prevent memory leaks.\n */\nexport class SequentialPromiseExecutor {\n /**\n * Map tracking the last operation promise for each ID\n */\n public operations = new Map<string, Promise<unknown>>();\n\n /**\n * Execute a promise-returning function, ensuring sequential execution for the same ID.\n * Automatically removes the promise from tracking once it completes.\n */\n public async execute<T>(id: string, execute: () => Promise<T>): Promise<T> {\n // Get the promise for the last operation with this ID, or a resolved promise if none\n const lastOperation = this.operations.get(id) || Promise.resolve();\n\n // Create a new operation that starts after the previous one finishes\n const operation = lastOperation\n // Suppress errors from previous operations to prevent chain breakage\n .catch((err) => {\n console.debug(`Ignoring error from previous operation on ${id}: ${err instanceof Error ? err.stack : err}`);\n })\n .then(execute); // Execute the new operation and use its return value\n\n // Set up cleanup when this operation completes (success or failure)\n const cleanupOperation = operation\n // Ensure cleanup happens even if operation fails\n .catch((err) => {\n console.debug(`Ignoring error cleaning operation on ${id}: ${err instanceof Error ? err.stack : err}`);\n })\n .finally(() => {\n // Only clean up if this is still the current operation for this ID\n if (this.operations.get(id) === cleanupOperation) {\n this.operations.delete(id);\n }\n });\n\n // Update the last operation for this ID with the operation that includes cleanup\n this.operations.set(id, cleanupOperation);\n\n // Return the original operation without the cleanup logic to avoid creating\n // a circular reference that might prevent garbage collection\n return operation;\n }\n\n /**\n * Clear all tracked operations for all IDs.\n * This is still useful for forcibly clearing all operations when needed.\n */\n public clear(): void {\n this.operations.clear();\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ms-cloudpack/cli",
3
- "version": "0.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "The Cloudpack command line interface - a tool for managing fast inner and outer looping in web apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,26 +18,26 @@
18
18
  "cloudpack": "./bin/cloudpack.js"
19
19
  },
20
20
  "dependencies": {
21
- "@ms-cloudpack/api-server": "^0.63.11",
22
- "@ms-cloudpack/app-server": "^0.18.14",
23
- "@ms-cloudpack/bundler": "^0.25.13",
24
- "@ms-cloudpack/bundler-capabilities": "^0.2.26",
25
- "@ms-cloudpack/common-types": "^0.24.20",
26
- "@ms-cloudpack/config": "^0.35.10",
27
- "@ms-cloudpack/create-express-app": "^1.10.35",
21
+ "@ms-cloudpack/api-server": "^0.64.0",
22
+ "@ms-cloudpack/app-server": "^0.18.15",
23
+ "@ms-cloudpack/bundler": "^0.25.14",
24
+ "@ms-cloudpack/bundler-capabilities": "^0.2.27",
25
+ "@ms-cloudpack/common-types": "^0.25.0",
26
+ "@ms-cloudpack/config": "^0.35.11",
27
+ "@ms-cloudpack/create-express-app": "^1.10.36",
28
28
  "@ms-cloudpack/environment": "^0.1.1",
29
29
  "@ms-cloudpack/json-utilities": "^0.1.10",
30
- "@ms-cloudpack/link-proxy": "^0.2.13",
31
- "@ms-cloudpack/overlay": "^0.19.9",
32
- "@ms-cloudpack/package-utilities": "^12.3.12",
30
+ "@ms-cloudpack/link-proxy": "^0.2.14",
31
+ "@ms-cloudpack/overlay": "^0.19.10",
32
+ "@ms-cloudpack/package-utilities": "^12.3.13",
33
33
  "@ms-cloudpack/path-string-parsing": "^1.2.7",
34
- "@ms-cloudpack/path-utilities": "^3.1.6",
35
- "@ms-cloudpack/remote-cache": "^0.11.22",
36
- "@ms-cloudpack/setup-utilities": "^0.5.27",
37
- "@ms-cloudpack/task-reporter": "^0.17.0",
38
- "@ms-cloudpack/telemetry": "^0.11.24",
34
+ "@ms-cloudpack/path-utilities": "^3.1.7",
35
+ "@ms-cloudpack/remote-cache": "^0.11.23",
36
+ "@ms-cloudpack/setup-utilities": "^0.5.28",
37
+ "@ms-cloudpack/task-reporter": "^0.17.1",
38
+ "@ms-cloudpack/telemetry": "^0.11.25",
39
39
  "@yarnpkg/lockfile": "^1.1.0",
40
- "commander": "^13.0.0",
40
+ "commander": "^14.0.0",
41
41
  "cross-spawn": "^7.0.3",
42
42
  "didyoumean": "^1.2.2",
43
43
  "get-port": "^7.0.0",
@@ -48,7 +48,7 @@
48
48
  "workspace-tools": "^0.38.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@ms-cloudpack/common-types": "^0.24.20",
51
+ "@ms-cloudpack/common-types": "^0.25.0",
52
52
  "@ms-cloudpack/common-types-browser": "^0.6.1",
53
53
  "@ms-cloudpack/eslint-plugin-internal": "^0.0.1",
54
54
  "@ms-cloudpack/scripts": "^0.0.1",