@kb-labs/release-manager-cli 0.5.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/README.md +211 -0
- package/dist/cli/commands/changelog.d.ts +17 -0
- package/dist/cli/commands/changelog.js +156 -0
- package/dist/cli/commands/changelog.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +12 -0
- package/dist/cli/commands/plan.js +117 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/publish.d.ts +15 -0
- package/dist/cli/commands/publish.js +486 -0
- package/dist/cli/commands/publish.js.map +1 -0
- package/dist/cli/commands/report.d.ts +9 -0
- package/dist/cli/commands/report.js +77 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +9 -0
- package/dist/cli/commands/rollback.js +42 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +16 -0
- package/dist/cli/commands/run.js +539 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +14 -0
- package/dist/cli/commands/verify.js +106 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/contracts/release.schema.d.ts +503 -0
- package/dist/contracts/release.schema.js +45 -0
- package/dist/contracts/release.schema.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +689 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +292 -0
- package/dist/manifest.js +604 -0
- package/dist/manifest.js.map +1 -0
- package/dist/rest/handlers/build-handler.d.ts +20 -0
- package/dist/rest/handlers/build-handler.js +68 -0
- package/dist/rest/handlers/build-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-generate-handler.d.ts +20 -0
- package/dist/rest/handlers/changelog-generate-handler.js +169 -0
- package/dist/rest/handlers/changelog-generate-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-handler.d.ts +16 -0
- package/dist/rest/handlers/changelog-handler.js +50 -0
- package/dist/rest/handlers/changelog-handler.js.map +1 -0
- package/dist/rest/handlers/changelog-save-handler.d.ts +13 -0
- package/dist/rest/handlers/changelog-save-handler.js +42 -0
- package/dist/rest/handlers/changelog-save-handler.js.map +1 -0
- package/dist/rest/handlers/checklist-handler.d.ts +39 -0
- package/dist/rest/handlers/checklist-handler.js +155 -0
- package/dist/rest/handlers/checklist-handler.js.map +1 -0
- package/dist/rest/handlers/generate-handler.d.ts +35 -0
- package/dist/rest/handlers/generate-handler.js +206 -0
- package/dist/rest/handlers/generate-handler.js.map +1 -0
- package/dist/rest/handlers/get-checks-handler.d.ts +15 -0
- package/dist/rest/handlers/get-checks-handler.js +22 -0
- package/dist/rest/handlers/get-checks-handler.js.map +1 -0
- package/dist/rest/handlers/git-timeline-handler.d.ts +26 -0
- package/dist/rest/handlers/git-timeline-handler.js +209 -0
- package/dist/rest/handlers/git-timeline-handler.js.map +1 -0
- package/dist/rest/handlers/history-changelog-handler.d.ts +14 -0
- package/dist/rest/handlers/history-changelog-handler.js +34 -0
- package/dist/rest/handlers/history-changelog-handler.js.map +1 -0
- package/dist/rest/handlers/history-handler.d.ts +20 -0
- package/dist/rest/handlers/history-handler.js +75 -0
- package/dist/rest/handlers/history-handler.js.map +1 -0
- package/dist/rest/handlers/history-plan-handler.d.ts +30 -0
- package/dist/rest/handlers/history-plan-handler.js +34 -0
- package/dist/rest/handlers/history-plan-handler.js.map +1 -0
- package/dist/rest/handlers/history-report-handler.d.ts +64 -0
- package/dist/rest/handlers/history-report-handler.js +34 -0
- package/dist/rest/handlers/history-report-handler.js.map +1 -0
- package/dist/rest/handlers/plan-handler.d.ts +29 -0
- package/dist/rest/handlers/plan-handler.js +75 -0
- package/dist/rest/handlers/plan-handler.js.map +1 -0
- package/dist/rest/handlers/preview-handler.d.ts +26 -0
- package/dist/rest/handlers/preview-handler.js +127 -0
- package/dist/rest/handlers/preview-handler.js.map +1 -0
- package/dist/rest/handlers/report-handler.d.ts +65 -0
- package/dist/rest/handlers/report-handler.js +48 -0
- package/dist/rest/handlers/report-handler.js.map +1 -0
- package/dist/rest/handlers/reset-handler.d.ts +12 -0
- package/dist/rest/handlers/reset-handler.js +38 -0
- package/dist/rest/handlers/reset-handler.js.map +1 -0
- package/dist/rest/handlers/run-checks-handler.d.ts +20 -0
- package/dist/rest/handlers/run-checks-handler.js +58 -0
- package/dist/rest/handlers/run-checks-handler.js.map +1 -0
- package/dist/rest/handlers/run-handler.d.ts +68 -0
- package/dist/rest/handlers/run-handler.js +274 -0
- package/dist/rest/handlers/run-handler.js.map +1 -0
- package/dist/rest/handlers/scopes-handler.d.ts +20 -0
- package/dist/rest/handlers/scopes-handler.js +63 -0
- package/dist/rest/handlers/scopes-handler.js.map +1 -0
- package/dist/rest/handlers/status-handler.d.ts +24 -0
- package/dist/rest/handlers/status-handler.js +120 -0
- package/dist/rest/handlers/status-handler.js.map +1 -0
- package/dist/setup/handler.d.ts +19 -0
- package/dist/setup/handler.js +103 -0
- package/dist/setup/handler.js.map +1 -0
- package/dist/widgets/220.js +446 -0
- package/dist/widgets/220.js.map +1 -0
- package/dist/widgets/331.js +2 -0
- package/dist/widgets/331.js.map +1 -0
- package/dist/widgets/403.js +2 -0
- package/dist/widgets/403.js.map +1 -0
- package/dist/widgets/406.js +35 -0
- package/dist/widgets/406.js.map +1 -0
- package/dist/widgets/455.js +2 -0
- package/dist/widgets/455.js.map +1 -0
- package/dist/widgets/482.js +2 -0
- package/dist/widgets/482.js.map +1 -0
- package/dist/widgets/485.js +2 -0
- package/dist/widgets/485.js.map +1 -0
- package/dist/widgets/527.js +2 -0
- package/dist/widgets/527.js.map +1 -0
- package/dist/widgets/628.js +2 -0
- package/dist/widgets/628.js.map +1 -0
- package/dist/widgets/694.js +2 -0
- package/dist/widgets/694.js.map +1 -0
- package/dist/widgets/712.js +2 -0
- package/dist/widgets/712.js.map +1 -0
- package/dist/widgets/866.js +2 -0
- package/dist/widgets/866.js.map +1 -0
- package/dist/widgets/915.js +39 -0
- package/dist/widgets/915.js.map +1 -0
- package/dist/widgets/957.js +10 -0
- package/dist/widgets/957.js.map +1 -0
- package/dist/widgets/983.js +2 -0
- package/dist/widgets/983.js.map +1 -0
- package/dist/widgets/@mf-types.d.ts +3 -0
- package/dist/widgets/@mf-types.zip +0 -0
- package/dist/widgets/__federation_expose_ReleasePage.js +2 -0
- package/dist/widgets/__federation_expose_ReleasePage.js.map +1 -0
- package/dist/widgets/mf-manifest.json +260 -0
- package/dist/widgets/mf-stats.json +302 -0
- package/dist/widgets/remoteEntry.js +7 -0
- package/dist/widgets/remoteEntry.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { defineHandler, findRepoRoot } from '@kb-labs/sdk';
|
|
2
|
+
import { RELEASE_CACHE_PREFIX } from '@kb-labs/release-manager-contracts';
|
|
3
|
+
import 'path';
|
|
4
|
+
import 'fs/promises';
|
|
5
|
+
import 'globby';
|
|
6
|
+
|
|
7
|
+
// src/rest/handlers/plan-handler.ts
|
|
8
|
+
function scopeToDir(scope) {
|
|
9
|
+
return scope.replace(/^@/, "").replace(/\//g, "-").replace(/:/g, "-").replace(/\*/g, "");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/rest/handlers/plan-handler.ts
|
|
13
|
+
var CACHE_TTL_MS = 15e3;
|
|
14
|
+
var plan_handler_default = defineHandler({
|
|
15
|
+
async execute(ctx, input) {
|
|
16
|
+
const scope = input.query?.scope || "root";
|
|
17
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
18
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
19
|
+
ctx.platform?.logger?.info?.("Plan handler called", { scope, query: input.query });
|
|
20
|
+
const scopeDirName = scopeToDir(scope);
|
|
21
|
+
const planPath = `${repoRoot}/.kb/release/plans/${scopeDirName}/current/plan.json`;
|
|
22
|
+
const cacheKey = `${RELEASE_CACHE_PREFIX}plan:${scope}`;
|
|
23
|
+
const cached = await ctx.platform?.cache?.get(cacheKey);
|
|
24
|
+
if (cached !== void 0 && cached !== null) {
|
|
25
|
+
ctx.platform?.logger?.info?.("Returning cached plan response", {
|
|
26
|
+
scope,
|
|
27
|
+
hasPlan: cached.hasPlan,
|
|
28
|
+
fromCache: true
|
|
29
|
+
});
|
|
30
|
+
return cached;
|
|
31
|
+
}
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = await ctx.runtime.fs.readFile(planPath, "utf-8");
|
|
35
|
+
} catch (error) {
|
|
36
|
+
ctx.platform?.logger?.info?.("No plan found for scope", {
|
|
37
|
+
scope,
|
|
38
|
+
planPath,
|
|
39
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
40
|
+
});
|
|
41
|
+
const response = {
|
|
42
|
+
hasPlan: false,
|
|
43
|
+
scope
|
|
44
|
+
};
|
|
45
|
+
await ctx.platform?.cache?.set(cacheKey, response, 5e3);
|
|
46
|
+
return response;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const plan = JSON.parse(raw);
|
|
50
|
+
const response = {
|
|
51
|
+
hasPlan: true,
|
|
52
|
+
plan,
|
|
53
|
+
scope
|
|
54
|
+
};
|
|
55
|
+
ctx.platform?.logger?.info?.("Plan loaded successfully", { scope, hasPlan: true });
|
|
56
|
+
await ctx.platform?.cache?.set(cacheKey, response, CACHE_TTL_MS);
|
|
57
|
+
return response;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
ctx.platform?.logger?.error?.(
|
|
60
|
+
"Failed to parse release plan",
|
|
61
|
+
error instanceof Error ? error : void 0,
|
|
62
|
+
{ scope }
|
|
63
|
+
);
|
|
64
|
+
const response = {
|
|
65
|
+
hasPlan: false,
|
|
66
|
+
scope
|
|
67
|
+
};
|
|
68
|
+
return response;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export { plan_handler_default as default };
|
|
74
|
+
//# sourceMappingURL=plan-handler.js.map
|
|
75
|
+
//# sourceMappingURL=plan-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/shared/utils.ts","../../../src/rest/handlers/plan-handler.ts"],"names":["findRepoRoot"],"mappings":"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","file":"plan-handler.js","sourcesContent":["import { join } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport globby from 'globby';\n\nexport { findRepoRoot } from '@kb-labs/sdk';\n\n/**\n * Converts scope to safe directory name\n */\nexport function scopeToDir(scope: string): string {\n return scope\n .replace(/^@/, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '-')\n .replace(/\\*/g, '');\n}\n\n/**\n * Converts safe directory name back to scope\n */\nexport function dirToScope(dirName: string): string {\n if (dirName === 'root') {\n return 'root';\n }\n\n const parts = dirName.split('-');\n if (parts.length >= 2) {\n return '@' + parts[0] + '-' + parts[1] + '/' + parts.slice(2).join('-');\n }\n\n return dirName;\n}\n\n/**\n * Resolve scope name to absolute filesystem path.\n * Scans all package.json in repoRoot to find the matching package by name.\n */\nexport async function resolveScopePath(repoRoot: string, scope: string): Promise<string> {\n if (scope === 'root') {\n return repoRoot;\n }\n\n if (scope.startsWith('@')) {\n const packageJsonPaths = await globby('**/package.json', {\n cwd: repoRoot,\n absolute: true,\n onlyFiles: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.*/**'],\n });\n\n for (const pkgJsonPath of packageJsonPaths) {\n try {\n const pkg = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n if (pkg.name === scope) {\n return join(pkgJsonPath, '..');\n }\n } catch { /* skip */ }\n }\n }\n\n // Direct path or fallback\n return join(repoRoot, scope);\n}\n","/**\n * Plan handler - Get current release plan for a scope\n *\n * Reads: .kb/release/plans/{scope}/current/plan.json\n * Cache: 15s TTL to avoid repeated file reads\n */\n\nimport { defineHandler, findRepoRoot, type RestInput } from '@kb-labs/sdk';\nimport type { PlanResponse, ReleasePlan, PlanInput } from '@kb-labs/release-manager-contracts';\nimport { RELEASE_CACHE_PREFIX } from '@kb-labs/release-manager-contracts';\nimport { scopeToDir } from '../../shared/utils';\n\nconst CACHE_TTL_MS = 15000; // 15 seconds\n\nexport default defineHandler({\n async execute(ctx, input: RestInput<PlanInput>): Promise<PlanResponse> {\n const scope = input.query?.scope || 'root';\n const cwd = ctx.cwd ?? process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n\n ctx.platform?.logger?.info?.('Plan handler called', { scope, query: input.query });\n\n const scopeDirName = scopeToDir(scope);\n const planPath = `${repoRoot}/.kb/release/plans/${scopeDirName}/current/plan.json`;\n const cacheKey = `${RELEASE_CACHE_PREFIX}plan:${scope}`;\n\n // Try cache first\n const cached = await ctx.platform?.cache?.get(cacheKey);\n if (cached !== undefined && cached !== null) {\n ctx.platform?.logger?.info?.('Returning cached plan response', {\n scope,\n hasPlan: (cached as PlanResponse).hasPlan,\n fromCache: true\n });\n return cached as PlanResponse;\n }\n\n // Cache miss - read from file\n let raw: string;\n try {\n raw = await ctx.runtime.fs.readFile(planPath, 'utf-8');\n } catch (error) {\n // No plan found for this scope\n ctx.platform?.logger?.info?.('No plan found for scope', {\n scope,\n planPath,\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n\n const response: PlanResponse = {\n hasPlan: false,\n scope,\n };\n // Cache negative result too (shorter TTL)\n await ctx.platform?.cache?.set(cacheKey, response, 5000); // 5s for \"not found\"\n return response;\n }\n\n try {\n const plan: ReleasePlan = JSON.parse(raw);\n const response: PlanResponse = {\n hasPlan: true,\n plan,\n scope,\n };\n\n ctx.platform?.logger?.info?.('Plan loaded successfully', { scope, hasPlan: true });\n\n // Cache successful result\n await ctx.platform?.cache?.set(cacheKey, response, CACHE_TTL_MS);\n return response;\n } catch (error) {\n ctx.platform?.logger?.error?.(\n 'Failed to parse release plan',\n error instanceof Error ? error : undefined,\n { scope }\n );\n\n const response: PlanResponse = {\n hasPlan: false,\n scope,\n };\n return response;\n }\n }\n});\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<{
|
|
5
|
+
scope: string;
|
|
6
|
+
}, unknown, unknown>, {
|
|
7
|
+
scope: string;
|
|
8
|
+
packages: {
|
|
9
|
+
name: string;
|
|
10
|
+
path: string;
|
|
11
|
+
version: string;
|
|
12
|
+
buildStatus: "ready" | "not_built" | "outdated" | "building";
|
|
13
|
+
files: {
|
|
14
|
+
path: string;
|
|
15
|
+
size: number;
|
|
16
|
+
}[];
|
|
17
|
+
totalSize: number;
|
|
18
|
+
fileCount: number;
|
|
19
|
+
expectedFiles?: string[] | undefined;
|
|
20
|
+
}[];
|
|
21
|
+
totalSize: number;
|
|
22
|
+
totalFiles: number;
|
|
23
|
+
allBuilt: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
26
|
+
export { _default as default };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { defineHandler, findRepoRoot } from '@kb-labs/sdk';
|
|
2
|
+
import { readFile, stat, access } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import 'globby';
|
|
5
|
+
import packlist from 'npm-packlist';
|
|
6
|
+
|
|
7
|
+
// src/rest/handlers/preview-handler.ts
|
|
8
|
+
function scopeToDir(scope) {
|
|
9
|
+
return scope.replace(/^@/, "").replace(/\//g, "-").replace(/:/g, "-").replace(/\*/g, "");
|
|
10
|
+
}
|
|
11
|
+
async function checkBuildStatus(packagePath) {
|
|
12
|
+
const distPath = join(packagePath, "dist");
|
|
13
|
+
try {
|
|
14
|
+
await access(distPath);
|
|
15
|
+
return "ready";
|
|
16
|
+
} catch {
|
|
17
|
+
return "not_built";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function getExpectedFiles(packagePath) {
|
|
21
|
+
try {
|
|
22
|
+
const pkgJsonPath = join(packagePath, "package.json");
|
|
23
|
+
const pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8"));
|
|
24
|
+
return pkgJson.files || [];
|
|
25
|
+
} catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
var preview_handler_default = defineHandler({
|
|
30
|
+
async execute(ctx, input) {
|
|
31
|
+
const scope = input.query?.scope || "root";
|
|
32
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
33
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
34
|
+
const scopeDir = scopeToDir(scope);
|
|
35
|
+
const planPath = join(repoRoot, ".kb/release/plans", scopeDir, "current", "plan.json");
|
|
36
|
+
let plan;
|
|
37
|
+
try {
|
|
38
|
+
const planRaw = await readFile(planPath, "utf-8");
|
|
39
|
+
plan = JSON.parse(planRaw);
|
|
40
|
+
} catch {
|
|
41
|
+
return {
|
|
42
|
+
scope,
|
|
43
|
+
packages: [],
|
|
44
|
+
totalSize: 0,
|
|
45
|
+
totalFiles: 0,
|
|
46
|
+
allBuilt: false
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const packages = [];
|
|
50
|
+
let totalSize = 0;
|
|
51
|
+
let totalFiles = 0;
|
|
52
|
+
let allBuilt = true;
|
|
53
|
+
for (const pkg of plan.packages) {
|
|
54
|
+
const packagePath = pkg.path.startsWith("/") ? pkg.path : join(repoRoot, pkg.path);
|
|
55
|
+
const buildStatus = await checkBuildStatus(packagePath);
|
|
56
|
+
if (buildStatus !== "ready") {
|
|
57
|
+
allBuilt = false;
|
|
58
|
+
}
|
|
59
|
+
const expectedFiles = await getExpectedFiles(packagePath);
|
|
60
|
+
try {
|
|
61
|
+
const pkgJsonPath = join(packagePath, "package.json");
|
|
62
|
+
const pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8"));
|
|
63
|
+
const tree = {
|
|
64
|
+
path: packagePath,
|
|
65
|
+
isProjectRoot: true,
|
|
66
|
+
package: {
|
|
67
|
+
...pkgJson,
|
|
68
|
+
bundleDependencies: pkgJson.bundleDependencies || []
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const files = await packlist(tree);
|
|
72
|
+
const filesWithSize = await Promise.all(
|
|
73
|
+
files.map(async (filePath) => {
|
|
74
|
+
try {
|
|
75
|
+
const fullPath = join(packagePath, filePath);
|
|
76
|
+
const stats = await stat(fullPath);
|
|
77
|
+
return {
|
|
78
|
+
path: filePath,
|
|
79
|
+
size: stats.size
|
|
80
|
+
};
|
|
81
|
+
} catch {
|
|
82
|
+
return {
|
|
83
|
+
path: filePath,
|
|
84
|
+
size: 0
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
const packageTotalSize = filesWithSize.reduce((sum, f) => sum + f.size, 0);
|
|
90
|
+
packages.push({
|
|
91
|
+
name: pkg.name,
|
|
92
|
+
version: pkg.nextVersion,
|
|
93
|
+
path: pkg.path,
|
|
94
|
+
buildStatus,
|
|
95
|
+
files: filesWithSize,
|
|
96
|
+
expectedFiles: expectedFiles.length > 0 ? expectedFiles : void 0,
|
|
97
|
+
totalSize: packageTotalSize,
|
|
98
|
+
fileCount: files.length
|
|
99
|
+
});
|
|
100
|
+
totalSize += packageTotalSize;
|
|
101
|
+
totalFiles += files.length;
|
|
102
|
+
} catch {
|
|
103
|
+
packages.push({
|
|
104
|
+
name: pkg.name,
|
|
105
|
+
version: pkg.nextVersion,
|
|
106
|
+
path: pkg.path,
|
|
107
|
+
buildStatus,
|
|
108
|
+
files: [],
|
|
109
|
+
expectedFiles: expectedFiles.length > 0 ? expectedFiles : void 0,
|
|
110
|
+
totalSize: 0,
|
|
111
|
+
fileCount: 0
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
scope,
|
|
117
|
+
packages,
|
|
118
|
+
totalSize,
|
|
119
|
+
totalFiles,
|
|
120
|
+
allBuilt
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export { preview_handler_default as default };
|
|
126
|
+
//# sourceMappingURL=preview-handler.js.map
|
|
127
|
+
//# sourceMappingURL=preview-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/shared/utils.ts","../../../src/rest/handlers/preview-handler.ts"],"names":["join","readFile","findRepoRoot"],"mappings":"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","file":"preview-handler.js","sourcesContent":["import { join } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport globby from 'globby';\n\nexport { findRepoRoot } from '@kb-labs/sdk';\n\n/**\n * Converts scope to safe directory name\n */\nexport function scopeToDir(scope: string): string {\n return scope\n .replace(/^@/, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '-')\n .replace(/\\*/g, '');\n}\n\n/**\n * Converts safe directory name back to scope\n */\nexport function dirToScope(dirName: string): string {\n if (dirName === 'root') {\n return 'root';\n }\n\n const parts = dirName.split('-');\n if (parts.length >= 2) {\n return '@' + parts[0] + '-' + parts[1] + '/' + parts.slice(2).join('-');\n }\n\n return dirName;\n}\n\n/**\n * Resolve scope name to absolute filesystem path.\n * Scans all package.json in repoRoot to find the matching package by name.\n */\nexport async function resolveScopePath(repoRoot: string, scope: string): Promise<string> {\n if (scope === 'root') {\n return repoRoot;\n }\n\n if (scope.startsWith('@')) {\n const packageJsonPaths = await globby('**/package.json', {\n cwd: repoRoot,\n absolute: true,\n onlyFiles: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.*/**'],\n });\n\n for (const pkgJsonPath of packageJsonPaths) {\n try {\n const pkg = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n if (pkg.name === scope) {\n return join(pkgJsonPath, '..');\n }\n } catch { /* skip */ }\n }\n }\n\n // Direct path or fallback\n return join(repoRoot, scope);\n}\n","/**\n * Preview handler - Get list of files that will be published for each package\n *\n * Uses npm-packlist to determine what files will be included in the tarball\n * Also checks build status (dist/ folder existence)\n */\n\nimport { defineHandler, findRepoRoot, type RestInput } from '@kb-labs/sdk';\nimport type {\n PreviewInput,\n PreviewResponse,\n PackagePreview,\n PackageFile,\n ReleasePlan,\n BuildStatus,\n} from '@kb-labs/release-manager-contracts';\nimport { readFile, stat, access } from 'node:fs/promises';\nimport { scopeToDir } from '../../shared/utils';\nimport { join } from 'node:path';\nimport packlist from 'npm-packlist';\n\n/**\n * Check if dist folder exists and determine build status\n */\nasync function checkBuildStatus(packagePath: string): Promise<BuildStatus> {\n const distPath = join(packagePath, 'dist');\n try {\n await access(distPath);\n // TODO: Could check if dist is older than src for 'outdated' status\n return 'ready';\n } catch {\n return 'not_built';\n }\n}\n\n/**\n * Read expected files from package.json \"files\" field\n */\nasync function getExpectedFiles(packagePath: string): Promise<string[]> {\n try {\n const pkgJsonPath = join(packagePath, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n return pkgJson.files || [];\n } catch {\n return [];\n }\n}\n\nexport default defineHandler({\n async execute(ctx, input: RestInput<PreviewInput>): Promise<PreviewResponse> {\n const scope = input.query?.scope || 'root';\n const cwd = ctx.cwd ?? process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n\n // Read plan to get packages\n const scopeDir = scopeToDir(scope);\n const planPath = join(repoRoot, '.kb/release/plans', scopeDir, 'current', 'plan.json');\n\n let plan: ReleasePlan;\n try {\n const planRaw = await readFile(planPath, 'utf-8');\n plan = JSON.parse(planRaw);\n } catch {\n return {\n scope,\n packages: [],\n totalSize: 0,\n totalFiles: 0,\n allBuilt: false,\n };\n }\n\n const packages: PackagePreview[] = [];\n let totalSize = 0;\n let totalFiles = 0;\n let allBuilt = true;\n\n for (const pkg of plan.packages) {\n // pkg.path can be absolute or relative\n const packagePath = pkg.path.startsWith('/') ? pkg.path : join(repoRoot, pkg.path);\n\n // Check build status\n const buildStatus = await checkBuildStatus(packagePath);\n if (buildStatus !== 'ready') {\n allBuilt = false;\n }\n\n // Get expected files from package.json\n const expectedFiles = await getExpectedFiles(packagePath);\n\n try {\n // Read package.json to create tree object for npm-packlist v10+\n const pkgJsonPath = join(packagePath, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n\n // npm-packlist v10+ requires a tree-like arborist node with:\n // - path: package path\n // - package: package.json content (must have bundleDependencies if not isProjectRoot)\n // - isProjectRoot: true to use bundleDependencies instead of all deps\n // - edgesOut: Map of dependency edges (not needed if bundleDependencies is empty)\n // npm-packlist v10+ reads tree.path and tree.package at runtime.\n // @types/npm-packlist expects an arborist Node, but a plain object works fine —\n // cast to avoid the type mismatch without installing the full @npmcli/arborist types.\n const tree = {\n path: packagePath,\n isProjectRoot: true,\n package: {\n ...pkgJson,\n bundleDependencies: pkgJson.bundleDependencies || [],\n },\n } as Parameters<typeof packlist>[0];\n const files = await packlist(tree);\n\n // Get file sizes\n const filesWithSize: PackageFile[] = await Promise.all(\n files.map(async (filePath: string): Promise<PackageFile> => {\n try {\n const fullPath = join(packagePath, filePath);\n const stats = await stat(fullPath);\n return {\n path: filePath,\n size: stats.size,\n };\n } catch {\n return {\n path: filePath,\n size: 0,\n };\n }\n })\n );\n\n const packageTotalSize = filesWithSize.reduce((sum: number, f: PackageFile) => sum + f.size, 0);\n\n packages.push({\n name: pkg.name,\n version: pkg.nextVersion,\n path: pkg.path,\n buildStatus,\n files: filesWithSize,\n expectedFiles: expectedFiles.length > 0 ? expectedFiles : undefined,\n totalSize: packageTotalSize,\n fileCount: files.length,\n });\n\n totalSize += packageTotalSize;\n totalFiles += files.length;\n } catch {\n // If we can't read the package, add it with empty files\n packages.push({\n name: pkg.name,\n version: pkg.nextVersion,\n path: pkg.path,\n buildStatus,\n files: [],\n expectedFiles: expectedFiles.length > 0 ? expectedFiles : undefined,\n totalSize: 0,\n fileCount: 0,\n });\n }\n }\n\n return {\n scope,\n packages,\n totalSize,\n totalFiles,\n allBuilt,\n };\n },\n});\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Report handler - Get latest release report
|
|
5
|
+
*
|
|
6
|
+
* Reads from .kb/release/history/index.json and returns most recent report
|
|
7
|
+
*/
|
|
8
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, unknown, {
|
|
9
|
+
hasReport: boolean;
|
|
10
|
+
report?: {
|
|
11
|
+
scope: string;
|
|
12
|
+
schemaVersion: "1.0";
|
|
13
|
+
ts: string;
|
|
14
|
+
context: {
|
|
15
|
+
repo: string;
|
|
16
|
+
cwd: string;
|
|
17
|
+
branch: string;
|
|
18
|
+
profile?: string | undefined;
|
|
19
|
+
dryRun?: boolean | undefined;
|
|
20
|
+
};
|
|
21
|
+
stage: "rollback" | "planning" | "checking" | "versioning" | "publishing" | "verifying";
|
|
22
|
+
result: {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
timingMs: number;
|
|
25
|
+
changelog?: string | undefined;
|
|
26
|
+
version?: string | undefined;
|
|
27
|
+
published?: string[] | undefined;
|
|
28
|
+
skipped?: string[] | undefined;
|
|
29
|
+
checks?: Record<string, {
|
|
30
|
+
id: string;
|
|
31
|
+
ok: boolean;
|
|
32
|
+
details?: unknown;
|
|
33
|
+
hint?: string | undefined;
|
|
34
|
+
timingMs?: number | undefined;
|
|
35
|
+
}> | undefined;
|
|
36
|
+
git?: {
|
|
37
|
+
committed: boolean;
|
|
38
|
+
tagged: string[];
|
|
39
|
+
pushed: boolean;
|
|
40
|
+
} | undefined;
|
|
41
|
+
errors?: string[] | undefined;
|
|
42
|
+
};
|
|
43
|
+
plan?: {
|
|
44
|
+
scope: string;
|
|
45
|
+
schemaVersion: "1.0";
|
|
46
|
+
packages: {
|
|
47
|
+
name: string;
|
|
48
|
+
path: string;
|
|
49
|
+
currentVersion: string;
|
|
50
|
+
nextVersion: string;
|
|
51
|
+
bump: "patch" | "minor" | "major" | "auto";
|
|
52
|
+
isPublished: boolean;
|
|
53
|
+
dependencies?: string[] | undefined;
|
|
54
|
+
reason?: string | undefined;
|
|
55
|
+
}[];
|
|
56
|
+
strategy: "semver";
|
|
57
|
+
registry: string;
|
|
58
|
+
rollbackEnabled: boolean;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
} | undefined;
|
|
61
|
+
} | undefined;
|
|
62
|
+
scope?: string | undefined;
|
|
63
|
+
}>;
|
|
64
|
+
|
|
65
|
+
export { _default as default };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { defineHandler, findRepoRoot } from '@kb-labs/sdk';
|
|
2
|
+
|
|
3
|
+
// src/rest/handlers/report-handler.ts
|
|
4
|
+
var report_handler_default = defineHandler({
|
|
5
|
+
async execute(ctx, _input) {
|
|
6
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
7
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
8
|
+
const indexPath = `${repoRoot}/.kb/release/history/index.json`;
|
|
9
|
+
let raw;
|
|
10
|
+
try {
|
|
11
|
+
raw = await ctx.runtime.fs.readFile(indexPath, "utf-8");
|
|
12
|
+
} catch (error) {
|
|
13
|
+
return {
|
|
14
|
+
hasReport: false
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const index = JSON.parse(raw);
|
|
19
|
+
if (!index.releases || index.releases.length === 0) {
|
|
20
|
+
return {
|
|
21
|
+
hasReport: false
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const latest = index.releases[0];
|
|
25
|
+
const reportPath = `${repoRoot}/.kb/release/history/${latest.id}/report.json`;
|
|
26
|
+
const reportRaw = await ctx.runtime.fs.readFile(reportPath, "utf-8");
|
|
27
|
+
const report = JSON.parse(reportRaw);
|
|
28
|
+
return {
|
|
29
|
+
hasReport: true,
|
|
30
|
+
report,
|
|
31
|
+
scope: report.scope
|
|
32
|
+
};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
ctx.platform?.logger?.error?.(
|
|
35
|
+
"Failed to read release report",
|
|
36
|
+
error instanceof Error ? error : void 0,
|
|
37
|
+
{}
|
|
38
|
+
);
|
|
39
|
+
return {
|
|
40
|
+
hasReport: false
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export { report_handler_default as default };
|
|
47
|
+
//# sourceMappingURL=report-handler.js.map
|
|
48
|
+
//# sourceMappingURL=report-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/rest/handlers/report-handler.ts"],"names":[],"mappings":";;;AASA,IAAO,yBAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,GAAA,EAAK,MAAA,EAA0C;AAC3D,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AACnC,IAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,GAAG,CAAA;AAGvC,IAAA,MAAM,SAAA,GAAY,GAAG,QAAQ,CAAA,+BAAA,CAAA;AAE7B,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,EAAA,CAAG,QAAA,CAAS,WAAW,OAAO,CAAA;AAAA,IACxD,SAAS,KAAA,EAAO;AAEd,MAAA,OAAO;AAAA,QACL,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAE5B,MAAA,IAAI,CAAC,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,QAAA,CAAS,WAAW,CAAA,EAAG;AAClD,QAAA,OAAO;AAAA,UACL,SAAA,EAAW;AAAA,SACb;AAAA,MACF;AAGA,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,CAAS,CAAC,CAAA;AAG/B,MAAA,MAAM,UAAA,GAAa,CAAA,EAAG,QAAQ,CAAA,qBAAA,EAAwB,OAAO,EAAE,CAAA,YAAA,CAAA;AAC/D,MAAA,MAAM,YAAY,MAAM,GAAA,CAAI,QAAQ,EAAA,CAAG,QAAA,CAAS,YAAY,OAAO,CAAA;AACnE,MAAA,MAAM,MAAA,GAAwB,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AAElD,MAAA,OAAO;AAAA,QACL,SAAA,EAAW,IAAA;AAAA,QACX,MAAA;AAAA,QACA,OAAO,MAAA,CAAO;AAAA,OAChB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,UAAU,MAAA,EAAQ,KAAA;AAAA,QACpB,+BAAA;AAAA,QACA,KAAA,YAAiB,QAAQ,KAAA,GAAQ,MAAA;AAAA,QACjC;AAAC,OACH;AAEA,MAAA,OAAO;AAAA,QACL,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAAA,EACF;AACF,CAAC","file":"report-handler.js","sourcesContent":["/**\n * Report handler - Get latest release report\n *\n * Reads from .kb/release/history/index.json and returns most recent report\n */\n\nimport { defineHandler, findRepoRoot } from '@kb-labs/sdk';\nimport type { ReportResponse, ReleaseReport } from '@kb-labs/release-manager-contracts';\n\nexport default defineHandler({\n async execute(ctx, _input: unknown): Promise<ReportResponse> {\n const cwd = ctx.cwd ?? process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n\n // Read history index to find latest report\n const indexPath = `${repoRoot}/.kb/release/history/index.json`;\n\n let raw: string;\n try {\n raw = await ctx.runtime.fs.readFile(indexPath, 'utf-8');\n } catch (error) {\n // No history yet\n return {\n hasReport: false,\n };\n }\n\n try {\n const index = JSON.parse(raw);\n\n if (!index.releases || index.releases.length === 0) {\n return {\n hasReport: false,\n };\n }\n\n // Get most recent release\n const latest = index.releases[0];\n\n // Read the full report\n const reportPath = `${repoRoot}/.kb/release/history/${latest.id}/report.json`;\n const reportRaw = await ctx.runtime.fs.readFile(reportPath, 'utf-8');\n const report: ReleaseReport = JSON.parse(reportRaw);\n\n return {\n hasReport: true,\n report,\n scope: report.scope,\n };\n } catch (error) {\n ctx.platform?.logger?.error?.(\n 'Failed to read release report',\n error instanceof Error ? error : undefined,\n {}\n );\n\n return {\n hasReport: false,\n };\n }\n }\n});\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<{
|
|
5
|
+
scope: string;
|
|
6
|
+
}, unknown, unknown>, {
|
|
7
|
+
message: string;
|
|
8
|
+
scope: string;
|
|
9
|
+
success: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
export { _default as default };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineHandler, findRepoRoot } from '@kb-labs/sdk';
|
|
2
|
+
import { rm } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import 'globby';
|
|
5
|
+
|
|
6
|
+
// src/rest/handlers/reset-handler.ts
|
|
7
|
+
function scopeToDir(scope) {
|
|
8
|
+
return scope.replace(/^@/, "").replace(/\//g, "-").replace(/:/g, "-").replace(/\*/g, "");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/rest/handlers/reset-handler.ts
|
|
12
|
+
var reset_handler_default = defineHandler({
|
|
13
|
+
async execute(ctx, input) {
|
|
14
|
+
const scope = input.query?.scope || "root";
|
|
15
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
16
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
17
|
+
const scopeDirName = scopeToDir(scope);
|
|
18
|
+
const scopeDir = join(repoRoot, ".kb/release/plans", scopeDirName, "current");
|
|
19
|
+
try {
|
|
20
|
+
await rm(scopeDir, { recursive: true, force: true });
|
|
21
|
+
return {
|
|
22
|
+
success: true,
|
|
23
|
+
scope,
|
|
24
|
+
message: `Release plan for scope "${scope}" has been reset`
|
|
25
|
+
};
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
scope,
|
|
30
|
+
message: `Failed to reset plan: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export { reset_handler_default as default };
|
|
37
|
+
//# sourceMappingURL=reset-handler.js.map
|
|
38
|
+
//# sourceMappingURL=reset-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/shared/utils.ts","../../../src/rest/handlers/reset-handler.ts"],"names":["findRepoRoot","join"],"mappings":";;;;;;AASO,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,OAAO,KAAA,CACJ,OAAA,CAAQ,IAAA,EAAM,EAAE,EAChB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAClB,QAAQ,IAAA,EAAM,GAAG,CAAA,CACjB,OAAA,CAAQ,OAAO,EAAE,CAAA;AACtB;;;ACHA,IAAO,wBAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAyE;AAC1F,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,EAAO,KAAA,IAAS,MAAA;AACpC,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AACnC,IAAA,MAAM,QAAA,GAAW,MAAMA,YAAAA,CAAa,GAAG,CAAA;AAEvC,IAAA,MAAM,YAAA,GAAe,WAAW,KAAK,CAAA;AACrC,IAAA,MAAM,QAAA,GAAWC,IAAAA,CAAK,QAAA,EAAU,mBAAA,EAAqB,cAAc,SAAS,CAAA;AAE5E,IAAA,IAAI;AAEF,MAAA,MAAM,GAAG,QAAA,EAAU,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAEnD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,KAAA;AAAA,QACA,OAAA,EAAS,2BAA2B,KAAK,CAAA,gBAAA;AAAA,OAC3C;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,KAAA;AAAA,QACA,SAAS,CAAA,sBAAA,EAAyB,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,eAAe,CAAA;AAAA,OAC5F;AAAA,IACF;AAAA,EACF;AACF,CAAC","file":"reset-handler.js","sourcesContent":["import { join } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport globby from 'globby';\n\nexport { findRepoRoot } from '@kb-labs/sdk';\n\n/**\n * Converts scope to safe directory name\n */\nexport function scopeToDir(scope: string): string {\n return scope\n .replace(/^@/, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '-')\n .replace(/\\*/g, '');\n}\n\n/**\n * Converts safe directory name back to scope\n */\nexport function dirToScope(dirName: string): string {\n if (dirName === 'root') {\n return 'root';\n }\n\n const parts = dirName.split('-');\n if (parts.length >= 2) {\n return '@' + parts[0] + '-' + parts[1] + '/' + parts.slice(2).join('-');\n }\n\n return dirName;\n}\n\n/**\n * Resolve scope name to absolute filesystem path.\n * Scans all package.json in repoRoot to find the matching package by name.\n */\nexport async function resolveScopePath(repoRoot: string, scope: string): Promise<string> {\n if (scope === 'root') {\n return repoRoot;\n }\n\n if (scope.startsWith('@')) {\n const packageJsonPaths = await globby('**/package.json', {\n cwd: repoRoot,\n absolute: true,\n onlyFiles: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.*/**'],\n });\n\n for (const pkgJsonPath of packageJsonPaths) {\n try {\n const pkg = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n if (pkg.name === scope) {\n return join(pkgJsonPath, '..');\n }\n } catch { /* skip */ }\n }\n }\n\n // Direct path or fallback\n return join(repoRoot, scope);\n}\n","/**\n * Reset release plan handler - Delete current release plan and changelog\n *\n * Deletes: .kb/release/plans/{scope}/current/\n */\n\nimport { defineHandler, findRepoRoot, type RestInput } from '@kb-labs/sdk';\nimport type { ResetPlanRequest, ResetPlanResponse } from '@kb-labs/release-manager-contracts';\nimport { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { scopeToDir } from '../../shared/utils';\n\nexport default defineHandler({\n async execute(ctx, input: RestInput<ResetPlanRequest, unknown>): Promise<ResetPlanResponse> {\n const scope = input.query?.scope || 'root';\n const cwd = ctx.cwd ?? process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n\n const scopeDirName = scopeToDir(scope);\n const scopeDir = join(repoRoot, '.kb/release/plans', scopeDirName, 'current');\n\n try {\n // Remove entire current directory for this scope\n await rm(scopeDir, { recursive: true, force: true });\n\n return {\n success: true,\n scope,\n message: `Release plan for scope \"${scope}\" has been reset`,\n };\n } catch (error) {\n return {\n success: false,\n scope,\n message: `Failed to reset plan: ${error instanceof Error ? error.message : 'Unknown error'}`,\n };\n }\n }\n});\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<unknown, {
|
|
5
|
+
scope: string;
|
|
6
|
+
}, unknown>, {
|
|
7
|
+
scope: string;
|
|
8
|
+
success: boolean;
|
|
9
|
+
checks: {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
success: boolean;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
error?: string | undefined;
|
|
15
|
+
optional?: boolean | undefined;
|
|
16
|
+
}[];
|
|
17
|
+
totalDurationMs: number;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
export { _default as default };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { defineHandler, findRepoRoot, useConfig } from '@kb-labs/sdk';
|
|
2
|
+
import { resolveScopePath, runReleaseChecks } from '@kb-labs/release-manager-core';
|
|
3
|
+
import { readFile } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import 'globby';
|
|
6
|
+
|
|
7
|
+
// src/rest/handlers/run-checks-handler.ts
|
|
8
|
+
function scopeToDir(scope) {
|
|
9
|
+
return scope.replace(/^@/, "").replace(/\//g, "-").replace(/:/g, "-").replace(/\*/g, "");
|
|
10
|
+
}
|
|
11
|
+
var run_checks_handler_default = defineHandler({
|
|
12
|
+
async execute(ctx, input) {
|
|
13
|
+
const scope = input.body?.scope ?? "root";
|
|
14
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
15
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
16
|
+
const scopeCwd = await resolveScopePath(repoRoot, scope);
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
const config = await useConfig();
|
|
19
|
+
const checks = config?.scopes?.[scope]?.checks ?? config?.checks ?? [];
|
|
20
|
+
if (checks.length === 0) {
|
|
21
|
+
return { scope, success: true, checks: [], totalDurationMs: Date.now() - startTime };
|
|
22
|
+
}
|
|
23
|
+
const scopeDir = scopeToDir(scope);
|
|
24
|
+
const planPath = join(repoRoot, ".kb/release/plans", scopeDir, "current", "plan.json");
|
|
25
|
+
let packagePaths = [];
|
|
26
|
+
try {
|
|
27
|
+
const plan = JSON.parse(await readFile(planPath, "utf-8"));
|
|
28
|
+
packagePaths = plan.packages.map((pkg) => pkg.path.startsWith("/") ? pkg.path : join(repoRoot, pkg.path));
|
|
29
|
+
} catch {
|
|
30
|
+
packagePaths = [scopeCwd];
|
|
31
|
+
}
|
|
32
|
+
const results = await runReleaseChecks(checks, {
|
|
33
|
+
repoRoot,
|
|
34
|
+
packagePaths,
|
|
35
|
+
scopePath: scopeCwd,
|
|
36
|
+
logger: ctx.platform?.logger
|
|
37
|
+
});
|
|
38
|
+
const allPassed = results.every((r) => r.ok || r.hint === "optional");
|
|
39
|
+
const checkItems = results.map((r) => ({
|
|
40
|
+
id: r.id,
|
|
41
|
+
name: checks.find((c) => c.id === r.id)?.name ?? r.id,
|
|
42
|
+
success: r.ok,
|
|
43
|
+
error: r.details && typeof r.details === "object" && "error" in r.details ? String(r.details.error) : void 0,
|
|
44
|
+
durationMs: r.timingMs ?? 0,
|
|
45
|
+
optional: checks.find((c) => c.id === r.id)?.optional
|
|
46
|
+
}));
|
|
47
|
+
return {
|
|
48
|
+
scope,
|
|
49
|
+
success: allPassed,
|
|
50
|
+
checks: checkItems,
|
|
51
|
+
totalDurationMs: Date.now() - startTime
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export { run_checks_handler_default as default };
|
|
57
|
+
//# sourceMappingURL=run-checks-handler.js.map
|
|
58
|
+
//# sourceMappingURL=run-checks-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/shared/utils.ts","../../../src/rest/handlers/run-checks-handler.ts"],"names":["findRepoRoot","join","readFile"],"mappings":"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","file":"run-checks-handler.js","sourcesContent":["import { join } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport globby from 'globby';\n\nexport { findRepoRoot } from '@kb-labs/sdk';\n\n/**\n * Converts scope to safe directory name\n */\nexport function scopeToDir(scope: string): string {\n return scope\n .replace(/^@/, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '-')\n .replace(/\\*/g, '');\n}\n\n/**\n * Converts safe directory name back to scope\n */\nexport function dirToScope(dirName: string): string {\n if (dirName === 'root') {\n return 'root';\n }\n\n const parts = dirName.split('-');\n if (parts.length >= 2) {\n return '@' + parts[0] + '-' + parts[1] + '/' + parts.slice(2).join('-');\n }\n\n return dirName;\n}\n\n/**\n * Resolve scope name to absolute filesystem path.\n * Scans all package.json in repoRoot to find the matching package by name.\n */\nexport async function resolveScopePath(repoRoot: string, scope: string): Promise<string> {\n if (scope === 'root') {\n return repoRoot;\n }\n\n if (scope.startsWith('@')) {\n const packageJsonPaths = await globby('**/package.json', {\n cwd: repoRoot,\n absolute: true,\n onlyFiles: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.*/**'],\n });\n\n for (const pkgJsonPath of packageJsonPaths) {\n try {\n const pkg = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n if (pkg.name === scope) {\n return join(pkgJsonPath, '..');\n }\n } catch { /* skip */ }\n }\n }\n\n // Direct path or fallback\n return join(repoRoot, scope);\n}\n","/**\n * Run pre-release checks handler — thin adapter over core runReleaseChecks().\n */\n\nimport { defineHandler, findRepoRoot, type RestInput, useConfig } from '@kb-labs/sdk';\nimport type { RunChecksRequest, RunChecksResponse, CheckResultItem } from '@kb-labs/release-manager-contracts';\nimport { runReleaseChecks, type ReleaseConfig, type CustomCheckConfig } from '@kb-labs/release-manager-core';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { scopeToDir } from '../../shared/utils.js';\nimport { resolveScopePath } from '@kb-labs/release-manager-core';\n\nexport default defineHandler({\n async execute(ctx, input: RestInput<unknown, RunChecksRequest>): Promise<RunChecksResponse> {\n const scope = input.body?.scope ?? 'root';\n const cwd = ctx.cwd ?? process.cwd();\n const repoRoot = await findRepoRoot(cwd);\n const scopeCwd = await resolveScopePath(repoRoot, scope);\n const startTime = Date.now();\n\n const config = await useConfig<ReleaseConfig>();\n const checks: CustomCheckConfig[] = config?.scopes?.[scope]?.checks ?? config?.checks ?? [];\n\n if (checks.length === 0) {\n return { scope, success: true, checks: [], totalDurationMs: Date.now() - startTime };\n }\n\n // Read plan to get package paths\n const scopeDir = scopeToDir(scope);\n const planPath = join(repoRoot, '.kb/release/plans', scopeDir, 'current', 'plan.json');\n let packagePaths: string[] = [];\n try {\n const plan: { packages: Array<{ name: string; path: string }> } = JSON.parse(await readFile(planPath, 'utf-8'));\n packagePaths = plan.packages.map(pkg => pkg.path.startsWith('/') ? pkg.path : join(repoRoot, pkg.path));\n } catch {\n packagePaths = [scopeCwd];\n }\n\n // Run checks via core\n const results = await runReleaseChecks(checks, {\n repoRoot,\n packagePaths,\n scopePath: scopeCwd,\n logger: ctx.platform?.logger,\n });\n\n const allPassed = results.every(r => r.ok || r.hint === 'optional');\n\n // Map core CheckResult to REST CheckResultItem\n const checkItems: CheckResultItem[] = results.map(r => ({\n id: r.id,\n name: checks.find(c => c.id === r.id)?.name ?? r.id,\n success: r.ok,\n error: r.details && typeof r.details === 'object' && 'error' in r.details ? String((r.details as any).error) : undefined,\n durationMs: r.timingMs ?? 0,\n optional: checks.find(c => c.id === r.id)?.optional,\n }));\n\n return {\n scope,\n success: allPassed,\n checks: checkItems,\n totalDurationMs: Date.now() - startTime,\n };\n },\n});\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<unknown, {
|
|
5
|
+
scope: string;
|
|
6
|
+
strict?: boolean | undefined;
|
|
7
|
+
dryRun?: boolean | undefined;
|
|
8
|
+
skipChecks?: boolean | undefined;
|
|
9
|
+
otp?: string | undefined;
|
|
10
|
+
}, unknown>, {
|
|
11
|
+
report: {
|
|
12
|
+
scope: string;
|
|
13
|
+
schemaVersion: "1.0";
|
|
14
|
+
ts: string;
|
|
15
|
+
context: {
|
|
16
|
+
repo: string;
|
|
17
|
+
cwd: string;
|
|
18
|
+
branch: string;
|
|
19
|
+
profile?: string | undefined;
|
|
20
|
+
dryRun?: boolean | undefined;
|
|
21
|
+
};
|
|
22
|
+
stage: "rollback" | "planning" | "checking" | "versioning" | "publishing" | "verifying";
|
|
23
|
+
result: {
|
|
24
|
+
ok: boolean;
|
|
25
|
+
timingMs: number;
|
|
26
|
+
changelog?: string | undefined;
|
|
27
|
+
version?: string | undefined;
|
|
28
|
+
published?: string[] | undefined;
|
|
29
|
+
skipped?: string[] | undefined;
|
|
30
|
+
checks?: Record<string, {
|
|
31
|
+
id: string;
|
|
32
|
+
ok: boolean;
|
|
33
|
+
details?: unknown;
|
|
34
|
+
hint?: string | undefined;
|
|
35
|
+
timingMs?: number | undefined;
|
|
36
|
+
}> | undefined;
|
|
37
|
+
git?: {
|
|
38
|
+
committed: boolean;
|
|
39
|
+
tagged: string[];
|
|
40
|
+
pushed: boolean;
|
|
41
|
+
} | undefined;
|
|
42
|
+
errors?: string[] | undefined;
|
|
43
|
+
};
|
|
44
|
+
plan?: {
|
|
45
|
+
scope: string;
|
|
46
|
+
schemaVersion: "1.0";
|
|
47
|
+
packages: {
|
|
48
|
+
name: string;
|
|
49
|
+
path: string;
|
|
50
|
+
currentVersion: string;
|
|
51
|
+
nextVersion: string;
|
|
52
|
+
bump: "patch" | "minor" | "major" | "auto";
|
|
53
|
+
isPublished: boolean;
|
|
54
|
+
dependencies?: string[] | undefined;
|
|
55
|
+
reason?: string | undefined;
|
|
56
|
+
}[];
|
|
57
|
+
strategy: "semver";
|
|
58
|
+
registry: string;
|
|
59
|
+
rollbackEnabled: boolean;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
} | undefined;
|
|
62
|
+
};
|
|
63
|
+
scope: string;
|
|
64
|
+
success: boolean;
|
|
65
|
+
errors?: string[] | undefined;
|
|
66
|
+
}>;
|
|
67
|
+
|
|
68
|
+
export { _default as default };
|