@kb-labs/infra-worker-core 0.5.0 → 2.6.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.
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +142 -0
- package/dist/cli/index.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as prepareInfraCommand } from './commands/prepare-infra.js';
|
|
2
|
+
export { default as captureSnapshotCommand } from './commands/capture-snapshot.js';
|
|
3
|
+
export { default as restoreSnapshotCommand } from './commands/restore-snapshot.js';
|
|
4
|
+
import '@kb-labs/shared-command-kit';
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { defineCommand } from '@kb-labs/sdk';
|
|
2
|
+
|
|
3
|
+
// src/cli/commands/prepare-infra.ts
|
|
4
|
+
function toBoolean(value) {
|
|
5
|
+
if (typeof value === "boolean") {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value === "string") {
|
|
9
|
+
const normalized = value.trim().toLowerCase();
|
|
10
|
+
if (normalized === "true") {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (normalized === "false") {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
function toNumber(value) {
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
24
|
+
const parsed = Number(value);
|
|
25
|
+
if (Number.isFinite(parsed)) {
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
var prepare_infra_default = defineCommand({
|
|
32
|
+
id: "infra-worker:prepare",
|
|
33
|
+
description: "Materialize workspace, optionally provision environment, optionally capture snapshot.",
|
|
34
|
+
handler: {
|
|
35
|
+
async execute(ctx, input) {
|
|
36
|
+
const flags = input.flags;
|
|
37
|
+
const createEnvironment = toBoolean(flags.createEnvironment) ?? false;
|
|
38
|
+
const captureSnapshot = toBoolean(flags.captureSnapshot) ?? false;
|
|
39
|
+
const ttlMs = toNumber(flags.ttlMs);
|
|
40
|
+
const workspace = await ctx.api.workspace.materialize({
|
|
41
|
+
sourceRef: flags.sourceRef,
|
|
42
|
+
basePath: flags.basePath
|
|
43
|
+
});
|
|
44
|
+
let environmentId;
|
|
45
|
+
if (createEnvironment) {
|
|
46
|
+
const environment = await ctx.api.environment.create({
|
|
47
|
+
templateId: flags.templateId,
|
|
48
|
+
ttlMs,
|
|
49
|
+
workspacePath: workspace.rootPath ?? flags.basePath
|
|
50
|
+
});
|
|
51
|
+
environmentId = environment.environmentId;
|
|
52
|
+
await ctx.api.workspace.attach({
|
|
53
|
+
workspaceId: workspace.workspaceId,
|
|
54
|
+
environmentId
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
let snapshotId;
|
|
58
|
+
if (captureSnapshot) {
|
|
59
|
+
const snapshot = await ctx.api.snapshot.capture({
|
|
60
|
+
workspaceId: workspace.workspaceId,
|
|
61
|
+
environmentId,
|
|
62
|
+
namespace: flags.namespace
|
|
63
|
+
});
|
|
64
|
+
snapshotId = snapshot.snapshotId;
|
|
65
|
+
}
|
|
66
|
+
const result = {
|
|
67
|
+
workspaceId: workspace.workspaceId,
|
|
68
|
+
environmentId,
|
|
69
|
+
snapshotId
|
|
70
|
+
};
|
|
71
|
+
ctx.ui.success("Infrastructure prepared", {
|
|
72
|
+
sections: [
|
|
73
|
+
{
|
|
74
|
+
header: "Identifiers",
|
|
75
|
+
items: [
|
|
76
|
+
`workspaceId: ${result.workspaceId}`,
|
|
77
|
+
`environmentId: ${result.environmentId ?? "-"}`,
|
|
78
|
+
`snapshotId: ${result.snapshotId ?? "-"}`
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
exitCode: 0,
|
|
85
|
+
result
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var capture_snapshot_default = defineCommand({
|
|
91
|
+
id: "infra-worker:capture-snapshot",
|
|
92
|
+
description: "Capture snapshot from workspace/environment.",
|
|
93
|
+
handler: {
|
|
94
|
+
async execute(ctx, input) {
|
|
95
|
+
const flags = input.flags;
|
|
96
|
+
const snapshot = await ctx.api.snapshot.capture({
|
|
97
|
+
workspaceId: flags.workspaceId,
|
|
98
|
+
environmentId: flags.environmentId,
|
|
99
|
+
namespace: flags.namespace,
|
|
100
|
+
sourcePath: flags.sourcePath
|
|
101
|
+
});
|
|
102
|
+
const result = { snapshotId: snapshot.snapshotId };
|
|
103
|
+
ctx.ui.success(`Snapshot captured: ${result.snapshotId}`);
|
|
104
|
+
return {
|
|
105
|
+
exitCode: 0,
|
|
106
|
+
result
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
var restore_snapshot_default = defineCommand({
|
|
112
|
+
id: "infra-worker:restore-snapshot",
|
|
113
|
+
description: "Restore snapshot to workspace/environment.",
|
|
114
|
+
handler: {
|
|
115
|
+
async execute(ctx, input) {
|
|
116
|
+
const flags = input.flags;
|
|
117
|
+
if (!flags.snapshotId) {
|
|
118
|
+
throw new Error("Missing required flag: snapshotId");
|
|
119
|
+
}
|
|
120
|
+
const restored = await ctx.api.snapshot.restore({
|
|
121
|
+
snapshotId: flags.snapshotId,
|
|
122
|
+
workspaceId: flags.workspaceId,
|
|
123
|
+
environmentId: flags.environmentId,
|
|
124
|
+
targetPath: flags.targetPath,
|
|
125
|
+
overwrite: flags.overwrite
|
|
126
|
+
});
|
|
127
|
+
const result = {
|
|
128
|
+
snapshotId: restored.snapshotId,
|
|
129
|
+
restoredAt: restored.restoredAt
|
|
130
|
+
};
|
|
131
|
+
ctx.ui.success(`Snapshot restored: ${result.snapshotId}`);
|
|
132
|
+
return {
|
|
133
|
+
exitCode: 0,
|
|
134
|
+
result
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
export { capture_snapshot_default as captureSnapshotCommand, prepare_infra_default as prepareInfraCommand, restore_snapshot_default as restoreSnapshotCommand };
|
|
141
|
+
//# sourceMappingURL=index.js.map
|
|
142
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/prepare-infra.ts","../../src/cli/commands/capture-snapshot.ts","../../src/cli/commands/restore-snapshot.ts"],"names":["defineCommand"],"mappings":"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","file":"index.js","sourcesContent":["import { defineCommand, type CommandResult, type PluginContextV3 } from '@kb-labs/sdk';\n\ninterface PrepareInfraFlags {\n sourceRef?: string;\n basePath?: string;\n createEnvironment?: boolean;\n templateId?: string;\n ttlMs?: number;\n captureSnapshot?: boolean;\n namespace?: string;\n}\n\ninterface PrepareInfraInput {\n argv: string[];\n flags: PrepareInfraFlags;\n}\n\ninterface PrepareInfraResult {\n workspaceId: string;\n environmentId?: string;\n snapshotId?: string;\n}\n\nfunction toBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') {\n return value;\n }\n if (typeof value === 'string') {\n const normalized = value.trim().toLowerCase();\n if (normalized === 'true') {return true;}\n if (normalized === 'false') {return false;}\n }\n return undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {return parsed;}\n }\n return undefined;\n}\n\nexport default defineCommand<unknown, PrepareInfraInput, PrepareInfraResult>({\n id: 'infra-worker:prepare',\n description: 'Materialize workspace, optionally provision environment, optionally capture snapshot.',\n handler: {\n async execute(\n ctx: PluginContextV3<unknown>,\n input: PrepareInfraInput\n ): Promise<CommandResult<PrepareInfraResult>> {\n const flags = input.flags;\n const createEnvironment = toBoolean(flags.createEnvironment) ?? false;\n const captureSnapshot = toBoolean(flags.captureSnapshot) ?? false;\n const ttlMs = toNumber(flags.ttlMs);\n\n const workspace = await ctx.api.workspace.materialize({\n sourceRef: flags.sourceRef,\n basePath: flags.basePath,\n });\n\n let environmentId: string | undefined;\n if (createEnvironment) {\n const environment = await ctx.api.environment.create({\n templateId: flags.templateId,\n ttlMs,\n workspacePath: workspace.rootPath ?? flags.basePath,\n });\n environmentId = environment.environmentId;\n await ctx.api.workspace.attach({\n workspaceId: workspace.workspaceId,\n environmentId,\n });\n }\n\n let snapshotId: string | undefined;\n if (captureSnapshot) {\n const snapshot = await ctx.api.snapshot.capture({\n workspaceId: workspace.workspaceId,\n environmentId,\n namespace: flags.namespace,\n });\n snapshotId = snapshot.snapshotId;\n }\n\n const result: PrepareInfraResult = {\n workspaceId: workspace.workspaceId,\n environmentId,\n snapshotId,\n };\n\n ctx.ui.success('Infrastructure prepared', {\n sections: [\n {\n header: 'Identifiers',\n items: [\n `workspaceId: ${result.workspaceId}`,\n `environmentId: ${result.environmentId ?? '-'}`,\n `snapshotId: ${result.snapshotId ?? '-'}`,\n ],\n },\n ],\n });\n\n return {\n exitCode: 0,\n result,\n };\n },\n },\n});\n","import { defineCommand, type CommandResult, type PluginContextV3 } from '@kb-labs/sdk';\n\ninterface CaptureSnapshotFlags {\n workspaceId?: string;\n environmentId?: string;\n namespace?: string;\n sourcePath?: string;\n}\n\ninterface CaptureSnapshotInput {\n argv: string[];\n flags: CaptureSnapshotFlags;\n}\n\ninterface CaptureSnapshotResult {\n snapshotId: string;\n}\n\nexport default defineCommand<unknown, CaptureSnapshotInput, CaptureSnapshotResult>({\n id: 'infra-worker:capture-snapshot',\n description: 'Capture snapshot from workspace/environment.',\n handler: {\n async execute(\n ctx: PluginContextV3<unknown>,\n input: CaptureSnapshotInput\n ): Promise<CommandResult<CaptureSnapshotResult>> {\n const flags = input.flags;\n const snapshot = await ctx.api.snapshot.capture({\n workspaceId: flags.workspaceId,\n environmentId: flags.environmentId,\n namespace: flags.namespace,\n sourcePath: flags.sourcePath,\n });\n\n const result: CaptureSnapshotResult = { snapshotId: snapshot.snapshotId };\n ctx.ui.success(`Snapshot captured: ${result.snapshotId}`);\n\n return {\n exitCode: 0,\n result,\n };\n },\n },\n});\n","import { defineCommand, type CommandResult, type PluginContextV3 } from '@kb-labs/sdk';\n\ninterface RestoreSnapshotFlags {\n snapshotId?: string;\n workspaceId?: string;\n environmentId?: string;\n targetPath?: string;\n overwrite?: boolean;\n}\n\ninterface RestoreSnapshotInput {\n argv: string[];\n flags: RestoreSnapshotFlags;\n}\n\ninterface RestoreSnapshotResult {\n snapshotId: string;\n restoredAt: string;\n}\n\nexport default defineCommand<unknown, RestoreSnapshotInput, RestoreSnapshotResult>({\n id: 'infra-worker:restore-snapshot',\n description: 'Restore snapshot to workspace/environment.',\n handler: {\n async execute(\n ctx: PluginContextV3<unknown>,\n input: RestoreSnapshotInput\n ): Promise<CommandResult<RestoreSnapshotResult>> {\n const flags = input.flags;\n if (!flags.snapshotId) {\n throw new Error('Missing required flag: snapshotId');\n }\n\n const restored = await ctx.api.snapshot.restore({\n snapshotId: flags.snapshotId,\n workspaceId: flags.workspaceId,\n environmentId: flags.environmentId,\n targetPath: flags.targetPath,\n overwrite: flags.overwrite,\n });\n\n const result: RestoreSnapshotResult = {\n snapshotId: restored.snapshotId,\n restoredAt: restored.restoredAt,\n };\n ctx.ui.success(`Snapshot restored: ${result.snapshotId}`);\n\n return {\n exitCode: 0,\n result,\n };\n },\n },\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb-labs/infra-worker-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Infra worker plugin core for workspace/environment/snapshot lifecycle operations.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"test:watch": "vitest"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@kb-labs/plugin-contracts": "^
|
|
42
|
-
"@kb-labs/infra-worker-contracts": "^
|
|
43
|
-
"@kb-labs/sdk": "
|
|
41
|
+
"@kb-labs/plugin-contracts": "^2.6.0",
|
|
42
|
+
"@kb-labs/infra-worker-contracts": "^2.6.0",
|
|
43
|
+
"@kb-labs/sdk": "workspace:*",
|
|
44
44
|
"react": "^18.3.1",
|
|
45
45
|
"zod": "^3.23.8"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@kb-labs/devkit": "
|
|
49
|
-
"@kb-labs/plugin-runtime": "
|
|
48
|
+
"@kb-labs/devkit": "workspace:*",
|
|
49
|
+
"@kb-labs/plugin-runtime": "workspace:*",
|
|
50
50
|
"@types/node": "^24.3.3",
|
|
51
51
|
"@types/react": "^18.3.8",
|
|
52
52
|
"@types/react-dom": "^18.3.0",
|