@spekn/cli 1.0.0 → 1.0.1
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 +58 -0
- package/dist/main.js +3707 -611
- package/dist/tui/index.mjs +2 -2
- package/package.json +29 -12
- package/dist/__tests__/export-cli.test.d.ts +0 -1
- package/dist/__tests__/export-cli.test.js +0 -70
- package/dist/__tests__/tui-args-policy.test.d.ts +0 -1
- package/dist/__tests__/tui-args-policy.test.js +0 -50
- package/dist/acp-S2MHZOAD.mjs +0 -23
- package/dist/acp-UCCI44JY.mjs +0 -25
- package/dist/auth/credentials-store.d.ts +0 -2
- package/dist/auth/credentials-store.js +0 -5
- package/dist/auth/device-flow.d.ts +0 -36
- package/dist/auth/device-flow.js +0 -189
- package/dist/auth/jwt.d.ts +0 -1
- package/dist/auth/jwt.js +0 -6
- package/dist/auth/session.d.ts +0 -67
- package/dist/auth/session.js +0 -86
- package/dist/auth-login.d.ts +0 -34
- package/dist/auth-login.js +0 -202
- package/dist/auth-logout.d.ts +0 -25
- package/dist/auth-logout.js +0 -115
- package/dist/auth-status.d.ts +0 -24
- package/dist/auth-status.js +0 -109
- package/dist/backlog-generate.d.ts +0 -11
- package/dist/backlog-generate.js +0 -308
- package/dist/backlog-health.d.ts +0 -11
- package/dist/backlog-health.js +0 -287
- package/dist/bridge-login.d.ts +0 -40
- package/dist/bridge-login.js +0 -277
- package/dist/chunk-3PAYRI4G.mjs +0 -2428
- package/dist/chunk-M4CS3A25.mjs +0 -2426
- package/dist/commands/auth/login.d.ts +0 -30
- package/dist/commands/auth/login.js +0 -164
- package/dist/commands/auth/logout.d.ts +0 -25
- package/dist/commands/auth/logout.js +0 -115
- package/dist/commands/auth/status.d.ts +0 -24
- package/dist/commands/auth/status.js +0 -109
- package/dist/commands/backlog/generate.d.ts +0 -11
- package/dist/commands/backlog/generate.js +0 -308
- package/dist/commands/backlog/health.d.ts +0 -11
- package/dist/commands/backlog/health.js +0 -287
- package/dist/commands/bridge/login.d.ts +0 -36
- package/dist/commands/bridge/login.js +0 -258
- package/dist/commands/export.d.ts +0 -35
- package/dist/commands/export.js +0 -485
- package/dist/commands/marketplace-export.d.ts +0 -21
- package/dist/commands/marketplace-export.js +0 -214
- package/dist/commands/project-clean.d.ts +0 -1
- package/dist/commands/project-clean.js +0 -126
- package/dist/commands/repo/common.d.ts +0 -105
- package/dist/commands/repo/common.js +0 -775
- package/dist/commands/repo/detach.d.ts +0 -2
- package/dist/commands/repo/detach.js +0 -120
- package/dist/commands/repo/register.d.ts +0 -21
- package/dist/commands/repo/register.js +0 -175
- package/dist/commands/repo/sync.d.ts +0 -22
- package/dist/commands/repo/sync.js +0 -873
- package/dist/commands/skills-import-local.d.ts +0 -16
- package/dist/commands/skills-import-local.js +0 -352
- package/dist/commands/spec/drift-check.d.ts +0 -3
- package/dist/commands/spec/drift-check.js +0 -186
- package/dist/commands/spec/frontmatter.d.ts +0 -11
- package/dist/commands/spec/frontmatter.js +0 -219
- package/dist/commands/spec/lint.d.ts +0 -11
- package/dist/commands/spec/lint.js +0 -499
- package/dist/commands/spec/parse.d.ts +0 -11
- package/dist/commands/spec/parse.js +0 -162
- package/dist/export.d.ts +0 -35
- package/dist/export.js +0 -485
- package/dist/main.d.ts +0 -1
- package/dist/marketplace-export.d.ts +0 -21
- package/dist/marketplace-export.js +0 -214
- package/dist/project-clean.d.ts +0 -1
- package/dist/project-clean.js +0 -126
- package/dist/project-context.d.ts +0 -99
- package/dist/project-context.js +0 -376
- package/dist/repo-common.d.ts +0 -101
- package/dist/repo-common.js +0 -671
- package/dist/repo-detach.d.ts +0 -2
- package/dist/repo-detach.js +0 -102
- package/dist/repo-ingest.d.ts +0 -29
- package/dist/repo-ingest.js +0 -305
- package/dist/repo-register.d.ts +0 -21
- package/dist/repo-register.js +0 -175
- package/dist/repo-sync.d.ts +0 -16
- package/dist/repo-sync.js +0 -152
- package/dist/resources/prompt-loader.d.ts +0 -1
- package/dist/resources/prompt-loader.js +0 -62
- package/dist/skills-import-local.d.ts +0 -16
- package/dist/skills-import-local.js +0 -352
- package/dist/spec-drift-check.d.ts +0 -3
- package/dist/spec-drift-check.js +0 -186
- package/dist/spec-frontmatter.d.ts +0 -11
- package/dist/spec-frontmatter.js +0 -219
- package/dist/spec-lint.d.ts +0 -11
- package/dist/spec-lint.js +0 -499
- package/dist/spec-parse.d.ts +0 -11
- package/dist/spec-parse.js +0 -162
- package/dist/stubs/dotenv.d.ts +0 -5
- package/dist/stubs/dotenv.js +0 -6
- package/dist/stubs/typeorm.d.ts +0 -22
- package/dist/stubs/typeorm.js +0 -28
- package/dist/tui/app.d.ts +0 -7
- package/dist/tui/app.js +0 -122
- package/dist/tui/args.d.ts +0 -8
- package/dist/tui/args.js +0 -57
- package/dist/tui/capabilities/policy.d.ts +0 -7
- package/dist/tui/capabilities/policy.js +0 -64
- package/dist/tui/components/frame.d.ts +0 -8
- package/dist/tui/components/frame.js +0 -8
- package/dist/tui/components/status-bar.d.ts +0 -8
- package/dist/tui/components/status-bar.js +0 -8
- package/dist/tui/index.d.ts +0 -2
- package/dist/tui/index.js +0 -23
- package/dist/tui/keymap/use-global-keymap.d.ts +0 -19
- package/dist/tui/keymap/use-global-keymap.js +0 -82
- package/dist/tui/navigation/nav-items.d.ts +0 -3
- package/dist/tui/navigation/nav-items.js +0 -18
- package/dist/tui/screens/bridge.d.ts +0 -8
- package/dist/tui/screens/bridge.js +0 -19
- package/dist/tui/screens/decisions.d.ts +0 -5
- package/dist/tui/screens/decisions.js +0 -28
- package/dist/tui/screens/export.d.ts +0 -5
- package/dist/tui/screens/export.js +0 -16
- package/dist/tui/screens/home.d.ts +0 -5
- package/dist/tui/screens/home.js +0 -33
- package/dist/tui/screens/locked.d.ts +0 -5
- package/dist/tui/screens/locked.js +0 -9
- package/dist/tui/screens/specs.d.ts +0 -5
- package/dist/tui/screens/specs.js +0 -31
- package/dist/tui/services/client.d.ts +0 -1
- package/dist/tui/services/client.js +0 -18
- package/dist/tui/services/context-service.d.ts +0 -19
- package/dist/tui/services/context-service.js +0 -246
- package/dist/tui/shared-enums.d.ts +0 -16
- package/dist/tui/shared-enums.js +0 -19
- package/dist/tui/state/use-app-state.d.ts +0 -35
- package/dist/tui/state/use-app-state.js +0 -177
- package/dist/tui/types.d.ts +0 -77
- package/dist/tui/types.js +0 -2
- package/dist/tui-bundle.d.ts +0 -1
- package/dist/tui-bundle.js +0 -5
- package/dist/tui-entry.mjs +0 -1407
- package/dist/utils/cli-runtime.d.ts +0 -5
- package/dist/utils/cli-runtime.js +0 -22
- package/dist/utils/help-error.d.ts +0 -7
- package/dist/utils/help-error.js +0 -14
- package/dist/utils/interaction.d.ts +0 -19
- package/dist/utils/interaction.js +0 -93
- package/dist/utils/structured-log.d.ts +0 -7
- package/dist/utils/structured-log.js +0 -112
- package/dist/utils/trpc-url.d.ts +0 -4
- package/dist/utils/trpc-url.js +0 -15
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* auth login CLI command
|
|
4
|
-
*
|
|
5
|
-
* Authenticates the CLI user via the Keycloak Device Authorization Grant
|
|
6
|
-
* (RFC 8628) and persists credentials to ~/.spekn/credentials.json.
|
|
7
|
-
*
|
|
8
|
-
* Usage: spekn auth login [--keycloak-url <url>] [--realm <realm>]
|
|
9
|
-
*/
|
|
10
|
-
import type { DeviceFlowDeps, DeviceFlowResult } from "../../auth/device-flow.js";
|
|
11
|
-
import { CredentialsStore } from "../../auth/credentials-store.js";
|
|
12
|
-
interface CLIOptions {
|
|
13
|
-
keycloakUrl: string;
|
|
14
|
-
realm: string;
|
|
15
|
-
}
|
|
16
|
-
interface Deps {
|
|
17
|
-
stdout: {
|
|
18
|
-
write(s: string): void;
|
|
19
|
-
};
|
|
20
|
-
stderr: {
|
|
21
|
-
write(s: string): void;
|
|
22
|
-
};
|
|
23
|
-
performDeviceFlow: (keycloakUrl: string, realm: string, clientId: string, deps?: Partial<DeviceFlowDeps>) => Promise<DeviceFlowResult>;
|
|
24
|
-
credentialsStore: CredentialsStore;
|
|
25
|
-
}
|
|
26
|
-
declare function parseArgs(args: string[]): CLIOptions;
|
|
27
|
-
export declare function runAuthLoginCli(args: string[], deps?: Partial<Deps>): Promise<number>;
|
|
28
|
-
declare function main(): Promise<void>;
|
|
29
|
-
export { main, parseArgs };
|
|
30
|
-
export { decodeJwtPayload } from "../../auth/jwt.js";
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* auth login CLI command
|
|
5
|
-
*
|
|
6
|
-
* Authenticates the CLI user via the Keycloak Device Authorization Grant
|
|
7
|
-
* (RFC 8628) and persists credentials to ~/.spekn/credentials.json.
|
|
8
|
-
*
|
|
9
|
-
* Usage: spekn auth login [--keycloak-url <url>] [--realm <realm>]
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.decodeJwtPayload = void 0;
|
|
13
|
-
exports.runAuthLoginCli = runAuthLoginCli;
|
|
14
|
-
exports.main = main;
|
|
15
|
-
exports.parseArgs = parseArgs;
|
|
16
|
-
const client_1 = require("@trpc/client");
|
|
17
|
-
const device_flow_js_1 = require("../../auth/device-flow.js");
|
|
18
|
-
const credentials_store_js_1 = require("../../auth/credentials-store.js");
|
|
19
|
-
const session_js_1 = require("../../auth/session.js");
|
|
20
|
-
const help_error_1 = require("../../utils/help-error");
|
|
21
|
-
const trpc_url_1 = require("../../utils/trpc-url");
|
|
22
|
-
const structured_log_1 = require("../../utils/structured-log");
|
|
23
|
-
const defaultDeps = {
|
|
24
|
-
stdout: process.stdout,
|
|
25
|
-
stderr: process.stderr,
|
|
26
|
-
performDeviceFlow: device_flow_js_1.performDeviceFlow,
|
|
27
|
-
credentialsStore: new credentials_store_js_1.CredentialsStore(),
|
|
28
|
-
};
|
|
29
|
-
function resolveDeps(deps) {
|
|
30
|
-
return {
|
|
31
|
-
stdout: deps?.stdout ?? defaultDeps.stdout,
|
|
32
|
-
stderr: deps?.stderr ?? defaultDeps.stderr,
|
|
33
|
-
performDeviceFlow: deps?.performDeviceFlow ?? defaultDeps.performDeviceFlow,
|
|
34
|
-
credentialsStore: deps?.credentialsStore ?? defaultDeps.credentialsStore,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function printHelp(stderr) {
|
|
38
|
-
stderr.write(`
|
|
39
|
-
auth login - Authenticate the Spekn CLI via browser-based device flow
|
|
40
|
-
|
|
41
|
-
USAGE:
|
|
42
|
-
spekn auth login [options]
|
|
43
|
-
|
|
44
|
-
OPTIONS:
|
|
45
|
-
--keycloak-url <url> Keycloak base URL (default: KEYCLOAK_URL or https://auth.spekn.com)
|
|
46
|
-
--realm <realm> Keycloak realm name (default: KEYCLOAK_REALM or spekn)
|
|
47
|
-
--help Show this help message
|
|
48
|
-
|
|
49
|
-
ENVIRONMENT:
|
|
50
|
-
KEYCLOAK_URL Keycloak base URL
|
|
51
|
-
KEYCLOAK_REALM Keycloak realm name
|
|
52
|
-
|
|
53
|
-
EXAMPLES:
|
|
54
|
-
spekn auth login
|
|
55
|
-
spekn auth login --keycloak-url https://auth.example.com --realm my-realm
|
|
56
|
-
`);
|
|
57
|
-
}
|
|
58
|
-
function parseArgs(args) {
|
|
59
|
-
const keycloakUrlDefault = process.env["KEYCLOAK_URL"] ?? "https://auth.spekn.com";
|
|
60
|
-
const realmDefault = process.env["KEYCLOAK_REALM"] ?? "spekn";
|
|
61
|
-
let keycloakUrl = keycloakUrlDefault;
|
|
62
|
-
let realm = realmDefault;
|
|
63
|
-
for (let index = 0; index < args.length; index++) {
|
|
64
|
-
const arg = args[index];
|
|
65
|
-
if (arg === "--help" || arg === "-h") {
|
|
66
|
-
throw new help_error_1.HelpRequestedError();
|
|
67
|
-
}
|
|
68
|
-
if (arg === "--keycloak-url" && args[index + 1]) {
|
|
69
|
-
keycloakUrl = args[++index];
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (arg.startsWith("--keycloak-url=")) {
|
|
73
|
-
keycloakUrl = arg.slice("--keycloak-url=".length);
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
if (arg === "--realm" && args[index + 1]) {
|
|
77
|
-
realm = args[++index];
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
if (arg.startsWith("--realm=")) {
|
|
81
|
-
realm = arg.slice("--realm=".length);
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return { keycloakUrl, realm };
|
|
86
|
-
}
|
|
87
|
-
async function runAuthLoginCli(args, deps) {
|
|
88
|
-
const resolved = resolveDeps(deps);
|
|
89
|
-
try {
|
|
90
|
-
const options = parseArgs(args);
|
|
91
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
92
|
-
source: "cli.auth.login",
|
|
93
|
-
level: "info",
|
|
94
|
-
message: "Starting auth login",
|
|
95
|
-
details: { keycloakUrl: options.keycloakUrl, realm: options.realm },
|
|
96
|
-
});
|
|
97
|
-
const auth = await (0, session_js_1.ensureAuthenticated)({
|
|
98
|
-
keycloakUrl: options.keycloakUrl,
|
|
99
|
-
realm: options.realm,
|
|
100
|
-
credentialsStore: resolved.credentialsStore,
|
|
101
|
-
performDeviceFlow: resolved.performDeviceFlow,
|
|
102
|
-
stdout: resolved.stdout,
|
|
103
|
-
stderr: resolved.stderr,
|
|
104
|
-
forceDeviceFlow: true,
|
|
105
|
-
});
|
|
106
|
-
// Fetch the user's organizations from the API to resolve organizationId
|
|
107
|
-
const apiUrl = process.env.SPEKN_API_URL ?? "https://app.spekn.com";
|
|
108
|
-
const client = (0, client_1.createTRPCProxyClient)({
|
|
109
|
-
links: [
|
|
110
|
-
(0, client_1.httpBatchLink)({
|
|
111
|
-
url: (0, trpc_url_1.normalizeTrpcUrl)(apiUrl),
|
|
112
|
-
headers: {
|
|
113
|
-
authorization: `Bearer ${auth.accessToken}`,
|
|
114
|
-
},
|
|
115
|
-
}),
|
|
116
|
-
],
|
|
117
|
-
});
|
|
118
|
-
const organizationId = await (0, session_js_1.resolveOrganizationId)({
|
|
119
|
-
existingOrganizationId: auth.credentials.organizationId,
|
|
120
|
-
envOrganizationId: process.env.SPEKN_ORGANIZATION_ID,
|
|
121
|
-
fetchOrganizations: async () => (await client.organization.list.query()),
|
|
122
|
-
stdout: resolved.stdout,
|
|
123
|
-
});
|
|
124
|
-
const credentials = {
|
|
125
|
-
...auth.credentials,
|
|
126
|
-
organizationId,
|
|
127
|
-
};
|
|
128
|
-
resolved.credentialsStore.save(credentials);
|
|
129
|
-
resolved.stdout.write(`Logged in as ${auth.user.email}\n`);
|
|
130
|
-
if (organizationId) {
|
|
131
|
-
resolved.stdout.write(`Organization: ${organizationId}\n`);
|
|
132
|
-
}
|
|
133
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
134
|
-
source: "cli.auth.login",
|
|
135
|
-
level: "info",
|
|
136
|
-
message: "Auth login completed",
|
|
137
|
-
details: { email: auth.user.email, organizationId },
|
|
138
|
-
});
|
|
139
|
-
return 0;
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
if (error instanceof help_error_1.HelpRequestedError) {
|
|
143
|
-
printHelp(resolved.stderr);
|
|
144
|
-
return 0;
|
|
145
|
-
}
|
|
146
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
147
|
-
resolved.stderr.write(`Error: ${message}\n`);
|
|
148
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
149
|
-
source: "cli.auth.login",
|
|
150
|
-
level: "error",
|
|
151
|
-
message,
|
|
152
|
-
});
|
|
153
|
-
return 1;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
async function main() {
|
|
157
|
-
const exitCode = await runAuthLoginCli(process.argv.slice(2));
|
|
158
|
-
process.exit(exitCode);
|
|
159
|
-
}
|
|
160
|
-
if (require.main === module) {
|
|
161
|
-
void main();
|
|
162
|
-
}
|
|
163
|
-
var jwt_js_1 = require("../../auth/jwt.js");
|
|
164
|
-
Object.defineProperty(exports, "decodeJwtPayload", { enumerable: true, get: function () { return jwt_js_1.decodeJwtPayload; } });
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* auth logout CLI command
|
|
4
|
-
*
|
|
5
|
-
* Revokes the stored refresh token against Keycloak (best-effort) and then
|
|
6
|
-
* removes the local credentials file at ~/.spekn/credentials.json.
|
|
7
|
-
*
|
|
8
|
-
* Usage: spekn auth logout
|
|
9
|
-
*/
|
|
10
|
-
import { CredentialsStore } from "../../auth/credentials-store.js";
|
|
11
|
-
interface Deps {
|
|
12
|
-
stdout: {
|
|
13
|
-
write(s: string): void;
|
|
14
|
-
};
|
|
15
|
-
stderr: {
|
|
16
|
-
write(s: string): void;
|
|
17
|
-
};
|
|
18
|
-
credentialsStore: CredentialsStore;
|
|
19
|
-
/** POST to the Keycloak logout endpoint. Injected for testing. */
|
|
20
|
-
revokeToken: (logoutUrl: string, body: URLSearchParams) => Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
declare function parseArgs(args: string[]): void;
|
|
23
|
-
export declare function runAuthLogoutCli(args: string[], deps?: Partial<Deps>): Promise<number>;
|
|
24
|
-
declare function main(): Promise<void>;
|
|
25
|
-
export { main, parseArgs };
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* auth logout CLI command
|
|
5
|
-
*
|
|
6
|
-
* Revokes the stored refresh token against Keycloak (best-effort) and then
|
|
7
|
-
* removes the local credentials file at ~/.spekn/credentials.json.
|
|
8
|
-
*
|
|
9
|
-
* Usage: spekn auth logout
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.runAuthLogoutCli = runAuthLogoutCli;
|
|
13
|
-
exports.main = main;
|
|
14
|
-
exports.parseArgs = parseArgs;
|
|
15
|
-
const credentials_store_js_1 = require("../../auth/credentials-store.js");
|
|
16
|
-
const help_error_1 = require("../../utils/help-error");
|
|
17
|
-
const structured_log_1 = require("../../utils/structured-log");
|
|
18
|
-
/** Default revocation implementation — best-effort, ignores errors. */
|
|
19
|
-
async function defaultRevokeToken(logoutUrl, body) {
|
|
20
|
-
await fetch(logoutUrl, {
|
|
21
|
-
method: "POST",
|
|
22
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
23
|
-
body: body.toString(),
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
const defaultDeps = {
|
|
27
|
-
stdout: process.stdout,
|
|
28
|
-
stderr: process.stderr,
|
|
29
|
-
credentialsStore: new credentials_store_js_1.CredentialsStore(),
|
|
30
|
-
revokeToken: defaultRevokeToken,
|
|
31
|
-
};
|
|
32
|
-
function resolveDeps(deps) {
|
|
33
|
-
return {
|
|
34
|
-
stdout: deps?.stdout ?? defaultDeps.stdout,
|
|
35
|
-
stderr: deps?.stderr ?? defaultDeps.stderr,
|
|
36
|
-
credentialsStore: deps?.credentialsStore ?? defaultDeps.credentialsStore,
|
|
37
|
-
revokeToken: deps?.revokeToken ?? defaultDeps.revokeToken,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function printHelp(stderr) {
|
|
41
|
-
stderr.write(`
|
|
42
|
-
auth logout - Revoke the current session and remove stored credentials
|
|
43
|
-
|
|
44
|
-
USAGE:
|
|
45
|
-
spekn auth logout
|
|
46
|
-
|
|
47
|
-
OPTIONS:
|
|
48
|
-
--help Show this help message
|
|
49
|
-
|
|
50
|
-
EXAMPLES:
|
|
51
|
-
spekn auth logout
|
|
52
|
-
`);
|
|
53
|
-
}
|
|
54
|
-
function parseArgs(args) {
|
|
55
|
-
for (const arg of args) {
|
|
56
|
-
if (arg === "--help" || arg === "-h") {
|
|
57
|
-
throw new help_error_1.HelpRequestedError();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async function runAuthLogoutCli(args, deps) {
|
|
62
|
-
const resolved = resolveDeps(deps);
|
|
63
|
-
try {
|
|
64
|
-
parseArgs(args);
|
|
65
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
66
|
-
source: "cli.auth.logout",
|
|
67
|
-
level: "info",
|
|
68
|
-
message: "Starting auth logout",
|
|
69
|
-
});
|
|
70
|
-
const credentials = resolved.credentialsStore.load();
|
|
71
|
-
if (credentials !== null && credentials.refreshToken) {
|
|
72
|
-
const logoutUrl = `${credentials.keycloakUrl}/realms/${credentials.realm}/protocol/openid-connect/logout`;
|
|
73
|
-
const body = new URLSearchParams({
|
|
74
|
-
client_id: "spekn-cli",
|
|
75
|
-
refresh_token: credentials.refreshToken,
|
|
76
|
-
});
|
|
77
|
-
try {
|
|
78
|
-
await resolved.revokeToken(logoutUrl, body);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// Best-effort: ignore revocation errors so local credentials are always
|
|
82
|
-
// cleared even when Keycloak is unreachable.
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
resolved.credentialsStore.clear();
|
|
86
|
-
resolved.stdout.write("Logged out successfully.\n");
|
|
87
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
88
|
-
source: "cli.auth.logout",
|
|
89
|
-
level: "info",
|
|
90
|
-
message: "Auth logout completed",
|
|
91
|
-
});
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
if (error instanceof help_error_1.HelpRequestedError) {
|
|
96
|
-
printHelp(resolved.stderr);
|
|
97
|
-
return 0;
|
|
98
|
-
}
|
|
99
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
-
resolved.stderr.write(`Error: ${message}\n`);
|
|
101
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
102
|
-
source: "cli.auth.logout",
|
|
103
|
-
level: "error",
|
|
104
|
-
message,
|
|
105
|
-
});
|
|
106
|
-
return 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
async function main() {
|
|
110
|
-
const exitCode = await runAuthLogoutCli(process.argv.slice(2));
|
|
111
|
-
process.exit(exitCode);
|
|
112
|
-
}
|
|
113
|
-
if (require.main === module) {
|
|
114
|
-
void main();
|
|
115
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* auth status CLI command
|
|
4
|
-
*
|
|
5
|
-
* Displays the current authentication state: logged-in user, token expiry,
|
|
6
|
-
* and organization (if set). Attempts a silent token refresh when the stored
|
|
7
|
-
* token is expired but a refresh token is available.
|
|
8
|
-
*
|
|
9
|
-
* Usage: spekn auth status
|
|
10
|
-
*/
|
|
11
|
-
import { CredentialsStore } from "../../auth/credentials-store.js";
|
|
12
|
-
interface Deps {
|
|
13
|
-
stdout: {
|
|
14
|
-
write(s: string): void;
|
|
15
|
-
};
|
|
16
|
-
stderr: {
|
|
17
|
-
write(s: string): void;
|
|
18
|
-
};
|
|
19
|
-
credentialsStore: CredentialsStore;
|
|
20
|
-
}
|
|
21
|
-
declare function parseArgs(args: string[]): void;
|
|
22
|
-
export declare function runAuthStatusCli(args: string[], deps?: Partial<Deps>): Promise<number>;
|
|
23
|
-
declare function main(): Promise<void>;
|
|
24
|
-
export { main, parseArgs };
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* auth status CLI command
|
|
5
|
-
*
|
|
6
|
-
* Displays the current authentication state: logged-in user, token expiry,
|
|
7
|
-
* and organization (if set). Attempts a silent token refresh when the stored
|
|
8
|
-
* token is expired but a refresh token is available.
|
|
9
|
-
*
|
|
10
|
-
* Usage: spekn auth status
|
|
11
|
-
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.runAuthStatusCli = runAuthStatusCli;
|
|
14
|
-
exports.main = main;
|
|
15
|
-
exports.parseArgs = parseArgs;
|
|
16
|
-
const credentials_store_js_1 = require("../../auth/credentials-store.js");
|
|
17
|
-
const help_error_1 = require("../../utils/help-error");
|
|
18
|
-
const structured_log_1 = require("../../utils/structured-log");
|
|
19
|
-
const defaultDeps = {
|
|
20
|
-
stdout: process.stdout,
|
|
21
|
-
stderr: process.stderr,
|
|
22
|
-
credentialsStore: new credentials_store_js_1.CredentialsStore(),
|
|
23
|
-
};
|
|
24
|
-
function resolveDeps(deps) {
|
|
25
|
-
return {
|
|
26
|
-
stdout: deps?.stdout ?? defaultDeps.stdout,
|
|
27
|
-
stderr: deps?.stderr ?? defaultDeps.stderr,
|
|
28
|
-
credentialsStore: deps?.credentialsStore ?? defaultDeps.credentialsStore,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function printHelp(stderr) {
|
|
32
|
-
stderr.write(`
|
|
33
|
-
auth status - Show the current authentication status
|
|
34
|
-
|
|
35
|
-
USAGE:
|
|
36
|
-
spekn auth status
|
|
37
|
-
|
|
38
|
-
OPTIONS:
|
|
39
|
-
--help Show this help message
|
|
40
|
-
|
|
41
|
-
EXAMPLES:
|
|
42
|
-
spekn auth status
|
|
43
|
-
`);
|
|
44
|
-
}
|
|
45
|
-
function parseArgs(args) {
|
|
46
|
-
for (const arg of args) {
|
|
47
|
-
if (arg === "--help" || arg === "-h") {
|
|
48
|
-
throw new help_error_1.HelpRequestedError();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function runAuthStatusCli(args, deps) {
|
|
53
|
-
const resolved = resolveDeps(deps);
|
|
54
|
-
try {
|
|
55
|
-
parseArgs(args);
|
|
56
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
57
|
-
source: "cli.auth.status",
|
|
58
|
-
level: "info",
|
|
59
|
-
message: "Checking auth status",
|
|
60
|
-
});
|
|
61
|
-
const credentials = resolved.credentialsStore.load();
|
|
62
|
-
if (credentials === null) {
|
|
63
|
-
resolved.stdout.write("Not logged in. Run `spekn auth login` to authenticate.\n");
|
|
64
|
-
return 1;
|
|
65
|
-
}
|
|
66
|
-
const token = await resolved.credentialsStore.getValidToken();
|
|
67
|
-
if (token === null) {
|
|
68
|
-
resolved.stdout.write("Session expired. Run `spekn auth login` to re-authenticate.\n");
|
|
69
|
-
return 1;
|
|
70
|
-
}
|
|
71
|
-
// Reload credentials after a potential refresh so we report the updated
|
|
72
|
-
// expiry time rather than the stale one.
|
|
73
|
-
const fresh = resolved.credentialsStore.load() ?? credentials;
|
|
74
|
-
const email = fresh.user?.email ?? "unknown";
|
|
75
|
-
const expiresAt = new Date(fresh.expiresAt).toLocaleString();
|
|
76
|
-
const orgId = fresh.organizationId ?? "not set";
|
|
77
|
-
resolved.stdout.write(`Logged in as ${email}\n`);
|
|
78
|
-
resolved.stdout.write(`Token expires: ${expiresAt}\n`);
|
|
79
|
-
resolved.stdout.write(`Organization: ${orgId}\n`);
|
|
80
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
81
|
-
source: "cli.auth.status",
|
|
82
|
-
level: "info",
|
|
83
|
-
message: "Auth status available",
|
|
84
|
-
details: { email, organizationId: orgId },
|
|
85
|
-
});
|
|
86
|
-
return 0;
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
if (error instanceof help_error_1.HelpRequestedError) {
|
|
90
|
-
printHelp(resolved.stderr);
|
|
91
|
-
return 0;
|
|
92
|
-
}
|
|
93
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
-
resolved.stderr.write(`Error: ${message}\n`);
|
|
95
|
-
(0, structured_log_1.appendCliStructuredLog)({
|
|
96
|
-
source: "cli.auth.status",
|
|
97
|
-
level: "error",
|
|
98
|
-
message,
|
|
99
|
-
});
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async function main() {
|
|
104
|
-
const exitCode = await runAuthStatusCli(process.argv.slice(2));
|
|
105
|
-
process.exit(exitCode);
|
|
106
|
-
}
|
|
107
|
-
if (require.main === module) {
|
|
108
|
-
void main();
|
|
109
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* backlog-generate CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Auto-generate tasks from specification anchors.
|
|
6
|
-
*
|
|
7
|
-
* Usage: npm run backlog-generate <spec-file-path> [OPTIONS]
|
|
8
|
-
* Example: npm run backlog-generate specs/WORKFLOW.md --project-id=<uuid>
|
|
9
|
-
*/
|
|
10
|
-
declare function main(argv?: string[]): Promise<number>;
|
|
11
|
-
export { main };
|