@tomflow/proflow-platform-cli 0.1.11 → 0.1.13

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @tomflow/proflow-platform-cli
2
2
 
3
+ ## 0.1.13
4
+
5
+ ### Patch Changes
6
+
7
+ - Fully clean Workspace uninstall artifacts by removing empty ProFlow layout directories and stale pnpm release-age entries across prior managed versions.
8
+
9
+ ## 0.1.12
10
+
11
+ ### Patch Changes
12
+
13
+ - Clean pnpm release-age and empty-root lockfile artifacts after whole Workspace uninstall, and remove the `.proflow` root only when it is empty while preserving non-deployment data.
14
+
3
15
  ## 0.1.11
4
16
 
5
17
  ### Patch Changes
@@ -5,7 +5,7 @@ export declare const behaviorAdapter: {
5
5
  ok: boolean;
6
6
  status: "SUCCEEDED";
7
7
  moduleRef: "platform-cli";
8
- moduleVersion: "0.1.11";
8
+ moduleVersion: "0.1.13";
9
9
  data?: {} | null;
10
10
  };
11
11
  observedEffects: never[];
@@ -16,7 +16,7 @@ export declare const behaviorAdapter: {
16
16
  ok: boolean;
17
17
  status: "SUCCEEDED";
18
18
  moduleRef: "platform-cli";
19
- moduleVersion: "0.1.11";
19
+ moduleVersion: "0.1.13";
20
20
  data?: {} | null;
21
21
  };
22
22
  observedEffects: never[];
@@ -27,7 +27,7 @@ export declare const behaviorAdapter: {
27
27
  ok: boolean;
28
28
  status: "SUCCEEDED";
29
29
  moduleRef: "platform-cli";
30
- moduleVersion: "0.1.11";
30
+ moduleVersion: "0.1.13";
31
31
  data?: {} | null;
32
32
  };
33
33
  observedEffects: never[];
@@ -38,7 +38,7 @@ export declare const behaviorAdapter: {
38
38
  ok: boolean;
39
39
  status: "SUCCEEDED";
40
40
  moduleRef: "platform-cli";
41
- moduleVersion: "0.1.11";
41
+ moduleVersion: "0.1.13";
42
42
  data?: {} | null;
43
43
  };
44
44
  observedEffects: never[];
@@ -49,7 +49,7 @@ export declare const behaviorAdapter: {
49
49
  ok: boolean;
50
50
  status: "SUCCEEDED";
51
51
  moduleRef: "platform-cli";
52
- moduleVersion: "0.1.11";
52
+ moduleVersion: "0.1.13";
53
53
  data?: {} | null;
54
54
  };
55
55
  observedEffects: never[];
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "platform-cli";
5
5
  readonly packageName: "@tomflow/proflow-platform-cli";
6
- readonly moduleVersion: "0.1.11";
6
+ readonly moduleVersion: "0.1.13";
7
7
  readonly kind: "cli";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "platform-cli",
5
5
  packageName: "@tomflow/proflow-platform-cli",
6
- moduleVersion: "0.1.11",
6
+ moduleVersion: "0.1.13",
7
7
  kind: "cli",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -17,6 +17,10 @@ export interface PackageManagerDriver {
17
17
  * no-op driver to claim a product Workspace package mutation succeeded.
18
18
  */
19
19
  export declare function workspaceResidentDriver(): PackageManagerDriver;
20
+ export declare function cleanupWorkspacePackageManagerArtifacts(options: {
21
+ workspaceRoot: string;
22
+ removedModules: readonly ResolvedModule[];
23
+ }): Promise<void>;
20
24
  export declare function createWorkspacePackageManagerDriver(options: {
21
25
  workspaceRoot: string;
22
26
  runner?: PackageCommandRunner;
@@ -18,6 +18,14 @@ export function workspaceResidentDriver() {
18
18
  async remove() { },
19
19
  };
20
20
  }
21
+ export async function cleanupWorkspacePackageManagerArtifacts(options) {
22
+ const manager = await readWorkspacePackageManagerSelection(options.workspaceRoot);
23
+ if (manager.name !== "pnpm")
24
+ return;
25
+ const removedPackageNames = new Set(options.removedModules.map((module) => module.packageName));
26
+ await cleanupPnpmReleaseAgeExcludes(options.workspaceRoot, removedPackageNames);
27
+ await normalizeEmptyPnpmRootImporter(options.workspaceRoot);
28
+ }
21
29
  export function createWorkspacePackageManagerDriver(options) {
22
30
  const runner = options.runner ?? systemPackageCommandRunner();
23
31
  const executableAvailable = options.executableAvailable ?? findExecutable;
@@ -148,6 +156,71 @@ async function readWorkspaceManifest(workspaceRoot) {
148
156
  return undefined;
149
157
  }
150
158
  }
159
+ async function cleanupPnpmReleaseAgeExcludes(workspaceRoot, removedPackageNames) {
160
+ const path = join(workspaceRoot, "pnpm-workspace.yaml");
161
+ let raw;
162
+ try {
163
+ raw = await readFile(path, "utf8");
164
+ }
165
+ catch (error) {
166
+ if (isMissingFile(error))
167
+ return;
168
+ throw error;
169
+ }
170
+ const lines = raw.split("\n");
171
+ const keyIndex = lines.indexOf("minimumReleaseAgeExclude:");
172
+ if (keyIndex < 0)
173
+ return;
174
+ let endIndex = keyIndex + 1;
175
+ while (endIndex < lines.length &&
176
+ (lines[endIndex]?.trim() === "" || /^\s/.test(lines[endIndex] ?? ""))) {
177
+ endIndex += 1;
178
+ }
179
+ const retained = lines.slice(keyIndex + 1, endIndex).filter((line) => {
180
+ const match = /^\s*-\s+(.+?)\s*$/.exec(line);
181
+ if (match === null)
182
+ return true;
183
+ const value = stripYamlQuotes(match[1] ?? "");
184
+ for (const packageName of removedPackageNames) {
185
+ if (value === packageName || value.startsWith(`${packageName}@`))
186
+ return false;
187
+ }
188
+ return true;
189
+ });
190
+ const hasListItem = retained.some((line) => /^\s*-\s+/.test(line));
191
+ const replacement = hasListItem ? [lines[keyIndex] ?? "", ...retained] : [];
192
+ let next = [
193
+ ...lines.slice(0, keyIndex),
194
+ ...replacement,
195
+ ...lines.slice(endIndex),
196
+ ].join("\n");
197
+ if (raw.endsWith("\n") && !next.endsWith("\n"))
198
+ next += "\n";
199
+ if (next !== raw)
200
+ await atomicWrite(path, next);
201
+ }
202
+ async function normalizeEmptyPnpmRootImporter(workspaceRoot) {
203
+ const path = join(workspaceRoot, "pnpm-lock.yaml");
204
+ let raw;
205
+ try {
206
+ raw = await readFile(path, "utf8");
207
+ }
208
+ catch (error) {
209
+ if (isMissingFile(error))
210
+ return;
211
+ throw error;
212
+ }
213
+ const next = raw.replace("\nimporters:\n\n .: {}\n", "\nimporters:\n .: {}\n");
214
+ if (next !== raw)
215
+ await atomicWrite(path, next);
216
+ }
217
+ function stripYamlQuotes(value) {
218
+ if ((value.startsWith("'") && value.endsWith("'")) ||
219
+ (value.startsWith('"') && value.endsWith('"'))) {
220
+ return value.slice(1, -1);
221
+ }
222
+ return value;
223
+ }
151
224
  function hasOwn(record, key) {
152
225
  return record !== undefined && Object.hasOwn(record, key);
153
226
  }
package/dist/src/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { readFile, rm } from "node:fs/promises";
2
+ import { readFile, rm, rmdir } from "node:fs/promises";
3
3
  import { parseModuleDescriptor, } from "@tomflow/proflow-module-contract";
4
4
  import { descriptor as platformCliDescriptor } from "../deployment/descriptor.js";
5
5
  import { applyPlan } from "./apply/apply.js";
6
6
  import { rebuildCurrentAssumptions } from "./apply/current.js";
7
- import { createWorkspacePackageManagerDriver } from "./apply/driver.js";
7
+ import { cleanupWorkspacePackageManagerArtifacts, createWorkspacePackageManagerDriver, } from "./apply/driver.js";
8
8
  import { acquireGlobalOperationLock, canonicalizeWorkspace, claimWorkspaceBinding, clearGlobalBinding, forgetMissingWorkspaceBinding, loadGlobalBinding, observeBoundWorkspace, requireBoundWorkspace, updateGlobalBindingState, } from "./binding/global-binding.js";
9
9
  import { buildProductionBindings, importRawAdapter, } from "./binding/production-bindings.js";
10
10
  import { AutoModuleCatalog, discoverModules } from "./discovery/discover.js";
@@ -845,10 +845,37 @@ async function handlePlatformInstanceUninstall(args, runtime) {
845
845
  if (remaining.length > 0) {
846
846
  throw new PlatformError("UNINSTALL_FAILED", `Platform Instance uninstall left managed modules: ${remaining.map((module) => module.moduleRef).join(", ")}`);
847
847
  }
848
+ if (modules.length > 0) {
849
+ await cleanupWorkspacePackageManagerArtifacts({
850
+ workspaceRoot: binding.workspaceRealPath,
851
+ removedModules: modules,
852
+ });
853
+ }
848
854
  // Deployment-owned plans/state/verification/instance identity must not leak
849
855
  // into a future install of the same directory. Business/domain data outside
850
856
  // `.proflow/deployment` is intentionally preserved.
851
857
  await rm(ctx.paths.deployment, { recursive: true, force: true });
858
+ for (const path of [
859
+ ctx.paths.logsDeployment,
860
+ ctx.paths.logs,
861
+ ctx.paths.config,
862
+ ctx.paths.data,
863
+ ctx.paths.runtime,
864
+ ctx.paths.cache,
865
+ ctx.paths.tmp,
866
+ ctx.paths.proflow,
867
+ ]) {
868
+ try {
869
+ await rmdir(path);
870
+ }
871
+ catch (error) {
872
+ const code = typeof error === "object" && error !== null
873
+ ? Reflect.get(error, "code")
874
+ : undefined;
875
+ if (code !== "ENOENT" && code !== "ENOTEMPTY")
876
+ throw error;
877
+ }
878
+ }
852
879
  const completed = binding;
853
880
  await clearGlobalBinding({
854
881
  workspaceInstanceId: binding.workspaceInstanceId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-platform-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "platform-cli",
5
5
  "packageName": "@tomflow/proflow-platform-cli",
6
- "moduleVersion": "0.1.11",
6
+ "moduleVersion": "0.1.13",
7
7
  "kind": "cli",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",