@tomflow/proflow-platform-cli 0.1.12 → 0.1.14
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.js +8 -4
- package/dist/src/cli.js +101 -9
- package/dist/src/lifecycle/dispatch.d.ts +4 -3
- package/dist/src/lifecycle/dispatch.js +9 -4
- package/package.json +3 -3
- 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.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Gate `platform start` on managed preflight, make platform-level `restart` a stop-then-start sequence without an extra preflight, and render lifecycle / verify / doctor results clearly for human users.
|
|
8
|
+
|
|
9
|
+
## 0.1.13
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Fully clean Workspace uninstall artifacts by removing empty ProFlow layout directories and stale pnpm release-age entries across prior managed versions.
|
|
14
|
+
|
|
3
15
|
## 0.1.12
|
|
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.14";
|
|
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.14";
|
|
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.14";
|
|
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.14";
|
|
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.14";
|
|
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.14";
|
|
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.14",
|
|
7
7
|
kind: "cli",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
package/dist/src/apply/driver.js
CHANGED
|
@@ -22,8 +22,8 @@ export async function cleanupWorkspacePackageManagerArtifacts(options) {
|
|
|
22
22
|
const manager = await readWorkspacePackageManagerSelection(options.workspaceRoot);
|
|
23
23
|
if (manager.name !== "pnpm")
|
|
24
24
|
return;
|
|
25
|
-
const
|
|
26
|
-
await cleanupPnpmReleaseAgeExcludes(options.workspaceRoot,
|
|
25
|
+
const removedPackageNames = new Set(options.removedModules.map((module) => module.packageName));
|
|
26
|
+
await cleanupPnpmReleaseAgeExcludes(options.workspaceRoot, removedPackageNames);
|
|
27
27
|
await normalizeEmptyPnpmRootImporter(options.workspaceRoot);
|
|
28
28
|
}
|
|
29
29
|
export function createWorkspacePackageManagerDriver(options) {
|
|
@@ -156,7 +156,7 @@ async function readWorkspaceManifest(workspaceRoot) {
|
|
|
156
156
|
return undefined;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
async function cleanupPnpmReleaseAgeExcludes(workspaceRoot,
|
|
159
|
+
async function cleanupPnpmReleaseAgeExcludes(workspaceRoot, removedPackageNames) {
|
|
160
160
|
const path = join(workspaceRoot, "pnpm-workspace.yaml");
|
|
161
161
|
let raw;
|
|
162
162
|
try {
|
|
@@ -181,7 +181,11 @@ async function cleanupPnpmReleaseAgeExcludes(workspaceRoot, removedPackageSpecs)
|
|
|
181
181
|
if (match === null)
|
|
182
182
|
return true;
|
|
183
183
|
const value = stripYamlQuotes(match[1] ?? "");
|
|
184
|
-
|
|
184
|
+
for (const packageName of removedPackageNames) {
|
|
185
|
+
if (value === packageName || value.startsWith(`${packageName}@`))
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
return true;
|
|
185
189
|
});
|
|
186
190
|
const hasListItem = retained.some((line) => /^\s*-\s+/.test(line));
|
|
187
191
|
const replacement = hasListItem ? [lines[keyIndex] ?? "", ...retained] : [];
|
package/dist/src/cli.js
CHANGED
|
@@ -855,15 +855,26 @@ async function handlePlatformInstanceUninstall(args, runtime) {
|
|
|
855
855
|
// into a future install of the same directory. Business/domain data outside
|
|
856
856
|
// `.proflow/deployment` is intentionally preserved.
|
|
857
857
|
await rm(ctx.paths.deployment, { recursive: true, force: true });
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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
|
+
}
|
|
867
878
|
}
|
|
868
879
|
const completed = binding;
|
|
869
880
|
await clearGlobalBinding({
|
|
@@ -896,6 +907,12 @@ async function handlePlatformInstanceUninstall(args, runtime) {
|
|
|
896
907
|
}
|
|
897
908
|
}
|
|
898
909
|
async function handleLifecycle(ctx, args, primitive) {
|
|
910
|
+
if (primitive === "start") {
|
|
911
|
+
const preflight = await handlePreflight(ctx, args);
|
|
912
|
+
if (preflight.status !== "SUCCEEDED") {
|
|
913
|
+
return outcome("start", preflight.status, preflight.data);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
899
916
|
const modules = await discoverModules({ catalog: ctx.catalog });
|
|
900
917
|
const selected = selectModules(modules, args.positional[0]);
|
|
901
918
|
const result = primitive === "start"
|
|
@@ -1171,7 +1188,82 @@ function toMachineResult(outcomeResult) {
|
|
|
1171
1188
|
function isRecord(value) {
|
|
1172
1189
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1173
1190
|
}
|
|
1191
|
+
function humanArrayLines(data) {
|
|
1192
|
+
const isVerification = data.some((item) => isRecord(item) && isRecord(item.record));
|
|
1193
|
+
const isDoctor = data.some((item) => isRecord(item) && Array.isArray(item.errors) && isRecord(item.nextAction));
|
|
1194
|
+
const lines = [
|
|
1195
|
+
isVerification ? "Verification:" : isDoctor ? "Doctor:" : "Lifecycle:",
|
|
1196
|
+
];
|
|
1197
|
+
let skippedUnsupported = 0;
|
|
1198
|
+
for (const item of data) {
|
|
1199
|
+
if (!isRecord(item))
|
|
1200
|
+
continue;
|
|
1201
|
+
const moduleRef = typeof item.moduleRef === "string" ? item.moduleRef : "unknown";
|
|
1202
|
+
const runStatus = typeof item.status === "string" ? item.status : "UNKNOWN";
|
|
1203
|
+
if (runStatus === "SKIP_UNSUPPORTED") {
|
|
1204
|
+
skippedUnsupported += 1;
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
const result = isRecord(item.result) ? item.result : undefined;
|
|
1208
|
+
const resultStatus = result !== undefined && typeof result.status === "string"
|
|
1209
|
+
? result.status
|
|
1210
|
+
: runStatus;
|
|
1211
|
+
let detail = "";
|
|
1212
|
+
const actionRequired = result !== undefined && isRecord(result.actionRequired)
|
|
1213
|
+
? result.actionRequired
|
|
1214
|
+
: undefined;
|
|
1215
|
+
const error = result !== undefined && isRecord(result.error) ? result.error : undefined;
|
|
1216
|
+
if (actionRequired !== undefined) {
|
|
1217
|
+
const action = typeof actionRequired.action === "string"
|
|
1218
|
+
? actionRequired.action
|
|
1219
|
+
: "action-required";
|
|
1220
|
+
const description = typeof actionRequired.description === "string"
|
|
1221
|
+
? actionRequired.description
|
|
1222
|
+
: "human action required";
|
|
1223
|
+
detail = ` — ${action}: ${description}`;
|
|
1224
|
+
}
|
|
1225
|
+
else if (error !== undefined) {
|
|
1226
|
+
const code = typeof error.code === "string" ? error.code : "COMMAND_FAILED";
|
|
1227
|
+
const message = typeof error.message === "string" ? error.message : "Unknown error";
|
|
1228
|
+
detail = ` — ${code}: ${message}`;
|
|
1229
|
+
}
|
|
1230
|
+
else if (isRecord(item.record) &&
|
|
1231
|
+
typeof item.record.summary === "string") {
|
|
1232
|
+
detail = ` — ${item.record.summary}`;
|
|
1233
|
+
}
|
|
1234
|
+
lines.push(`- ${moduleRef}: ${resultStatus}${detail}`);
|
|
1235
|
+
if (Array.isArray(item.errors)) {
|
|
1236
|
+
for (const doctorError of item.errors) {
|
|
1237
|
+
if (!isRecord(doctorError))
|
|
1238
|
+
continue;
|
|
1239
|
+
const code = typeof doctorError.code === "string"
|
|
1240
|
+
? doctorError.code
|
|
1241
|
+
: "COMMAND_FAILED";
|
|
1242
|
+
const message = typeof doctorError.message === "string"
|
|
1243
|
+
? doctorError.message
|
|
1244
|
+
: "Unknown error";
|
|
1245
|
+
lines.push(` Error: ${code}: ${message}`);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
if (isRecord(item.nextAction)) {
|
|
1249
|
+
if (item.nextAction.kind === "human-action" &&
|
|
1250
|
+
typeof item.nextAction.action === "string" &&
|
|
1251
|
+
typeof item.nextAction.description === "string") {
|
|
1252
|
+
lines.push(` Next: ${item.nextAction.action} — ${item.nextAction.description}`);
|
|
1253
|
+
}
|
|
1254
|
+
else if (item.nextAction.kind === "repair-plan" &&
|
|
1255
|
+
typeof item.nextAction.summary === "string") {
|
|
1256
|
+
lines.push(` Next: platform plan --intent repair — ${item.nextAction.summary}`);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
if (skippedUnsupported > 0)
|
|
1261
|
+
lines.push(`Skipped unsupported: ${skippedUnsupported}`);
|
|
1262
|
+
return lines;
|
|
1263
|
+
}
|
|
1174
1264
|
function humanDetailLines(data) {
|
|
1265
|
+
if (Array.isArray(data))
|
|
1266
|
+
return humanArrayLines(data);
|
|
1175
1267
|
if (!isRecord(data)) {
|
|
1176
1268
|
return data === undefined ? [] : [String(data)];
|
|
1177
1269
|
}
|
|
@@ -34,9 +34,10 @@ export declare function startModules(catalog: ModuleCatalog, modules: readonly R
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function stopModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
|
|
36
36
|
/**
|
|
37
|
-
* Restarts a module set
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* Restarts a module set as a platform-level stop → start sequence. Stop runs in
|
|
38
|
+
* reverse dependency order; only after every executed stop succeeds does start
|
|
39
|
+
* run in forward dependency order with the same dependency blocking rules as a
|
|
40
|
+
* normal start. Module-native `restart` primitives are not used here.
|
|
40
41
|
*/
|
|
41
42
|
export declare function restartModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
|
|
42
43
|
/**
|
|
@@ -172,12 +172,17 @@ export async function stopModules(catalog, modules) {
|
|
|
172
172
|
return runInOrder(catalog, modules, order, "stop");
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
* Restarts a module set
|
|
176
|
-
*
|
|
177
|
-
*
|
|
175
|
+
* Restarts a module set as a platform-level stop → start sequence. Stop runs in
|
|
176
|
+
* reverse dependency order; only after every executed stop succeeds does start
|
|
177
|
+
* run in forward dependency order with the same dependency blocking rules as a
|
|
178
|
+
* normal start. Module-native `restart` primitives are not used here.
|
|
178
179
|
*/
|
|
179
180
|
export async function restartModules(catalog, modules) {
|
|
180
|
-
|
|
181
|
+
const stopped = await stopModules(catalog, modules);
|
|
182
|
+
const stopBlocked = stopped.some((item) => item.result !== undefined && item.result.status !== "SUCCEEDED");
|
|
183
|
+
if (stopBlocked)
|
|
184
|
+
return stopped;
|
|
185
|
+
return startModules(catalog, modules);
|
|
181
186
|
}
|
|
182
187
|
/**
|
|
183
188
|
* Queries current reality by dispatching the `status` primitive to every
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomflow/proflow-platform-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"@tomflow/proflow-module-contract": "^0.1.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@tomflow/proflow-
|
|
28
|
-
"@tomflow/proflow-
|
|
27
|
+
"@tomflow/proflow-deployment-conformance": "^0.1.2",
|
|
28
|
+
"@tomflow/proflow-module-template": "^0.1.2"
|
|
29
29
|
},
|
|
30
30
|
"description": "Deterministic platform-level deployment discovery, planning, lifecycle and verification CLI.",
|
|
31
31
|
"keywords": [
|
package/proflow.module.json
CHANGED