workos 0.0.23 → 0.1.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/.claude-plugin/plugin.json +13 -0
- package/LICENSE +47 -0
- package/README.md +154 -1
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +163 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.config.d.ts +52 -0
- package/dist/cli.config.js +70 -0
- package/dist/cli.config.js.map +1 -0
- package/dist/package.json +87 -0
- package/dist/src/commands/install-skill.d.ts +20 -0
- package/dist/src/commands/install-skill.js +130 -0
- package/dist/src/commands/install-skill.js.map +1 -0
- package/dist/src/commands/install.d.ts +22 -0
- package/dist/src/commands/install.js +57 -0
- package/dist/src/commands/install.js.map +1 -0
- package/dist/src/commands/login.d.ts +1 -0
- package/dist/src/commands/login.js +141 -0
- package/dist/src/commands/login.js.map +1 -0
- package/dist/src/commands/logout.d.ts +1 -0
- package/dist/src/commands/logout.js +17 -0
- package/dist/src/commands/logout.js.map +1 -0
- package/dist/src/dashboard/components/AnimatedLogo.d.ts +8 -0
- package/dist/src/dashboard/components/AnimatedLogo.js +16 -0
- package/dist/src/dashboard/components/AnimatedLogo.js.map +1 -0
- package/dist/src/dashboard/components/CompletionView.d.ts +13 -0
- package/dist/src/dashboard/components/CompletionView.js +21 -0
- package/dist/src/dashboard/components/CompletionView.js.map +1 -0
- package/dist/src/dashboard/components/ConfirmPrompt.d.ts +9 -0
- package/dist/src/dashboard/components/ConfirmPrompt.js +25 -0
- package/dist/src/dashboard/components/ConfirmPrompt.js.map +1 -0
- package/dist/src/dashboard/components/CredentialsForm.d.ts +10 -0
- package/dist/src/dashboard/components/CredentialsForm.js +47 -0
- package/dist/src/dashboard/components/CredentialsForm.js.map +1 -0
- package/dist/src/dashboard/components/Dashboard.d.ts +3 -0
- package/dist/src/dashboard/components/Dashboard.js +100 -0
- package/dist/src/dashboard/components/Dashboard.js.map +1 -0
- package/dist/src/dashboard/components/DashboardLayout.d.ts +24 -0
- package/dist/src/dashboard/components/DashboardLayout.js +25 -0
- package/dist/src/dashboard/components/DashboardLayout.js.map +1 -0
- package/dist/src/dashboard/components/DiffPanel.d.ts +9 -0
- package/dist/src/dashboard/components/DiffPanel.js +136 -0
- package/dist/src/dashboard/components/DiffPanel.js.map +1 -0
- package/dist/src/dashboard/components/InlinePrompt.d.ts +8 -0
- package/dist/src/dashboard/components/InlinePrompt.js +19 -0
- package/dist/src/dashboard/components/InlinePrompt.js.map +1 -0
- package/dist/src/dashboard/components/OutputPanel.d.ts +10 -0
- package/dist/src/dashboard/components/OutputPanel.js +100 -0
- package/dist/src/dashboard/components/OutputPanel.js.map +1 -0
- package/dist/src/dashboard/components/Panel.d.ts +12 -0
- package/dist/src/dashboard/components/Panel.js +6 -0
- package/dist/src/dashboard/components/Panel.js.map +1 -0
- package/dist/src/dashboard/components/TextInput.d.ts +13 -0
- package/dist/src/dashboard/components/TextInput.js +57 -0
- package/dist/src/dashboard/components/TextInput.js.map +1 -0
- package/dist/src/dashboard/components/WelcomeArt.d.ts +2 -0
- package/dist/src/dashboard/components/WelcomeArt.js +9 -0
- package/dist/src/dashboard/components/WelcomeArt.js.map +1 -0
- package/dist/src/dashboard/hooks/useAnimation.d.ts +7 -0
- package/dist/src/dashboard/hooks/useAnimation.js +24 -0
- package/dist/src/dashboard/hooks/useAnimation.js.map +1 -0
- package/dist/src/dashboard/hooks/useKeyboard.d.ts +8 -0
- package/dist/src/dashboard/hooks/useKeyboard.js +18 -0
- package/dist/src/dashboard/hooks/useKeyboard.js.map +1 -0
- package/dist/src/dashboard/hooks/useTerminalSize.d.ts +8 -0
- package/dist/src/dashboard/hooks/useTerminalSize.js +23 -0
- package/dist/src/dashboard/hooks/useTerminalSize.js.map +1 -0
- package/dist/src/dashboard/index.d.ts +6 -0
- package/dist/src/dashboard/index.js +36 -0
- package/dist/src/dashboard/index.js.map +1 -0
- package/dist/src/dashboard/lib/diff-utils.d.ts +21 -0
- package/dist/src/dashboard/lib/diff-utils.js +271 -0
- package/dist/src/dashboard/lib/diff-utils.js.map +1 -0
- package/dist/src/dashboard/lib/logo-frames.d.ts +20 -0
- package/dist/src/dashboard/lib/logo-frames.js +109 -0
- package/dist/src/dashboard/lib/logo-frames.js.map +1 -0
- package/dist/src/dashboard/lib/welcome-art.d.ts +1 -0
- package/dist/src/dashboard/lib/welcome-art.js +5 -0
- package/dist/src/dashboard/lib/welcome-art.js.map +1 -0
- package/dist/src/dashboard/types.d.ts +5 -0
- package/dist/src/dashboard/types.js +2 -0
- package/dist/src/dashboard/types.js.map +1 -0
- package/dist/src/lib/__tests__/test-utils.d.ts +40 -0
- package/dist/src/lib/__tests__/test-utils.js +108 -0
- package/dist/src/lib/__tests__/test-utils.js.map +1 -0
- package/dist/src/lib/adapters/cli-adapter.d.ts +56 -0
- package/dist/src/lib/adapters/cli-adapter.js +318 -0
- package/dist/src/lib/adapters/cli-adapter.js.map +1 -0
- package/dist/src/lib/adapters/dashboard-adapter.d.ts +30 -0
- package/dist/src/lib/adapters/dashboard-adapter.js +97 -0
- package/dist/src/lib/adapters/dashboard-adapter.js.map +1 -0
- package/dist/src/lib/adapters/index.d.ts +3 -0
- package/dist/src/lib/adapters/index.js +3 -0
- package/dist/src/lib/adapters/index.js.map +1 -0
- package/dist/src/lib/adapters/types.d.ts +41 -0
- package/dist/src/lib/adapters/types.js +2 -0
- package/dist/src/lib/adapters/types.js.map +1 -0
- package/dist/src/lib/agent-interface.d.ts +75 -0
- package/dist/src/lib/agent-interface.js +563 -0
- package/dist/src/lib/agent-interface.js.map +1 -0
- package/dist/src/lib/agent-runner.d.ts +9 -0
- package/dist/src/lib/agent-runner.js +213 -0
- package/dist/src/lib/agent-runner.js.map +1 -0
- package/dist/src/lib/api.d.ts +25 -0
- package/dist/src/lib/api.js +120 -0
- package/dist/src/lib/api.js.map +1 -0
- package/dist/src/lib/config.d.ts +60 -0
- package/dist/src/lib/config.js +88 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/constants.d.ts +32 -0
- package/dist/src/lib/constants.js +53 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/credentials.d.ts +19 -0
- package/dist/src/lib/credentials.js +55 -0
- package/dist/src/lib/credentials.js.map +1 -0
- package/dist/src/lib/env-writer.d.ts +14 -0
- package/dist/src/lib/env-writer.js +39 -0
- package/dist/src/lib/env-writer.js.map +1 -0
- package/dist/src/lib/events.d.ts +114 -0
- package/dist/src/lib/events.js +19 -0
- package/dist/src/lib/events.js.map +1 -0
- package/dist/src/lib/framework-config.d.ts +108 -0
- package/dist/src/lib/framework-config.js +11 -0
- package/dist/src/lib/framework-config.js.map +1 -0
- package/dist/src/lib/helper-functions.d.ts +1 -0
- package/dist/src/lib/helper-functions.js +2 -0
- package/dist/src/lib/helper-functions.js.map +1 -0
- package/dist/src/lib/port-detection.d.ts +7 -0
- package/dist/src/lib/port-detection.js +112 -0
- package/dist/src/lib/port-detection.js.map +1 -0
- package/dist/src/lib/progress-tracker.d.ts +22 -0
- package/dist/src/lib/progress-tracker.js +47 -0
- package/dist/src/lib/progress-tracker.js.map +1 -0
- package/dist/src/lib/run-with-core.d.ts +2 -0
- package/dist/src/lib/run-with-core.js +266 -0
- package/dist/src/lib/run-with-core.js.map +1 -0
- package/dist/src/lib/safe-tools.d.ts +2 -0
- package/dist/src/lib/safe-tools.js +212 -0
- package/dist/src/lib/safe-tools.js.map +1 -0
- package/dist/src/lib/settings.d.ts +59 -0
- package/dist/src/lib/settings.js +36 -0
- package/dist/src/lib/settings.js.map +1 -0
- package/dist/src/lib/token-refresh.d.ts +12 -0
- package/dist/src/lib/token-refresh.js +26 -0
- package/dist/src/lib/token-refresh.js.map +1 -0
- package/dist/src/lib/validation/build-validator.d.ts +9 -0
- package/dist/src/lib/validation/build-validator.js +118 -0
- package/dist/src/lib/validation/build-validator.js.map +1 -0
- package/dist/src/lib/validation/index.d.ts +3 -0
- package/dist/src/lib/validation/index.js +3 -0
- package/dist/src/lib/validation/index.js.map +1 -0
- package/dist/src/lib/validation/types.d.ts +41 -0
- package/dist/src/lib/validation/types.js +2 -0
- package/dist/src/lib/validation/types.js.map +1 -0
- package/dist/src/lib/validation/validator.d.ts +6 -0
- package/dist/src/lib/validation/validator.js +647 -0
- package/dist/src/lib/validation/validator.js.map +1 -0
- package/dist/src/lib/wizard-core.d.ts +200 -0
- package/dist/src/lib/wizard-core.js +392 -0
- package/dist/src/lib/wizard-core.js.map +1 -0
- package/dist/src/lib/wizard-core.types.d.ts +73 -0
- package/dist/src/lib/wizard-core.types.js +2 -0
- package/dist/src/lib/wizard-core.types.js.map +1 -0
- package/dist/src/lib/workos-management.d.ts +32 -0
- package/dist/src/lib/workos-management.js +142 -0
- package/dist/src/lib/workos-management.js.map +1 -0
- package/dist/src/nextjs/nextjs-wizard-agent.d.ts +6 -0
- package/dist/src/nextjs/nextjs-wizard-agent.js +97 -0
- package/dist/src/nextjs/nextjs-wizard-agent.js.map +1 -0
- package/dist/src/nextjs/utils.d.ts +8 -0
- package/dist/src/nextjs/utils.js +53 -0
- package/dist/src/nextjs/utils.js.map +1 -0
- package/dist/src/react/react-wizard-agent.d.ts +2 -0
- package/dist/src/react/react-wizard-agent.js +47 -0
- package/dist/src/react/react-wizard-agent.js.map +1 -0
- package/dist/src/react-router/react-router-wizard-agent.d.ts +6 -0
- package/dist/src/react-router/react-router-wizard-agent.js +103 -0
- package/dist/src/react-router/react-router-wizard-agent.js.map +1 -0
- package/dist/src/react-router/utils.d.ts +19 -0
- package/dist/src/react-router/utils.js +210 -0
- package/dist/src/react-router/utils.js.map +1 -0
- package/dist/src/run.d.ts +24 -0
- package/dist/src/run.js +48 -0
- package/dist/src/run.js.map +1 -0
- package/dist/src/steps/add-or-update-environment-variables.d.ts +10 -0
- package/dist/src/steps/add-or-update-environment-variables.js +155 -0
- package/dist/src/steps/add-or-update-environment-variables.js.map +1 -0
- package/dist/src/steps/index.d.ts +3 -0
- package/dist/src/steps/index.js +4 -0
- package/dist/src/steps/index.js.map +1 -0
- package/dist/src/steps/run-prettier.d.ts +5 -0
- package/dist/src/steps/run-prettier.js +54 -0
- package/dist/src/steps/run-prettier.js.map +1 -0
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.d.ts +8 -0
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js +7 -0
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js.map +1 -0
- package/dist/src/steps/upload-environment-variables/index.d.ts +6 -0
- package/dist/src/steps/upload-environment-variables/index.js +57 -0
- package/dist/src/steps/upload-environment-variables/index.js.map +1 -0
- package/dist/src/steps/upload-environment-variables/providers/vercel.d.ts +14 -0
- package/dist/src/steps/upload-environment-variables/providers/vercel.js +104 -0
- package/dist/src/steps/upload-environment-variables/providers/vercel.js.map +1 -0
- package/dist/src/tanstack-start/tanstack-start-wizard-agent.d.ts +2 -0
- package/dist/src/tanstack-start/tanstack-start-wizard-agent.js +49 -0
- package/dist/src/tanstack-start/tanstack-start-wizard-agent.js.map +1 -0
- package/dist/src/telemetry.d.ts +2 -0
- package/dist/src/telemetry.js +29 -0
- package/dist/src/telemetry.js.map +1 -0
- package/dist/src/utils/analytics.d.ts +24 -0
- package/dist/src/utils/analytics.js +139 -0
- package/dist/src/utils/analytics.js.map +1 -0
- package/dist/src/utils/bash.d.ts +2 -0
- package/dist/src/utils/bash.js +17 -0
- package/dist/src/utils/bash.js.map +1 -0
- package/dist/src/utils/clack-utils.d.ts +93 -0
- package/dist/src/utils/clack-utils.js +397 -0
- package/dist/src/utils/clack-utils.js.map +1 -0
- package/dist/src/utils/clack.d.ts +5 -0
- package/dist/src/utils/clack.js +34 -0
- package/dist/src/utils/clack.js.map +1 -0
- package/dist/src/utils/cli-symbols.d.ts +32 -0
- package/dist/src/utils/cli-symbols.js +46 -0
- package/dist/src/utils/cli-symbols.js.map +1 -0
- package/dist/src/utils/debug.d.ts +7 -0
- package/dist/src/utils/debug.js +88 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/env-parser.d.ts +5 -0
- package/dist/src/utils/env-parser.js +18 -0
- package/dist/src/utils/env-parser.js.map +1 -0
- package/dist/src/utils/environment.d.ts +4 -0
- package/dist/src/utils/environment.js +69 -0
- package/dist/src/utils/environment.js.map +1 -0
- package/dist/src/utils/errors.d.ts +3 -0
- package/dist/src/utils/errors.js +7 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/logging.d.ts +9 -0
- package/dist/src/utils/logging.js +36 -0
- package/dist/src/utils/logging.js.map +1 -0
- package/dist/src/utils/package-json.d.ts +25 -0
- package/dist/src/utils/package-json.js +21 -0
- package/dist/src/utils/package-json.js.map +1 -0
- package/dist/src/utils/package-manager.d.ts +21 -0
- package/dist/src/utils/package-manager.js +167 -0
- package/dist/src/utils/package-manager.js.map +1 -0
- package/dist/src/utils/redact.d.ts +5 -0
- package/dist/src/utils/redact.js +29 -0
- package/dist/src/utils/redact.js.map +1 -0
- package/dist/src/utils/semver.d.ts +10 -0
- package/dist/src/utils/semver.js +43 -0
- package/dist/src/utils/semver.js.map +1 -0
- package/dist/src/utils/string.d.ts +1 -0
- package/dist/src/utils/string.js +6 -0
- package/dist/src/utils/string.js.map +1 -0
- package/dist/src/utils/telemetry-client.d.ts +15 -0
- package/dist/src/utils/telemetry-client.js +57 -0
- package/dist/src/utils/telemetry-client.js.map +1 -0
- package/dist/src/utils/telemetry-types.d.ts +51 -0
- package/dist/src/utils/telemetry-types.js +6 -0
- package/dist/src/utils/telemetry-types.js.map +1 -0
- package/dist/src/utils/types.d.ts +80 -0
- package/dist/src/utils/types.js +2 -0
- package/dist/src/utils/types.js.map +1 -0
- package/dist/src/utils/urls.d.ts +7 -0
- package/dist/src/utils/urls.js +8 -0
- package/dist/src/utils/urls.js.map +1 -0
- package/dist/src/utils/vendor/is-unicorn-supported.d.ts +1 -0
- package/dist/src/utils/vendor/is-unicorn-supported.js +21 -0
- package/dist/src/utils/vendor/is-unicorn-supported.js.map +1 -0
- package/dist/src/vanilla-js/vanilla-js-wizard-agent.d.ts +2 -0
- package/dist/src/vanilla-js/vanilla-js-wizard-agent.js +47 -0
- package/dist/src/vanilla-js/vanilla-js-wizard-agent.js.map +1 -0
- package/package.json +76 -84
- package/skills/workos-authkit-base/SKILL.md +113 -0
- package/skills/workos-authkit-nextjs/SKILL.md +115 -0
- package/skills/workos-authkit-react/SKILL.md +91 -0
- package/skills/workos-authkit-react-router/SKILL.md +106 -0
- package/skills/workos-authkit-tanstack-start/SKILL.md +104 -0
- package/skills/workos-authkit-vanilla-js/SKILL.md +81 -0
- package/build/apps/index.js +0 -50
- package/build/apps/slack.js +0 -151
- package/build/cli.js +0 -42
- package/build/config.js +0 -34
- package/build/dev.js +0 -5
- package/build/enable-api-access.png +0 -0
- package/build/groups.js +0 -480
- package/build/index.js +0 -3
- package/build/info.js +0 -69
- package/build/login.js +0 -161
- package/build/main.js +0 -214
- package/build/users.js +0 -402
- package/build/util.js +0 -157
- package/coverage/clover.xml +0 -66
- package/coverage/coverage-final.json +0 -4
- package/coverage/lcov-report/base.css +0 -212
- package/coverage/lcov-report/cli.ts.html +0 -329
- package/coverage/lcov-report/config.ts.html +0 -152
- package/coverage/lcov-report/index.html +0 -119
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -1
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -158
- package/coverage/lcov-report/util.ts.html +0 -350
- package/coverage/lcov.info +0 -121
- package/package-lock.json +0 -7617
- package/tests/util.test.ts +0 -35
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { mkdir, copyFile, readdir } from 'fs/promises';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
export function createAgents(home) {
|
|
8
|
+
return {
|
|
9
|
+
'claude-code': {
|
|
10
|
+
name: 'claude-code',
|
|
11
|
+
displayName: 'Claude Code',
|
|
12
|
+
globalSkillsDir: join(home, '.claude/skills'),
|
|
13
|
+
detect: () => existsSync(join(home, '.claude')),
|
|
14
|
+
},
|
|
15
|
+
codex: {
|
|
16
|
+
name: 'codex',
|
|
17
|
+
displayName: 'Codex',
|
|
18
|
+
globalSkillsDir: join(home, '.codex/skills'),
|
|
19
|
+
detect: () => existsSync(join(home, '.codex')),
|
|
20
|
+
},
|
|
21
|
+
cursor: {
|
|
22
|
+
name: 'cursor',
|
|
23
|
+
displayName: 'Cursor',
|
|
24
|
+
globalSkillsDir: join(home, '.cursor/skills'),
|
|
25
|
+
detect: () => existsSync(join(home, '.cursor')),
|
|
26
|
+
},
|
|
27
|
+
goose: {
|
|
28
|
+
name: 'goose',
|
|
29
|
+
displayName: 'Goose',
|
|
30
|
+
globalSkillsDir: join(home, '.config/goose/skills'),
|
|
31
|
+
detect: () => existsSync(join(home, '.config/goose')),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function getSkillsDir() {
|
|
36
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
37
|
+
// From dist/src/commands/install-skill.js -> skills/
|
|
38
|
+
return join(dirname(currentFile), '..', '..', '..', 'skills');
|
|
39
|
+
}
|
|
40
|
+
export async function discoverSkills(skillsDir) {
|
|
41
|
+
const entries = await readdir(skillsDir, { withFileTypes: true });
|
|
42
|
+
return entries.filter((e) => e.isDirectory() && existsSync(join(skillsDir, e.name, 'SKILL.md'))).map((e) => e.name);
|
|
43
|
+
}
|
|
44
|
+
export function detectAgents(agents, filter) {
|
|
45
|
+
const detected = [];
|
|
46
|
+
for (const [key, config] of Object.entries(agents)) {
|
|
47
|
+
if (filter && !filter.includes(key))
|
|
48
|
+
continue;
|
|
49
|
+
if (config.detect()) {
|
|
50
|
+
detected.push(config);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return detected;
|
|
54
|
+
}
|
|
55
|
+
export async function installSkill(skillsDir, skillName, agent) {
|
|
56
|
+
const sourceFile = join(skillsDir, skillName, 'SKILL.md');
|
|
57
|
+
const targetDir = join(agent.globalSkillsDir, skillName);
|
|
58
|
+
const targetFile = join(targetDir, 'SKILL.md');
|
|
59
|
+
try {
|
|
60
|
+
await mkdir(targetDir, { recursive: true });
|
|
61
|
+
await copyFile(sourceFile, targetFile);
|
|
62
|
+
return { success: true };
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export async function runInstallSkill(options) {
|
|
72
|
+
const home = homedir();
|
|
73
|
+
const agents = createAgents(home);
|
|
74
|
+
const skillsDir = getSkillsDir();
|
|
75
|
+
const skills = await discoverSkills(skillsDir);
|
|
76
|
+
if (options.list) {
|
|
77
|
+
console.log(chalk.bold('\nAvailable Skills:\n'));
|
|
78
|
+
for (const skill of skills) {
|
|
79
|
+
console.log(` ${chalk.cyan(skill)}`);
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const targetSkills = options.skill ? skills.filter((s) => options.skill.includes(s)) : skills;
|
|
85
|
+
if (targetSkills.length === 0) {
|
|
86
|
+
console.error(chalk.red('No matching skills found.'));
|
|
87
|
+
console.log('Available skills:', skills.join(', '));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
const targetAgents = detectAgents(agents, options.agent);
|
|
91
|
+
if (targetAgents.length === 0) {
|
|
92
|
+
if (options.agent) {
|
|
93
|
+
console.error(chalk.red('Specified agents not found.'));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.error(chalk.red('No coding agents detected.'));
|
|
97
|
+
}
|
|
98
|
+
console.log('Supported agents:', Object.keys(agents).join(', '));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
console.log(chalk.bold('\nInstalling skills...\n'));
|
|
102
|
+
const results = [];
|
|
103
|
+
for (const skill of targetSkills) {
|
|
104
|
+
for (const agent of targetAgents) {
|
|
105
|
+
const result = await installSkill(skillsDir, skill, agent);
|
|
106
|
+
results.push({
|
|
107
|
+
skill,
|
|
108
|
+
agent: agent.displayName,
|
|
109
|
+
...result,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const successful = results.filter((r) => r.success);
|
|
114
|
+
const failed = results.filter((r) => !r.success);
|
|
115
|
+
if (successful.length > 0) {
|
|
116
|
+
console.log(chalk.green(`✓ Installed ${successful.length} skill(s):\n`));
|
|
117
|
+
for (const r of successful) {
|
|
118
|
+
console.log(` ${chalk.cyan(r.skill)} → ${chalk.dim(r.agent)}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (failed.length > 0) {
|
|
122
|
+
console.log(chalk.red(`\n✗ Failed to install ${failed.length}:\n`));
|
|
123
|
+
for (const r of failed) {
|
|
124
|
+
console.log(` ${r.skill} → ${r.agent}: ${chalk.dim(r.error)}`);
|
|
125
|
+
}
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
console.log(chalk.green('\nDone!'));
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=install-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-skill.js","sourceRoot":"","sources":["../../../src/commands/install-skill.ts"],"names":[],"mappings":"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","sourcesContent":["import { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { existsSync } from 'fs';\nimport { mkdir, copyFile, readdir } from 'fs/promises';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\n\nexport interface AgentConfig {\n name: string;\n displayName: string;\n globalSkillsDir: string;\n detect: () => boolean;\n}\n\nexport function createAgents(home: string): Record<string, AgentConfig> {\n return {\n 'claude-code': {\n name: 'claude-code',\n displayName: 'Claude Code',\n globalSkillsDir: join(home, '.claude/skills'),\n detect: () => existsSync(join(home, '.claude')),\n },\n codex: {\n name: 'codex',\n displayName: 'Codex',\n globalSkillsDir: join(home, '.codex/skills'),\n detect: () => existsSync(join(home, '.codex')),\n },\n cursor: {\n name: 'cursor',\n displayName: 'Cursor',\n globalSkillsDir: join(home, '.cursor/skills'),\n detect: () => existsSync(join(home, '.cursor')),\n },\n goose: {\n name: 'goose',\n displayName: 'Goose',\n globalSkillsDir: join(home, '.config/goose/skills'),\n detect: () => existsSync(join(home, '.config/goose')),\n },\n };\n}\n\nexport interface InstallSkillOptions {\n list?: boolean;\n skill?: string[];\n agent?: string[];\n}\n\nexport function getSkillsDir(): string {\n const currentFile = fileURLToPath(import.meta.url);\n // From dist/src/commands/install-skill.js -> skills/\n return join(dirname(currentFile), '..', '..', '..', 'skills');\n}\n\nexport async function discoverSkills(skillsDir: string): Promise<string[]> {\n const entries = await readdir(skillsDir, { withFileTypes: true });\n\n return entries.filter((e) => e.isDirectory() && existsSync(join(skillsDir, e.name, 'SKILL.md'))).map((e) => e.name);\n}\n\nexport function detectAgents(agents: Record<string, AgentConfig>, filter?: string[]): AgentConfig[] {\n const detected: AgentConfig[] = [];\n\n for (const [key, config] of Object.entries(agents)) {\n if (filter && !filter.includes(key)) continue;\n if (config.detect()) {\n detected.push(config);\n }\n }\n\n return detected;\n}\n\nexport async function installSkill(\n skillsDir: string,\n skillName: string,\n agent: AgentConfig,\n): Promise<{ success: boolean; error?: string }> {\n const sourceFile = join(skillsDir, skillName, 'SKILL.md');\n const targetDir = join(agent.globalSkillsDir, skillName);\n const targetFile = join(targetDir, 'SKILL.md');\n\n try {\n await mkdir(targetDir, { recursive: true });\n await copyFile(sourceFile, targetFile);\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n}\n\nexport async function runInstallSkill(options: InstallSkillOptions): Promise<void> {\n const home = homedir();\n const agents = createAgents(home);\n const skillsDir = getSkillsDir();\n const skills = await discoverSkills(skillsDir);\n\n if (options.list) {\n console.log(chalk.bold('\\nAvailable Skills:\\n'));\n for (const skill of skills) {\n console.log(` ${chalk.cyan(skill)}`);\n }\n console.log();\n return;\n }\n\n const targetSkills = options.skill ? skills.filter((s) => options.skill!.includes(s)) : skills;\n\n if (targetSkills.length === 0) {\n console.error(chalk.red('No matching skills found.'));\n console.log('Available skills:', skills.join(', '));\n process.exit(1);\n }\n\n const targetAgents = detectAgents(agents, options.agent);\n\n if (targetAgents.length === 0) {\n if (options.agent) {\n console.error(chalk.red('Specified agents not found.'));\n } else {\n console.error(chalk.red('No coding agents detected.'));\n }\n console.log('Supported agents:', Object.keys(agents).join(', '));\n process.exit(1);\n }\n\n console.log(chalk.bold('\\nInstalling skills...\\n'));\n\n const results: Array<{\n skill: string;\n agent: string;\n success: boolean;\n error?: string;\n }> = [];\n\n for (const skill of targetSkills) {\n for (const agent of targetAgents) {\n const result = await installSkill(skillsDir, skill, agent);\n results.push({\n skill,\n agent: agent.displayName,\n ...result,\n });\n }\n }\n\n const successful = results.filter((r) => r.success);\n const failed = results.filter((r) => !r.success);\n\n if (successful.length > 0) {\n console.log(chalk.green(`✓ Installed ${successful.length} skill(s):\\n`));\n for (const r of successful) {\n console.log(` ${chalk.cyan(r.skill)} → ${chalk.dim(r.agent)}`);\n }\n }\n\n if (failed.length > 0) {\n console.log(chalk.red(`\\n✗ Failed to install ${failed.length}:\\n`));\n for (const r of failed) {\n console.log(` ${r.skill} → ${r.agent}: ${chalk.dim(r.error)}`);\n }\n process.exit(1);\n }\n\n console.log(chalk.green('\\nDone!'));\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ArgumentsCamelCase } from 'yargs';
|
|
2
|
+
interface InstallArgs {
|
|
3
|
+
debug?: boolean;
|
|
4
|
+
local?: boolean;
|
|
5
|
+
ci?: boolean;
|
|
6
|
+
skipAuth?: boolean;
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
clientId?: string;
|
|
9
|
+
inspect?: boolean;
|
|
10
|
+
homepageUrl?: string;
|
|
11
|
+
redirectUri?: string;
|
|
12
|
+
noValidate?: boolean;
|
|
13
|
+
installDir?: string;
|
|
14
|
+
integration?: string;
|
|
15
|
+
forceInstall?: boolean;
|
|
16
|
+
dashboard?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Handle install command execution.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleInstall(argv: ArgumentsCamelCase<InstallArgs>): Promise<void>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { runWizard } from '../run.js';
|
|
2
|
+
import { isNonInteractiveEnvironment } from '../utils/environment.js';
|
|
3
|
+
import clack from '../utils/clack.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
/**
|
|
6
|
+
* Handle install command execution.
|
|
7
|
+
*/
|
|
8
|
+
export async function handleInstall(argv) {
|
|
9
|
+
const options = { ...argv };
|
|
10
|
+
// CI mode validation
|
|
11
|
+
if (options.ci) {
|
|
12
|
+
if (!options.apiKey) {
|
|
13
|
+
clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));
|
|
14
|
+
clack.log.error('CI mode requires --api-key (WorkOS API key sk_xxx)');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
if (!options.clientId) {
|
|
18
|
+
clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));
|
|
19
|
+
clack.log.error('CI mode requires --client-id (WorkOS Client ID client_xxx)');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
if (!options.installDir) {
|
|
23
|
+
clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));
|
|
24
|
+
clack.log.error('CI mode requires --install-dir (directory to install WorkOS AuthKit in)');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else if (isNonInteractiveEnvironment()) {
|
|
29
|
+
clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));
|
|
30
|
+
clack.log.error('This installer requires an interactive terminal (TTY) to run.\n' +
|
|
31
|
+
'It appears you are running in a non-interactive environment.\n' +
|
|
32
|
+
'Please run the wizard in an interactive terminal.\n\n' +
|
|
33
|
+
'For CI/CD environments, use --ci mode:\n' +
|
|
34
|
+
' wizard install --ci --api-key sk_xxx --client-id client_xxx');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
await runWizard(options);
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const { getLogFilePath } = await import('../utils/debug.js');
|
|
43
|
+
const logPath = getLogFilePath();
|
|
44
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
45
|
+
// Always show the error message
|
|
46
|
+
clack.log.error(errorMessage);
|
|
47
|
+
// Show stack trace in debug mode
|
|
48
|
+
if (options.debug && err instanceof Error && err.stack) {
|
|
49
|
+
console.error(err.stack);
|
|
50
|
+
}
|
|
51
|
+
if (logPath) {
|
|
52
|
+
clack.log.info(`Debug logs: ${logPath}`);
|
|
53
|
+
}
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/commands/install.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAoB1B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAqC;IACvE,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAE5B,qBAAqB;IACrB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QACf,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,IAAI,2BAA2B,EAAE,EAAE,CAAC;QACzC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACpD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,iEAAiE;YAC/D,gEAAgE;YAChE,uDAAuD;YACvD,0CAA0C;YAC1C,+DAA+D,CAClE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAmC,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEtE,gCAAgC;QAChC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAE9B,iCAAiC;QACjC,IAAI,OAAO,CAAC,KAAK,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACvD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC","sourcesContent":["import type { WizardOptions } from '../utils/types.js';\nimport { runWizard } from '../run.js';\nimport { isNonInteractiveEnvironment } from '../utils/environment.js';\nimport clack from '../utils/clack.js';\nimport chalk from 'chalk';\nimport type { ArgumentsCamelCase } from 'yargs';\n\ninterface InstallArgs {\n debug?: boolean;\n local?: boolean;\n ci?: boolean;\n skipAuth?: boolean;\n apiKey?: string;\n clientId?: string;\n inspect?: boolean;\n homepageUrl?: string;\n redirectUri?: string;\n noValidate?: boolean;\n installDir?: string;\n integration?: string;\n forceInstall?: boolean;\n dashboard?: boolean;\n}\n\n/**\n * Handle install command execution.\n */\nexport async function handleInstall(argv: ArgumentsCamelCase<InstallArgs>): Promise<void> {\n const options = { ...argv };\n\n // CI mode validation\n if (options.ci) {\n if (!options.apiKey) {\n clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));\n clack.log.error('CI mode requires --api-key (WorkOS API key sk_xxx)');\n process.exit(1);\n }\n if (!options.clientId) {\n clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));\n clack.log.error('CI mode requires --client-id (WorkOS Client ID client_xxx)');\n process.exit(1);\n }\n if (!options.installDir) {\n clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));\n clack.log.error('CI mode requires --install-dir (directory to install WorkOS AuthKit in)');\n process.exit(1);\n }\n } else if (isNonInteractiveEnvironment()) {\n clack.intro(chalk.inverse('WorkOS AuthKit Wizard'));\n clack.log.error(\n 'This installer requires an interactive terminal (TTY) to run.\\n' +\n 'It appears you are running in a non-interactive environment.\\n' +\n 'Please run the wizard in an interactive terminal.\\n\\n' +\n 'For CI/CD environments, use --ci mode:\\n' +\n ' wizard install --ci --api-key sk_xxx --client-id client_xxx',\n );\n process.exit(1);\n }\n\n try {\n await runWizard(options as unknown as WizardOptions);\n process.exit(0);\n } catch (err) {\n const { getLogFilePath } = await import('../utils/debug.js');\n const logPath = getLogFilePath();\n const errorMessage = err instanceof Error ? err.message : String(err);\n\n // Always show the error message\n clack.log.error(errorMessage);\n\n // Show stack trace in debug mode\n if (options.debug && err instanceof Error && err.stack) {\n console.error(err.stack);\n }\n if (logPath) {\n clack.log.info(`Debug logs: ${logPath}`);\n }\n process.exit(1);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runLogin(): Promise<void>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import open from 'opn';
|
|
2
|
+
import clack from '../utils/clack.js';
|
|
3
|
+
import { saveCredentials, getCredentials, getAccessToken } from '../lib/credentials.js';
|
|
4
|
+
import { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse JWT payload
|
|
7
|
+
*/
|
|
8
|
+
function parseJwt(token) {
|
|
9
|
+
try {
|
|
10
|
+
const parts = token.split('.');
|
|
11
|
+
if (parts.length !== 3)
|
|
12
|
+
return null;
|
|
13
|
+
return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extract expiry time from JWT token
|
|
21
|
+
*/
|
|
22
|
+
function getJwtExpiry(token) {
|
|
23
|
+
const payload = parseJwt(token);
|
|
24
|
+
if (!payload || typeof payload.exp !== 'number')
|
|
25
|
+
return null;
|
|
26
|
+
return payload.exp * 1000;
|
|
27
|
+
}
|
|
28
|
+
const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
29
|
+
/**
|
|
30
|
+
* Get Connect OAuth endpoints from AuthKit domain
|
|
31
|
+
*/
|
|
32
|
+
function getConnectEndpoints() {
|
|
33
|
+
const domain = getAuthkitDomain();
|
|
34
|
+
return {
|
|
35
|
+
deviceAuthorization: `${domain}/oauth2/device_authorization`,
|
|
36
|
+
token: `${domain}/oauth2/token`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function sleep(ms) {
|
|
40
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
export async function runLogin() {
|
|
43
|
+
const clientId = getCliAuthClientId();
|
|
44
|
+
if (!clientId) {
|
|
45
|
+
clack.log.error('CLI auth not configured. Set WORKOS_CLI_CLIENT_ID environment variable.');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
if (getAccessToken()) {
|
|
49
|
+
const creds = getCredentials();
|
|
50
|
+
clack.log.info(`Already logged in as ${creds?.email ?? 'unknown'}`);
|
|
51
|
+
clack.log.info('Run `wizard logout` to log out');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
clack.log.step('Starting authentication...');
|
|
55
|
+
const endpoints = getConnectEndpoints();
|
|
56
|
+
const authResponse = await fetch(endpoints.deviceAuthorization, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
60
|
+
},
|
|
61
|
+
body: new URLSearchParams({
|
|
62
|
+
client_id: clientId,
|
|
63
|
+
scope: 'openid email',
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
if (!authResponse.ok) {
|
|
67
|
+
clack.log.error(`Failed to start authentication: ${authResponse.status}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const deviceAuth = (await authResponse.json());
|
|
71
|
+
const pollIntervalMs = (deviceAuth.interval || 5) * 1000;
|
|
72
|
+
clack.log.info(`\nOpen this URL in your browser:\n`);
|
|
73
|
+
console.log(` ${deviceAuth.verification_uri}`);
|
|
74
|
+
console.log(`\nEnter code: ${deviceAuth.user_code}\n`);
|
|
75
|
+
try {
|
|
76
|
+
open(deviceAuth.verification_uri_complete);
|
|
77
|
+
clack.log.info('Browser opened automatically');
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// User can open manually
|
|
81
|
+
}
|
|
82
|
+
const spinner = clack.spinner();
|
|
83
|
+
spinner.start('Waiting for authentication...');
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
let currentInterval = pollIntervalMs;
|
|
86
|
+
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
87
|
+
await sleep(currentInterval);
|
|
88
|
+
try {
|
|
89
|
+
const tokenResponse = await fetch(endpoints.token, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: {
|
|
92
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
93
|
+
},
|
|
94
|
+
body: new URLSearchParams({
|
|
95
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
96
|
+
device_code: deviceAuth.device_code,
|
|
97
|
+
client_id: clientId,
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
const data = await tokenResponse.json();
|
|
101
|
+
if (tokenResponse.ok) {
|
|
102
|
+
const result = data;
|
|
103
|
+
// Parse user info from id_token JWT
|
|
104
|
+
const idTokenPayload = parseJwt(result.id_token);
|
|
105
|
+
const userId = idTokenPayload?.sub || 'unknown';
|
|
106
|
+
const email = idTokenPayload?.email || undefined;
|
|
107
|
+
// Extract actual expiry from access token JWT, fallback to response or 15 min
|
|
108
|
+
const jwtExpiry = getJwtExpiry(result.access_token);
|
|
109
|
+
const expiresAt = jwtExpiry ?? (result.expires_in ? Date.now() + result.expires_in * 1000 : Date.now() + 15 * 60 * 1000);
|
|
110
|
+
const expiresInSec = Math.round((expiresAt - Date.now()) / 1000);
|
|
111
|
+
saveCredentials({
|
|
112
|
+
accessToken: result.access_token,
|
|
113
|
+
expiresAt,
|
|
114
|
+
userId,
|
|
115
|
+
email,
|
|
116
|
+
});
|
|
117
|
+
spinner.stop('Authentication successful!');
|
|
118
|
+
clack.log.success(`Logged in as ${email || userId}`);
|
|
119
|
+
clack.log.info(`Token expires in ${expiresInSec} seconds`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const errorData = data;
|
|
123
|
+
if (errorData.error === 'authorization_pending')
|
|
124
|
+
continue;
|
|
125
|
+
if (errorData.error === 'slow_down') {
|
|
126
|
+
currentInterval += 5000;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
spinner.stop('Authentication failed');
|
|
130
|
+
clack.log.error(`Authentication error: ${errorData.error}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
spinner.stop('Authentication timed out');
|
|
138
|
+
clack.log.error('Authentication timed out. Please try again.');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import open from 'opn';\nimport clack from '../utils/clack.js';\nimport { saveCredentials, getCredentials, getAccessToken } from '../lib/credentials.js';\nimport { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';\n\n/**\n * Parse JWT payload\n */\nfunction parseJwt(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiry time from JWT token\n */\nfunction getJwtExpiry(token: string): number | null {\n const payload = parseJwt(token);\n if (!payload || typeof payload.exp !== 'number') return null;\n return payload.exp * 1000;\n}\n\nconst POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Get Connect OAuth endpoints from AuthKit domain\n */\nfunction getConnectEndpoints() {\n const domain = getAuthkitDomain();\n return {\n deviceAuthorization: `${domain}/oauth2/device_authorization`,\n token: `${domain}/oauth2/token`,\n };\n}\n\ninterface DeviceAuthResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n}\n\ninterface ConnectTokenResponse {\n access_token: string;\n id_token: string;\n token_type: string;\n expires_in: number;\n refresh_token?: string;\n}\n\ninterface AuthErrorResponse {\n error: string;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function runLogin(): Promise<void> {\n const clientId = getCliAuthClientId();\n\n if (!clientId) {\n clack.log.error('CLI auth not configured. Set WORKOS_CLI_CLIENT_ID environment variable.');\n process.exit(1);\n }\n\n if (getAccessToken()) {\n const creds = getCredentials();\n clack.log.info(`Already logged in as ${creds?.email ?? 'unknown'}`);\n clack.log.info('Run `wizard logout` to log out');\n return;\n }\n\n clack.log.step('Starting authentication...');\n\n const endpoints = getConnectEndpoints();\n\n const authResponse = await fetch(endpoints.deviceAuthorization, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n client_id: clientId,\n scope: 'openid email',\n }),\n });\n\n if (!authResponse.ok) {\n clack.log.error(`Failed to start authentication: ${authResponse.status}`);\n process.exit(1);\n }\n\n const deviceAuth = (await authResponse.json()) as DeviceAuthResponse;\n const pollIntervalMs = (deviceAuth.interval || 5) * 1000;\n\n clack.log.info(`\\nOpen this URL in your browser:\\n`);\n console.log(` ${deviceAuth.verification_uri}`);\n console.log(`\\nEnter code: ${deviceAuth.user_code}\\n`);\n\n try {\n open(deviceAuth.verification_uri_complete);\n clack.log.info('Browser opened automatically');\n } catch {\n // User can open manually\n }\n\n const spinner = clack.spinner();\n spinner.start('Waiting for authentication...');\n\n const startTime = Date.now();\n let currentInterval = pollIntervalMs;\n\n while (Date.now() - startTime < POLL_TIMEOUT_MS) {\n await sleep(currentInterval);\n\n try {\n const tokenResponse = await fetch(endpoints.token, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceAuth.device_code,\n client_id: clientId,\n }),\n });\n\n const data = await tokenResponse.json();\n\n if (tokenResponse.ok) {\n const result = data as ConnectTokenResponse;\n\n // Parse user info from id_token JWT\n const idTokenPayload = parseJwt(result.id_token);\n const userId = (idTokenPayload?.sub as string) || 'unknown';\n const email = (idTokenPayload?.email as string) || undefined;\n\n // Extract actual expiry from access token JWT, fallback to response or 15 min\n const jwtExpiry = getJwtExpiry(result.access_token);\n const expiresAt =\n jwtExpiry ?? (result.expires_in ? Date.now() + result.expires_in * 1000 : Date.now() + 15 * 60 * 1000);\n\n const expiresInSec = Math.round((expiresAt - Date.now()) / 1000);\n\n saveCredentials({\n accessToken: result.access_token,\n expiresAt,\n userId,\n email,\n });\n\n spinner.stop('Authentication successful!');\n clack.log.success(`Logged in as ${email || userId}`);\n clack.log.info(`Token expires in ${expiresInSec} seconds`);\n return;\n }\n\n const errorData = data as AuthErrorResponse;\n if (errorData.error === 'authorization_pending') continue;\n if (errorData.error === 'slow_down') {\n currentInterval += 5000;\n continue;\n }\n\n spinner.stop('Authentication failed');\n clack.log.error(`Authentication error: ${errorData.error}`);\n process.exit(1);\n } catch {\n continue;\n }\n }\n\n spinner.stop('Authentication timed out');\n clack.log.error('Authentication timed out. Please try again.');\n process.exit(1);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runLogout(): Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import clack from '../utils/clack.js';
|
|
2
|
+
import { clearCredentials, hasCredentials, getCredentials } from '../lib/credentials.js';
|
|
3
|
+
export async function runLogout() {
|
|
4
|
+
if (!hasCredentials()) {
|
|
5
|
+
clack.log.info('Not logged in');
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const creds = getCredentials();
|
|
9
|
+
clearCredentials();
|
|
10
|
+
if (creds?.email) {
|
|
11
|
+
clack.log.success(`Logged out from ${creds.email}`);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
clack.log.success('Logged out successfully');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEzF,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,gBAAgB,EAAE,CAAC;IAEnB,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;QACjB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC","sourcesContent":["import clack from '../utils/clack.js';\nimport { clearCredentials, hasCredentials, getCredentials } from '../lib/credentials.js';\n\nexport async function runLogout(): Promise<void> {\n if (!hasCredentials()) {\n clack.log.info('Not logged in');\n return;\n }\n\n const creds = getCredentials();\n clearCredentials();\n\n if (creds?.email) {\n clack.log.success(`Logged out from ${creds.email}`);\n } else {\n clack.log.success('Logged out successfully');\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type AnimationMode } from '../lib/logo-frames.js';
|
|
3
|
+
interface AnimatedLogoProps {
|
|
4
|
+
mode?: AnimationMode;
|
|
5
|
+
paused?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function AnimatedLogo({ mode, paused }: AnimatedLogoProps): React.ReactElement;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { useAnimation } from '../hooks/useAnimation.js';
|
|
5
|
+
import { getFrames, FRAME_DELAYS } from '../lib/logo-frames.js';
|
|
6
|
+
export function AnimatedLogo({ mode = 'spin', paused = false }) {
|
|
7
|
+
const frames = useMemo(() => getFrames(mode), [mode]);
|
|
8
|
+
const frameIndex = useAnimation({
|
|
9
|
+
frameCount: frames.length,
|
|
10
|
+
frameDelayMs: FRAME_DELAYS[mode],
|
|
11
|
+
paused,
|
|
12
|
+
});
|
|
13
|
+
const frame = frames[frameIndex];
|
|
14
|
+
return (_jsxs(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", children: [frame.lines.map((line, i) => (_jsx(Text, { children: `\x1b[${frame.color}m${line}\x1b[0m` }, i))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "WorkOS Installer" }) })] }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=AnimatedLogo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnimatedLogo.js","sourceRoot":"","sources":["../../../../src/dashboard/components/AnimatedLogo.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAsB,MAAM,uBAAuB,CAAC;AAOpF,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,MAAM,GAAG,KAAK,EAAqB;IAC/E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,YAAY,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC;QAChC,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAEjC,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,UAAU,EAAC,QAAQ,EAAC,cAAc,EAAC,QAAQ,aACpE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC5B,KAAC,IAAI,cAAU,QAAQ,KAAK,CAAC,KAAK,IAAI,IAAI,SAAS,IAAxC,CAAC,CAA+C,CAC5D,CAAC,EACF,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,QAAQ,uCAAwB,GAClC,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React, { useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport { useAnimation } from '../hooks/useAnimation.js';\nimport { getFrames, FRAME_DELAYS, type AnimationMode } from '../lib/logo-frames.js';\n\ninterface AnimatedLogoProps {\n mode?: AnimationMode;\n paused?: boolean;\n}\n\nexport function AnimatedLogo({ mode = 'spin', paused = false }: AnimatedLogoProps): React.ReactElement {\n const frames = useMemo(() => getFrames(mode), [mode]);\n const frameIndex = useAnimation({\n frameCount: frames.length,\n frameDelayMs: FRAME_DELAYS[mode],\n paused,\n });\n\n const frame = frames[frameIndex];\n\n return (\n <Box flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\">\n {frame.lines.map((line, i) => (\n <Text key={i}>{`\\x1b[${frame.color}m${line}\\x1b[0m`}</Text>\n ))}\n <Box marginTop={1}>\n <Text dimColor>WorkOS Installer</Text>\n </Box>\n </Box>\n );\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface OutputLine {
|
|
3
|
+
text: string;
|
|
4
|
+
isError?: boolean;
|
|
5
|
+
isStatus?: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface CompletionViewProps {
|
|
8
|
+
success: boolean;
|
|
9
|
+
summary?: string;
|
|
10
|
+
outputLog: OutputLine[];
|
|
11
|
+
}
|
|
12
|
+
export declare function CompletionView({ success, summary, outputLog }: CompletionViewProps): React.ReactElement;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text, useInput, useApp } from 'ink';
|
|
4
|
+
export function CompletionView({ success, summary, outputLog }) {
|
|
5
|
+
const { exit } = useApp();
|
|
6
|
+
const [scrollOffset, setScrollOffset] = useState(Math.max(0, outputLog.length - 20));
|
|
7
|
+
useInput((input, key) => {
|
|
8
|
+
if (key.upArrow) {
|
|
9
|
+
setScrollOffset((prev) => Math.max(0, prev - 1));
|
|
10
|
+
}
|
|
11
|
+
else if (key.downArrow) {
|
|
12
|
+
setScrollOffset((prev) => Math.min(outputLog.length - 1, prev + 1));
|
|
13
|
+
}
|
|
14
|
+
else if (key.return || input === 'q') {
|
|
15
|
+
exit();
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const visibleLines = outputLog.slice(scrollOffset, scrollOffset + 20);
|
|
19
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, width: "100%", height: "100%", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: success ? 'green' : 'red', children: success ? '✓ Installation Complete' : '✗ Installation Failed' }) }), summary && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: summary }) })), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", flexGrow: 1, paddingX: 1, children: [_jsxs(Text, { bold: true, dimColor: true, children: ["Output Log [", scrollOffset + 1, "-", scrollOffset + visibleLines.length, " of ", outputLog.length, "]"] }), visibleLines.map((line, i) => (_jsx(Text, { color: line.isError ? 'red' : line.isStatus ? 'yellow' : undefined, children: line.text }, i)))] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to scroll, Enter or Q to exit" }) })] }));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=CompletionView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompletionView.js","sourceRoot":"","sources":["../../../../src/dashboard/components/CompletionView.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAclD,MAAM,UAAU,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAuB;IACjF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;IAErF,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,eAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YACzB,eAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACvC,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,YAAY,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC;IAEtE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAC,MAAM,EAAC,MAAM,EAAC,MAAM,aAEhE,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,YACxC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,uBAAuB,GACzD,GACH,EAEL,OAAO,IAAI,CACV,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,KAAC,IAAI,cAAE,OAAO,GAAQ,GAClB,CACP,EAGD,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,MAAM,EAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,aACzF,MAAC,IAAI,IAAC,IAAI,QAAC,QAAQ,mCACJ,YAAY,GAAG,CAAC,OAAG,YAAY,GAAG,YAAY,CAAC,MAAM,UAAM,SAAS,CAAC,MAAM,SACnF,EACN,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,KAAC,IAAI,IAAS,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,YAC7E,IAAI,CAAC,IAAI,IADD,CAAC,CAEL,CACR,CAAC,IACE,EAGN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,QAAQ,kEAAyC,GACnD,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React, { useState } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\n\ninterface OutputLine {\n text: string;\n isError?: boolean;\n isStatus?: boolean;\n}\n\ninterface CompletionViewProps {\n success: boolean;\n summary?: string;\n outputLog: OutputLine[];\n}\n\nexport function CompletionView({ success, summary, outputLog }: CompletionViewProps): React.ReactElement {\n const { exit } = useApp();\n const [scrollOffset, setScrollOffset] = useState(Math.max(0, outputLog.length - 20));\n\n useInput((input, key) => {\n if (key.upArrow) {\n setScrollOffset((prev) => Math.max(0, prev - 1));\n } else if (key.downArrow) {\n setScrollOffset((prev) => Math.min(outputLog.length - 1, prev + 1));\n } else if (key.return || input === 'q') {\n exit();\n }\n });\n\n const visibleLines = outputLog.slice(scrollOffset, scrollOffset + 20);\n\n return (\n <Box flexDirection=\"column\" padding={1} width=\"100%\" height=\"100%\">\n {/* Header */}\n <Box marginBottom={1}>\n <Text bold color={success ? 'green' : 'red'}>\n {success ? '✓ Installation Complete' : '✗ Installation Failed'}\n </Text>\n </Box>\n\n {summary && (\n <Box marginBottom={1}>\n <Text>{summary}</Text>\n </Box>\n )}\n\n {/* Scrollable Log */}\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" flexGrow={1} paddingX={1}>\n <Text bold dimColor>\n Output Log [{scrollOffset + 1}-{scrollOffset + visibleLines.length} of {outputLog.length}]\n </Text>\n {visibleLines.map((line, i) => (\n <Text key={i} color={line.isError ? 'red' : line.isStatus ? 'yellow' : undefined}>\n {line.text}\n </Text>\n ))}\n </Box>\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text dimColor>↑/↓ to scroll, Enter or Q to exit</Text>\n </Box>\n </Box>\n );\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface ConfirmPromptProps {
|
|
3
|
+
message: string;
|
|
4
|
+
warning?: string;
|
|
5
|
+
files?: string[];
|
|
6
|
+
onConfirm: (confirmed: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function ConfirmPrompt({ message, warning, files, onConfirm }: ConfirmPromptProps): React.ReactElement;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
export function ConfirmPrompt({ message, warning, files, onConfirm }) {
|
|
5
|
+
const [selected, setSelected] = useState('yes');
|
|
6
|
+
useInput((input, key) => {
|
|
7
|
+
if (key.leftArrow || input === 'h') {
|
|
8
|
+
setSelected('yes');
|
|
9
|
+
}
|
|
10
|
+
else if (key.rightArrow || input === 'l') {
|
|
11
|
+
setSelected('no');
|
|
12
|
+
}
|
|
13
|
+
else if (input === 'y' || input === 'Y') {
|
|
14
|
+
onConfirm(true);
|
|
15
|
+
}
|
|
16
|
+
else if (input === 'n' || input === 'N') {
|
|
17
|
+
onConfirm(false);
|
|
18
|
+
}
|
|
19
|
+
else if (key.return) {
|
|
20
|
+
onConfirm(selected === 'yes');
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [warning && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "yellow", bold: true, children: ["\u26A0 ", warning] }) })), files && files.length > 0 && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [files.slice(0, 10).map((file, i) => (_jsx(Text, { dimColor: true, children: file }, i))), files.length > 10 && _jsxs(Text, { dimColor: true, children: ["...and ", files.length - 10, " more"] })] })), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: message }) }), _jsxs(Box, { children: [_jsxs(Text, { color: selected === 'yes' ? 'cyan' : undefined, bold: selected === 'yes', children: [selected === 'yes' ? '● ' : '○ ', "Yes"] }), _jsx(Text, { children: " " }), _jsxs(Text, { color: selected === 'no' ? 'cyan' : undefined, bold: selected === 'no', children: [selected === 'no' ? '● ' : '○ ', "No"] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2190/\u2192 or y/n to select | Enter to confirm" }) })] }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ConfirmPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmPrompt.js","sourceRoot":"","sources":["../../../../src/dashboard/components/ConfirmPrompt.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAS1C,MAAM,UAAU,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAsB;IACtF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAe,KAAK,CAAC,CAAC;IAE9D,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,SAAS,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YACnC,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC3C,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC1C,SAAS,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC1C,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACtB,SAAS,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aACpC,OAAO,IAAI,CACV,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,8BACpB,OAAO,IACL,GACH,CACP,EAEA,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAC5B,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACxC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACnC,KAAC,IAAI,IAAS,QAAQ,kBACnB,IAAI,IADI,CAAC,CAEL,CACR,CAAC,EACD,KAAK,CAAC,MAAM,GAAG,EAAE,IAAI,MAAC,IAAI,IAAC,QAAQ,8BAAS,KAAK,CAAC,MAAM,GAAG,EAAE,aAAa,IACvE,CACP,EAED,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,KAAC,IAAI,cAAE,OAAO,GAAQ,GAClB,EAEN,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,KAAK,KAAK,aAC3E,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,WAC5B,EACP,KAAC,IAAI,oBAAS,EACd,MAAC,IAAI,IAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,aACzE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAC3B,IACH,EAEN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,QAAQ,wEAA+C,GACzD,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\n\ninterface ConfirmPromptProps {\n message: string;\n warning?: string;\n files?: string[];\n onConfirm: (confirmed: boolean) => void;\n}\n\nexport function ConfirmPrompt({ message, warning, files, onConfirm }: ConfirmPromptProps): React.ReactElement {\n const [selected, setSelected] = useState<'yes' | 'no'>('yes');\n\n useInput((input, key) => {\n if (key.leftArrow || input === 'h') {\n setSelected('yes');\n } else if (key.rightArrow || input === 'l') {\n setSelected('no');\n } else if (input === 'y' || input === 'Y') {\n onConfirm(true);\n } else if (input === 'n' || input === 'N') {\n onConfirm(false);\n } else if (key.return) {\n onConfirm(selected === 'yes');\n }\n });\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n {warning && (\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>\n ⚠ {warning}\n </Text>\n </Box>\n )}\n\n {files && files.length > 0 && (\n <Box flexDirection=\"column\" marginBottom={1}>\n {files.slice(0, 10).map((file, i) => (\n <Text key={i} dimColor>\n {file}\n </Text>\n ))}\n {files.length > 10 && <Text dimColor>...and {files.length - 10} more</Text>}\n </Box>\n )}\n\n <Box marginBottom={1}>\n <Text>{message}</Text>\n </Box>\n\n <Box>\n <Text color={selected === 'yes' ? 'cyan' : undefined} bold={selected === 'yes'}>\n {selected === 'yes' ? '● ' : '○ '}Yes\n </Text>\n <Text> </Text>\n <Text color={selected === 'no' ? 'cyan' : undefined} bold={selected === 'no'}>\n {selected === 'no' ? '● ' : '○ '}No\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>←/→ or y/n to select | Enter to confirm</Text>\n </Box>\n </Box>\n );\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface CredentialsFormProps {
|
|
3
|
+
requiresApiKey: boolean;
|
|
4
|
+
onSubmit: (credentials: {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
clientId: string;
|
|
7
|
+
}) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function CredentialsForm({ requiresApiKey, onSubmit }: CredentialsFormProps): React.ReactElement;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
import { TextInput } from './TextInput.js';
|
|
5
|
+
export function CredentialsForm({ requiresApiKey, onSubmit }) {
|
|
6
|
+
const [apiKey, setApiKey] = useState('');
|
|
7
|
+
const [clientId, setClientId] = useState('');
|
|
8
|
+
const [focusedField, setFocusedField] = useState(requiresApiKey ? 'apiKey' : 'clientId');
|
|
9
|
+
const [errors, setErrors] = useState({});
|
|
10
|
+
const validate = () => {
|
|
11
|
+
const newErrors = {};
|
|
12
|
+
if (requiresApiKey && !apiKey) {
|
|
13
|
+
newErrors.apiKey = 'API Key is required';
|
|
14
|
+
}
|
|
15
|
+
else if (requiresApiKey && !apiKey.startsWith('sk_')) {
|
|
16
|
+
newErrors.apiKey = 'API Key should start with sk_';
|
|
17
|
+
}
|
|
18
|
+
if (!clientId) {
|
|
19
|
+
newErrors.clientId = 'Client ID is required';
|
|
20
|
+
}
|
|
21
|
+
else if (!clientId.startsWith('client_')) {
|
|
22
|
+
newErrors.clientId = 'Client ID should start with client_';
|
|
23
|
+
}
|
|
24
|
+
setErrors(newErrors);
|
|
25
|
+
return Object.keys(newErrors).length === 0;
|
|
26
|
+
};
|
|
27
|
+
const handleSubmit = () => {
|
|
28
|
+
if (validate()) {
|
|
29
|
+
onSubmit({ apiKey, clientId });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
// Tab/arrows to switch fields
|
|
33
|
+
useInput((input, key) => {
|
|
34
|
+
if (key.tab || key.downArrow) {
|
|
35
|
+
if (requiresApiKey) {
|
|
36
|
+
setFocusedField((prev) => (prev === 'apiKey' ? 'clientId' : 'apiKey'));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (key.upArrow) {
|
|
40
|
+
if (requiresApiKey) {
|
|
41
|
+
setFocusedField((prev) => (prev === 'clientId' ? 'apiKey' : 'clientId'));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "Enter your WorkOS credentials" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Get them from https://dashboard.workos.com" }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [requiresApiKey && (_jsx(Box, { marginBottom: 1, children: _jsx(TextInput, { label: "API Key", placeholder: "sk_...", mask: true, value: apiKey, onChange: setApiKey, onSubmit: () => setFocusedField('clientId'), focused: focusedField === 'apiKey', error: errors.apiKey }) })), _jsx(Box, { marginBottom: 1, children: _jsx(TextInput, { label: "Client ID", placeholder: "client_...", value: clientId, onChange: setClientId, onSubmit: handleSubmit, focused: focusedField === 'clientId', error: errors.clientId }) })] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [requiresApiKey ? 'Tab: switch fields | ' : '', "Ctrl+U: clear | Enter: continue"] }) })] }));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=CredentialsForm.js.map
|