@spekn/cli 1.0.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/__tests__/export-cli.test.d.ts +1 -0
- package/dist/__tests__/export-cli.test.js +70 -0
- package/dist/__tests__/tui-args-policy.test.d.ts +1 -0
- package/dist/__tests__/tui-args-policy.test.js +50 -0
- package/dist/acp-S2MHZOAD.mjs +23 -0
- package/dist/acp-UCCI44JY.mjs +25 -0
- package/dist/auth/credentials-store.d.ts +2 -0
- package/dist/auth/credentials-store.js +5 -0
- package/dist/auth/device-flow.d.ts +36 -0
- package/dist/auth/device-flow.js +189 -0
- package/dist/auth/jwt.d.ts +1 -0
- package/dist/auth/jwt.js +6 -0
- package/dist/auth/session.d.ts +67 -0
- package/dist/auth/session.js +86 -0
- package/dist/auth-login.d.ts +34 -0
- package/dist/auth-login.js +202 -0
- package/dist/auth-logout.d.ts +25 -0
- package/dist/auth-logout.js +115 -0
- package/dist/auth-status.d.ts +24 -0
- package/dist/auth-status.js +109 -0
- package/dist/backlog-generate.d.ts +11 -0
- package/dist/backlog-generate.js +308 -0
- package/dist/backlog-health.d.ts +11 -0
- package/dist/backlog-health.js +287 -0
- package/dist/bridge-login.d.ts +40 -0
- package/dist/bridge-login.js +277 -0
- package/dist/chunk-3PAYRI4G.mjs +2428 -0
- package/dist/chunk-M4CS3A25.mjs +2426 -0
- package/dist/commands/auth/login.d.ts +30 -0
- package/dist/commands/auth/login.js +164 -0
- package/dist/commands/auth/logout.d.ts +25 -0
- package/dist/commands/auth/logout.js +115 -0
- package/dist/commands/auth/status.d.ts +24 -0
- package/dist/commands/auth/status.js +109 -0
- package/dist/commands/backlog/generate.d.ts +11 -0
- package/dist/commands/backlog/generate.js +308 -0
- package/dist/commands/backlog/health.d.ts +11 -0
- package/dist/commands/backlog/health.js +287 -0
- package/dist/commands/bridge/login.d.ts +36 -0
- package/dist/commands/bridge/login.js +258 -0
- package/dist/commands/export.d.ts +35 -0
- package/dist/commands/export.js +485 -0
- package/dist/commands/marketplace-export.d.ts +21 -0
- package/dist/commands/marketplace-export.js +214 -0
- package/dist/commands/project-clean.d.ts +1 -0
- package/dist/commands/project-clean.js +126 -0
- package/dist/commands/repo/common.d.ts +105 -0
- package/dist/commands/repo/common.js +775 -0
- package/dist/commands/repo/detach.d.ts +2 -0
- package/dist/commands/repo/detach.js +120 -0
- package/dist/commands/repo/register.d.ts +21 -0
- package/dist/commands/repo/register.js +175 -0
- package/dist/commands/repo/sync.d.ts +22 -0
- package/dist/commands/repo/sync.js +873 -0
- package/dist/commands/skills-import-local.d.ts +16 -0
- package/dist/commands/skills-import-local.js +352 -0
- package/dist/commands/spec/drift-check.d.ts +3 -0
- package/dist/commands/spec/drift-check.js +186 -0
- package/dist/commands/spec/frontmatter.d.ts +11 -0
- package/dist/commands/spec/frontmatter.js +219 -0
- package/dist/commands/spec/lint.d.ts +11 -0
- package/dist/commands/spec/lint.js +499 -0
- package/dist/commands/spec/parse.d.ts +11 -0
- package/dist/commands/spec/parse.js +162 -0
- package/dist/export.d.ts +35 -0
- package/dist/export.js +485 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +21 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +115280 -0
- package/dist/marketplace-export.d.ts +21 -0
- package/dist/marketplace-export.js +214 -0
- package/dist/project-clean.d.ts +1 -0
- package/dist/project-clean.js +126 -0
- package/dist/project-context.d.ts +99 -0
- package/dist/project-context.js +376 -0
- package/dist/repo-common.d.ts +101 -0
- package/dist/repo-common.js +671 -0
- package/dist/repo-detach.d.ts +2 -0
- package/dist/repo-detach.js +102 -0
- package/dist/repo-ingest.d.ts +29 -0
- package/dist/repo-ingest.js +305 -0
- package/dist/repo-register.d.ts +21 -0
- package/dist/repo-register.js +175 -0
- package/dist/repo-sync.d.ts +16 -0
- package/dist/repo-sync.js +152 -0
- package/dist/resources/prompt-loader.d.ts +1 -0
- package/dist/resources/prompt-loader.js +62 -0
- package/dist/resources/prompts/README.md +21 -0
- package/dist/resources/prompts/prompts/repo-analysis.prompt.md +126 -0
- package/dist/resources/prompts/repo-analysis.prompt.md +151 -0
- package/dist/resources/prompts/repo-sync-analysis.prompt.md +85 -0
- package/dist/skills-import-local.d.ts +16 -0
- package/dist/skills-import-local.js +352 -0
- package/dist/spec-drift-check.d.ts +3 -0
- package/dist/spec-drift-check.js +186 -0
- package/dist/spec-frontmatter.d.ts +11 -0
- package/dist/spec-frontmatter.js +219 -0
- package/dist/spec-lint.d.ts +11 -0
- package/dist/spec-lint.js +499 -0
- package/dist/spec-parse.d.ts +11 -0
- package/dist/spec-parse.js +162 -0
- package/dist/stubs/dotenv.d.ts +5 -0
- package/dist/stubs/dotenv.js +6 -0
- package/dist/stubs/typeorm.d.ts +22 -0
- package/dist/stubs/typeorm.js +28 -0
- package/dist/tui/app.d.ts +7 -0
- package/dist/tui/app.js +122 -0
- package/dist/tui/args.d.ts +8 -0
- package/dist/tui/args.js +57 -0
- package/dist/tui/capabilities/policy.d.ts +7 -0
- package/dist/tui/capabilities/policy.js +64 -0
- package/dist/tui/components/frame.d.ts +8 -0
- package/dist/tui/components/frame.js +8 -0
- package/dist/tui/components/status-bar.d.ts +8 -0
- package/dist/tui/components/status-bar.js +8 -0
- package/dist/tui/index.d.ts +2 -0
- package/dist/tui/index.js +23 -0
- package/dist/tui/index.mjs +7563 -0
- package/dist/tui/keymap/use-global-keymap.d.ts +19 -0
- package/dist/tui/keymap/use-global-keymap.js +82 -0
- package/dist/tui/navigation/nav-items.d.ts +3 -0
- package/dist/tui/navigation/nav-items.js +18 -0
- package/dist/tui/screens/bridge.d.ts +8 -0
- package/dist/tui/screens/bridge.js +19 -0
- package/dist/tui/screens/decisions.d.ts +5 -0
- package/dist/tui/screens/decisions.js +28 -0
- package/dist/tui/screens/export.d.ts +5 -0
- package/dist/tui/screens/export.js +16 -0
- package/dist/tui/screens/home.d.ts +5 -0
- package/dist/tui/screens/home.js +33 -0
- package/dist/tui/screens/locked.d.ts +5 -0
- package/dist/tui/screens/locked.js +9 -0
- package/dist/tui/screens/specs.d.ts +5 -0
- package/dist/tui/screens/specs.js +31 -0
- package/dist/tui/services/client.d.ts +1 -0
- package/dist/tui/services/client.js +18 -0
- package/dist/tui/services/context-service.d.ts +19 -0
- package/dist/tui/services/context-service.js +246 -0
- package/dist/tui/shared-enums.d.ts +16 -0
- package/dist/tui/shared-enums.js +19 -0
- package/dist/tui/state/use-app-state.d.ts +35 -0
- package/dist/tui/state/use-app-state.js +177 -0
- package/dist/tui/types.d.ts +77 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui-bundle.d.ts +1 -0
- package/dist/tui-bundle.js +5 -0
- package/dist/tui-entry.mjs +1407 -0
- package/dist/utils/cli-runtime.d.ts +5 -0
- package/dist/utils/cli-runtime.js +22 -0
- package/dist/utils/help-error.d.ts +7 -0
- package/dist/utils/help-error.js +14 -0
- package/dist/utils/interaction.d.ts +19 -0
- package/dist/utils/interaction.js +93 -0
- package/dist/utils/structured-log.d.ts +7 -0
- package/dist/utils/structured-log.js +112 -0
- package/dist/utils/trpc-url.d.ts +4 -0
- package/dist/utils/trpc-url.js +15 -0
- package/package.json +59 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.runMarketplaceExportCli = runMarketplaceExportCli;
|
|
38
|
+
exports.main = main;
|
|
39
|
+
exports.parseArgs = parseArgs;
|
|
40
|
+
const client_1 = require("@trpc/client");
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const credentials_store_1 = require("../auth/credentials-store");
|
|
44
|
+
const export_1 = require("./export");
|
|
45
|
+
const project_context_1 = require("../project-context");
|
|
46
|
+
const structured_log_1 = require("../utils/structured-log");
|
|
47
|
+
const defaultDeps = {
|
|
48
|
+
createClient: (apiUrl, organizationId, authToken) => (0, client_1.createTRPCProxyClient)({
|
|
49
|
+
links: [
|
|
50
|
+
(0, client_1.httpBatchLink)({
|
|
51
|
+
url: (0, export_1.normalizeTrpcUrl)(apiUrl),
|
|
52
|
+
headers: {
|
|
53
|
+
'x-organization-id': organizationId,
|
|
54
|
+
authorization: authToken ? `Bearer ${authToken}` : '',
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
],
|
|
58
|
+
}),
|
|
59
|
+
writeFile: (filePath, content) => {
|
|
60
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
61
|
+
},
|
|
62
|
+
mkdirSync: (dirPath) => {
|
|
63
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
64
|
+
},
|
|
65
|
+
stdout: (content) => process.stdout.write(content),
|
|
66
|
+
stderr: (content) => process.stderr.write(content),
|
|
67
|
+
credentialsStore: new credentials_store_1.CredentialsStore(),
|
|
68
|
+
};
|
|
69
|
+
function printHelp(stderr) {
|
|
70
|
+
stderr(`
|
|
71
|
+
marketplace export - Export Claude Code-compatible plugin marketplace to disk
|
|
72
|
+
|
|
73
|
+
USAGE:
|
|
74
|
+
spekn marketplace export --project <uuid> [options]
|
|
75
|
+
|
|
76
|
+
OPTIONS:
|
|
77
|
+
--project <uuid> Project ID (optional if .spekn/context is present)
|
|
78
|
+
--output <dir> Output directory (default: .)
|
|
79
|
+
--api-url <url> API base URL (default: SPEKN_API_URL or https://app.spekn.com)
|
|
80
|
+
--marketplace-name <name> Marketplace identifier (default: spekn-marketplace)
|
|
81
|
+
--owner-name <name> Owner name (default: Spekn)
|
|
82
|
+
--help Show help
|
|
83
|
+
`);
|
|
84
|
+
}
|
|
85
|
+
function parseArgs(args) {
|
|
86
|
+
let projectId = '';
|
|
87
|
+
let output = '.';
|
|
88
|
+
let apiUrl = process.env.SPEKN_API_URL || 'https://app.spekn.com';
|
|
89
|
+
let marketplaceName = 'spekn-marketplace';
|
|
90
|
+
let ownerName = 'Spekn';
|
|
91
|
+
for (let index = 0; index < args.length; index++) {
|
|
92
|
+
const arg = args[index];
|
|
93
|
+
if (arg === '--help' || arg === '-h') {
|
|
94
|
+
throw new Error('__HELP__');
|
|
95
|
+
}
|
|
96
|
+
if (arg === '--project' && args[index + 1]) {
|
|
97
|
+
projectId = args[++index];
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (arg.startsWith('--project=')) {
|
|
101
|
+
projectId = arg.slice('--project='.length);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (arg === '--output' && args[index + 1]) {
|
|
105
|
+
output = args[++index];
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (arg.startsWith('--output=')) {
|
|
109
|
+
output = arg.slice('--output='.length);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (arg === '--api-url' && args[index + 1]) {
|
|
113
|
+
apiUrl = args[++index];
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (arg.startsWith('--api-url=')) {
|
|
117
|
+
apiUrl = arg.slice('--api-url='.length);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (arg === '--marketplace-name' && args[index + 1]) {
|
|
121
|
+
marketplaceName = args[++index];
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (arg.startsWith('--marketplace-name=')) {
|
|
125
|
+
marketplaceName = arg.slice('--marketplace-name='.length);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (arg === '--owner-name' && args[index + 1]) {
|
|
129
|
+
ownerName = args[++index];
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (arg.startsWith('--owner-name=')) {
|
|
133
|
+
ownerName = arg.slice('--owner-name='.length);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
projectId,
|
|
139
|
+
output,
|
|
140
|
+
apiUrl,
|
|
141
|
+
marketplaceName,
|
|
142
|
+
ownerName,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async function runMarketplaceExportCli(args, deps = defaultDeps) {
|
|
146
|
+
try {
|
|
147
|
+
const options = parseArgs(args);
|
|
148
|
+
(0, structured_log_1.appendCliStructuredLog)({
|
|
149
|
+
source: 'cli.marketplace.export',
|
|
150
|
+
level: 'info',
|
|
151
|
+
message: 'Starting marketplace export',
|
|
152
|
+
details: { output: options.output, apiUrl: options.apiUrl, marketplaceName: options.marketplaceName },
|
|
153
|
+
});
|
|
154
|
+
const storedToken = await deps.credentialsStore.getValidToken();
|
|
155
|
+
const authToken = storedToken ?? process.env.SPEKN_AUTH_TOKEN;
|
|
156
|
+
const storedCreds = deps.credentialsStore.load();
|
|
157
|
+
const context = (0, project_context_1.resolveProjectContext)({
|
|
158
|
+
explicitProjectId: options.projectId,
|
|
159
|
+
repoPath: process.cwd(),
|
|
160
|
+
credentialsOrganizationId: storedCreds?.organizationId,
|
|
161
|
+
envOrganizationId: process.env.SPEKN_ORGANIZATION_ID,
|
|
162
|
+
});
|
|
163
|
+
const client = deps.createClient(options.apiUrl, context.organizationId, authToken ?? undefined);
|
|
164
|
+
const result = await client.marketplace.exportClaudeCodeCatalog.query({
|
|
165
|
+
marketplaceName: options.marketplaceName,
|
|
166
|
+
ownerName: options.ownerName,
|
|
167
|
+
});
|
|
168
|
+
const outputDir = path.resolve(process.cwd(), options.output);
|
|
169
|
+
// Write marketplace.json
|
|
170
|
+
const marketplaceDir = path.join(outputDir, '.claude-plugin');
|
|
171
|
+
deps.mkdirSync(marketplaceDir);
|
|
172
|
+
deps.writeFile(path.join(marketplaceDir, 'marketplace.json'), typeof result.json === 'string' ? result.json : JSON.stringify(result.json, null, 2));
|
|
173
|
+
// Write per-plugin manifests
|
|
174
|
+
for (const entry of result.entries) {
|
|
175
|
+
const pluginDir = path.join(outputDir, 'plugins', entry.name, '.claude-plugin');
|
|
176
|
+
deps.mkdirSync(pluginDir);
|
|
177
|
+
deps.writeFile(path.join(pluginDir, 'plugin.json'), JSON.stringify({
|
|
178
|
+
name: entry.name,
|
|
179
|
+
description: entry.description,
|
|
180
|
+
version: entry.version,
|
|
181
|
+
author: entry.author,
|
|
182
|
+
}, null, 2));
|
|
183
|
+
}
|
|
184
|
+
deps.stdout(`Exported ${result.pluginCount} plugins to ${outputDir}\n`);
|
|
185
|
+
(0, structured_log_1.appendCliStructuredLog)({
|
|
186
|
+
source: 'cli.marketplace.export',
|
|
187
|
+
level: 'info',
|
|
188
|
+
message: 'Marketplace export complete',
|
|
189
|
+
details: { outputDir, pluginCount: result.pluginCount },
|
|
190
|
+
});
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
if (error instanceof Error && error.message === '__HELP__') {
|
|
195
|
+
printHelp(deps.stderr);
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
199
|
+
deps.stderr(`Error: ${message}\n`);
|
|
200
|
+
(0, structured_log_1.appendCliStructuredLog)({
|
|
201
|
+
source: 'cli.marketplace.export',
|
|
202
|
+
level: 'error',
|
|
203
|
+
message,
|
|
204
|
+
});
|
|
205
|
+
return 1;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async function main() {
|
|
209
|
+
const exitCode = await runMarketplaceExportCli(process.argv.slice(2));
|
|
210
|
+
process.exit(exitCode);
|
|
211
|
+
}
|
|
212
|
+
if (require.main === module) {
|
|
213
|
+
void main();
|
|
214
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runProjectDeleteCli(args: string[]): Promise<number>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runProjectDeleteCli = runProjectDeleteCli;
|
|
4
|
+
const client_1 = require("@trpc/client");
|
|
5
|
+
const credentials_store_1 = require("../auth/credentials-store");
|
|
6
|
+
const trpc_url_1 = require("../utils/trpc-url");
|
|
7
|
+
/**
|
|
8
|
+
* Delete a project using the API. With the fixed foreign key constraints,
|
|
9
|
+
* the database will automatically cascade delete all related entities.
|
|
10
|
+
*/
|
|
11
|
+
async function deleteProject(projectId, apiUrl) {
|
|
12
|
+
const credentialsStore = new credentials_store_1.CredentialsStore();
|
|
13
|
+
const authToken = await credentialsStore.getValidToken();
|
|
14
|
+
if (!authToken) {
|
|
15
|
+
throw new Error("Not authenticated. Please run 'spekn auth login' first.");
|
|
16
|
+
}
|
|
17
|
+
const credentials = credentialsStore.load();
|
|
18
|
+
const organizationId = credentials?.organizationId ?? "";
|
|
19
|
+
const trpc = (0, client_1.createTRPCProxyClient)({
|
|
20
|
+
links: [
|
|
21
|
+
(0, client_1.httpBatchLink)({
|
|
22
|
+
url: (0, trpc_url_1.normalizeTrpcUrl)(apiUrl),
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Bearer ${authToken}`,
|
|
25
|
+
"x-organization-id": organizationId,
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
console.log(`Deleting project ${projectId}...`);
|
|
31
|
+
try {
|
|
32
|
+
// With the fixed foreign key constraints, this single call will
|
|
33
|
+
// automatically cascade delete all related entities
|
|
34
|
+
await trpc.project.delete.mutate({ id: projectId });
|
|
35
|
+
console.log(`✅ Project ${projectId} and all related entities have been successfully deleted.`);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("❌ Error deleting project:", error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function printHelp() {
|
|
43
|
+
console.log(`
|
|
44
|
+
project delete - Delete a project and all its related entities
|
|
45
|
+
|
|
46
|
+
USAGE:
|
|
47
|
+
spekn project delete <project-id> [options]
|
|
48
|
+
|
|
49
|
+
ARGUMENTS:
|
|
50
|
+
<project-id> Project ID to delete
|
|
51
|
+
|
|
52
|
+
OPTIONS:
|
|
53
|
+
--api-url <url> API URL (default: SPEKN_API_URL or https://app.spekn.com)
|
|
54
|
+
--force Skip confirmation prompt
|
|
55
|
+
--help Show this help message
|
|
56
|
+
|
|
57
|
+
EXAMPLES:
|
|
58
|
+
spekn project delete 11111111-1111-4111-8111-111111111111
|
|
59
|
+
spekn project delete 11111111-1111-4111-8111-111111111111 --force
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
async function runProjectDeleteCli(args) {
|
|
63
|
+
// Parse arguments manually since we receive already-sliced args
|
|
64
|
+
let projectId;
|
|
65
|
+
let force = false;
|
|
66
|
+
let apiUrl = process.env.SPEKN_API_URL ?? "https://app.spekn.com";
|
|
67
|
+
for (let i = 0; i < args.length; i++) {
|
|
68
|
+
const arg = args[i];
|
|
69
|
+
if (arg === "--help" || arg === "-h") {
|
|
70
|
+
printHelp();
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
if (arg === "--force") {
|
|
74
|
+
force = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (arg === "--api-url" && args[i + 1]) {
|
|
78
|
+
apiUrl = args[i + 1];
|
|
79
|
+
i++; // skip next arg
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (arg.startsWith("--api-url=")) {
|
|
83
|
+
apiUrl = arg.slice("--api-url=".length);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Positional argument (project-id)
|
|
87
|
+
if (!projectId && !arg.startsWith("--")) {
|
|
88
|
+
projectId = arg;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Validate required arguments
|
|
93
|
+
if (!projectId) {
|
|
94
|
+
console.error("Error: Missing required argument <project-id>");
|
|
95
|
+
printHelp();
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
// Add confirmation prompt unless --force is used
|
|
100
|
+
if (!force) {
|
|
101
|
+
// Note: In a real implementation, we would use a proper prompt library
|
|
102
|
+
// For now, we'll proceed without confirmation to keep it simple
|
|
103
|
+
console.log(`🚨 Warning: This will permanently delete project ${projectId} and all related data.`);
|
|
104
|
+
console.log(`📝 Related entities that will be deleted: git repositories, specifications, tasks, decisions, runs, verifications, notes, worktrees, merge requests`);
|
|
105
|
+
console.log(`🔥 This action cannot be undone.`);
|
|
106
|
+
// TODO: Add proper interactive confirmation
|
|
107
|
+
// const confirmed = await confirm("Are you sure you want to continue? (y/N)");
|
|
108
|
+
// if (!confirmed) {
|
|
109
|
+
// console.log("💡 Deletion cancelled.");
|
|
110
|
+
// return 0;
|
|
111
|
+
// }
|
|
112
|
+
}
|
|
113
|
+
await deleteProject(projectId, apiUrl);
|
|
114
|
+
return 0;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (require.main === module) {
|
|
122
|
+
runProjectDeleteCli(process.argv.slice(2)).catch((err) => {
|
|
123
|
+
console.error(err);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for repo register / repo sync CLI commands.
|
|
3
|
+
*
|
|
4
|
+
* Extracts common concerns: deps, auth, git metadata, tRPC client, and
|
|
5
|
+
* file discovery. ACP prompt-driven analysis utilities are used by
|
|
6
|
+
* `repo register`; `repo sync` runs ingestion drift analysis via API calls.
|
|
7
|
+
*/
|
|
8
|
+
import { CredentialsStore } from "../../auth/credentials-store";
|
|
9
|
+
import { HelpRequestedError } from "../../utils/help-error";
|
|
10
|
+
export interface Deps {
|
|
11
|
+
execGit: (args: string[]) => string;
|
|
12
|
+
stdout: (content: string) => void;
|
|
13
|
+
stderr: (content: string) => void;
|
|
14
|
+
credentialsStore: CredentialsStore;
|
|
15
|
+
}
|
|
16
|
+
export declare const defaultDeps: Deps;
|
|
17
|
+
/** Fields common to both register and sync CLI options. */
|
|
18
|
+
export interface CommonOptions {
|
|
19
|
+
projectId: string;
|
|
20
|
+
apiUrl: string;
|
|
21
|
+
analyze: boolean;
|
|
22
|
+
agent: string | null;
|
|
23
|
+
repoPath: string;
|
|
24
|
+
dryRun: boolean;
|
|
25
|
+
mcpUrl: string;
|
|
26
|
+
debug: boolean;
|
|
27
|
+
acpTimeoutMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface DiscoveredFile {
|
|
30
|
+
relativePath: string;
|
|
31
|
+
absolutePath: string;
|
|
32
|
+
category: "governance" | "spec" | "decision" | "config" | "pdf";
|
|
33
|
+
}
|
|
34
|
+
export { HelpRequestedError };
|
|
35
|
+
/**
|
|
36
|
+
* Parse flags shared by both register and sync. Returns consumed arg
|
|
37
|
+
* count (0 if the flag was not recognized). Mutates `out` in place.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseCommonFlag(args: string[], index: number, out: CommonOptions): number;
|
|
40
|
+
export declare function commonDefaults(analyzeDefault: boolean): CommonOptions;
|
|
41
|
+
export declare function finalizeOptions<T extends CommonOptions>(opts: T): T;
|
|
42
|
+
export declare function resolveAuth(deps: Deps, options?: {
|
|
43
|
+
projectId?: string;
|
|
44
|
+
repoPath?: string;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
authToken: string | undefined;
|
|
47
|
+
organizationId: string;
|
|
48
|
+
projectId: string;
|
|
49
|
+
}>;
|
|
50
|
+
export declare function createApiClient(apiUrl: string, authToken: string | undefined, organizationId: string): any;
|
|
51
|
+
export declare function repoNameFromUrl(url: string): string;
|
|
52
|
+
export declare function resolveDefaultBranch(execGit: Deps["execGit"]): string;
|
|
53
|
+
export declare function readGitMetadata(repoPath: string, deps: Deps): {
|
|
54
|
+
remoteUrl: string;
|
|
55
|
+
name: string;
|
|
56
|
+
defaultBranch: string;
|
|
57
|
+
} | null;
|
|
58
|
+
export declare function discoverFiles(repoPath: string): DiscoveredFile[];
|
|
59
|
+
/** Discover files, print summary. Returns files or null if empty. */
|
|
60
|
+
export declare function discoverAndDisplay(repoPath: string, stdout: (s: string) => void): DiscoveredFile[] | null;
|
|
61
|
+
export declare function buildAnalysisPrompt(projectId: string, repoPath: string, files: DiscoveredFile[], organizationId?: string): string;
|
|
62
|
+
export declare function validateAnalysisReport(text: string): {
|
|
63
|
+
ok: boolean;
|
|
64
|
+
missing: string[];
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Connect to the MCP HTTP server via raw JSON-RPC, perform the MCP
|
|
68
|
+
* initialize handshake, then list tools and verify Spekn tools exist.
|
|
69
|
+
* Returns tool names on success or null on failure.
|
|
70
|
+
*/
|
|
71
|
+
export declare function verifyMcpServer(mcpUrl: string, authToken: string, stderr: (s: string) => void, debug: boolean, sessionPurpose?: string): Promise<string[] | null>;
|
|
72
|
+
export declare function executeAcpSession(agent: {
|
|
73
|
+
command: string;
|
|
74
|
+
args: string[];
|
|
75
|
+
}, prompt: string, repoPath: string, mcpUrl: string, authToken: string, stderr: (s: string) => void, organizationId?: string, sessionPurpose?: string, acpTimeoutMs?: number): Promise<{
|
|
76
|
+
text: string;
|
|
77
|
+
error?: string;
|
|
78
|
+
}>;
|
|
79
|
+
export interface AnalysisOptions {
|
|
80
|
+
apiUrl: string;
|
|
81
|
+
agentName: string | null;
|
|
82
|
+
prompt: string;
|
|
83
|
+
repoPath: string;
|
|
84
|
+
mcpUrl: string;
|
|
85
|
+
authToken: string;
|
|
86
|
+
organizationId?: string;
|
|
87
|
+
requiredTools?: string[];
|
|
88
|
+
stdout: (s: string) => void;
|
|
89
|
+
stderr: (s: string) => void;
|
|
90
|
+
debug: boolean;
|
|
91
|
+
acpTimeoutMs?: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Verify MCP server, resolve an agent, run the ACP session.
|
|
95
|
+
* Retries with the next agent if one doesn't support HTTP MCP.
|
|
96
|
+
*/
|
|
97
|
+
export declare function runAnalysisWithAgent(options: AnalysisOptions): Promise<{
|
|
98
|
+
text: string;
|
|
99
|
+
error?: string;
|
|
100
|
+
}>;
|
|
101
|
+
/**
|
|
102
|
+
* Complete analysis phase: discover files → build prompt → run agent.
|
|
103
|
+
* Returns exit code (0 = success, 1 = error).
|
|
104
|
+
*/
|
|
105
|
+
export declare function runAnalysisPhase(options: CommonOptions, authToken: string, deps: Deps, organizationId?: string): Promise<number>;
|