@tomflow/proflow-platform-cli 0.1.10 → 0.1.12
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 +12 -0
- package/dist/deployment/adapter.d.ts +5 -5
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/src/apply/driver.d.ts +4 -0
- package/dist/src/apply/driver.js +70 -1
- package/dist/src/cli.js +18 -2
- package/package.json +1 -1
- package/proflow.module.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @tomflow/proflow-platform-cli
|
|
2
2
|
|
|
3
|
+
## 0.1.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
|
|
9
|
+
## 0.1.11
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Use pnpm's global config form to disable scripts during package removal so Workspace uninstall works on pnpm 11.
|
|
14
|
+
|
|
3
15
|
## 0.1.10
|
|
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.
|
|
8
|
+
moduleVersion: "0.1.12";
|
|
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.
|
|
19
|
+
moduleVersion: "0.1.12";
|
|
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.
|
|
30
|
+
moduleVersion: "0.1.12";
|
|
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.
|
|
41
|
+
moduleVersion: "0.1.12";
|
|
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.
|
|
52
|
+
moduleVersion: "0.1.12";
|
|
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.
|
|
6
|
+
readonly moduleVersion: "0.1.12";
|
|
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.
|
|
6
|
+
moduleVersion: "0.1.12",
|
|
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;
|
package/dist/src/apply/driver.js
CHANGED
|
@@ -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 removedPackageSpecs = new Set(options.removedModules.map((module) => `${module.packageName}@${module.moduleVersion}`));
|
|
26
|
+
await cleanupPnpmReleaseAgeExcludes(options.workspaceRoot, removedPackageSpecs);
|
|
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;
|
|
@@ -51,7 +59,7 @@ async function mutatePackage(runner, manager, workspaceRoot, operation, packageS
|
|
|
51
59
|
async function packageManagerArgs(runner, manager, workspaceRoot, operation, packageSpec) {
|
|
52
60
|
if (manager.name === "pnpm") {
|
|
53
61
|
return operation === "remove"
|
|
54
|
-
? ["
|
|
62
|
+
? ["--config.ignore-scripts=true", "remove", packageSpec]
|
|
55
63
|
: ["add", "--save-exact", "--ignore-scripts", packageSpec];
|
|
56
64
|
}
|
|
57
65
|
if (manager.name === "npm") {
|
|
@@ -148,6 +156,67 @@ async function readWorkspaceManifest(workspaceRoot) {
|
|
|
148
156
|
return undefined;
|
|
149
157
|
}
|
|
150
158
|
}
|
|
159
|
+
async function cleanupPnpmReleaseAgeExcludes(workspaceRoot, removedPackageSpecs) {
|
|
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
|
+
return !removedPackageSpecs.has(value);
|
|
185
|
+
});
|
|
186
|
+
const hasListItem = retained.some((line) => /^\s*-\s+/.test(line));
|
|
187
|
+
const replacement = hasListItem ? [lines[keyIndex] ?? "", ...retained] : [];
|
|
188
|
+
let next = [
|
|
189
|
+
...lines.slice(0, keyIndex),
|
|
190
|
+
...replacement,
|
|
191
|
+
...lines.slice(endIndex),
|
|
192
|
+
].join("\n");
|
|
193
|
+
if (raw.endsWith("\n") && !next.endsWith("\n"))
|
|
194
|
+
next += "\n";
|
|
195
|
+
if (next !== raw)
|
|
196
|
+
await atomicWrite(path, next);
|
|
197
|
+
}
|
|
198
|
+
async function normalizeEmptyPnpmRootImporter(workspaceRoot) {
|
|
199
|
+
const path = join(workspaceRoot, "pnpm-lock.yaml");
|
|
200
|
+
let raw;
|
|
201
|
+
try {
|
|
202
|
+
raw = await readFile(path, "utf8");
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
if (isMissingFile(error))
|
|
206
|
+
return;
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
const next = raw.replace("\nimporters:\n\n .: {}\n", "\nimporters:\n .: {}\n");
|
|
210
|
+
if (next !== raw)
|
|
211
|
+
await atomicWrite(path, next);
|
|
212
|
+
}
|
|
213
|
+
function stripYamlQuotes(value) {
|
|
214
|
+
if ((value.startsWith("'") && value.endsWith("'")) ||
|
|
215
|
+
(value.startsWith('"') && value.endsWith('"'))) {
|
|
216
|
+
return value.slice(1, -1);
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
151
220
|
function hasOwn(record, key) {
|
|
152
221
|
return record !== undefined && Object.hasOwn(record, key);
|
|
153
222
|
}
|
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,26 @@ 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
|
+
try {
|
|
859
|
+
await rmdir(ctx.paths.proflow);
|
|
860
|
+
}
|
|
861
|
+
catch (error) {
|
|
862
|
+
const code = typeof error === "object" && error !== null
|
|
863
|
+
? Reflect.get(error, "code")
|
|
864
|
+
: undefined;
|
|
865
|
+
if (code !== "ENOENT" && code !== "ENOTEMPTY")
|
|
866
|
+
throw error;
|
|
867
|
+
}
|
|
852
868
|
const completed = binding;
|
|
853
869
|
await clearGlobalBinding({
|
|
854
870
|
workspaceInstanceId: binding.workspaceInstanceId,
|
package/package.json
CHANGED
package/proflow.module.json
CHANGED