@kingslanding/cli 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.
Files changed (78) hide show
  1. package/README.md +157 -0
  2. package/dist/commands/deploy-key.d.ts +3 -0
  3. package/dist/commands/deploy-key.d.ts.map +1 -0
  4. package/dist/commands/deploy-key.js +113 -0
  5. package/dist/commands/deploy-key.js.map +1 -0
  6. package/dist/commands/deploy.d.ts +3 -0
  7. package/dist/commands/deploy.d.ts.map +1 -0
  8. package/dist/commands/deploy.js +139 -0
  9. package/dist/commands/deploy.js.map +1 -0
  10. package/dist/commands/init.d.ts +3 -0
  11. package/dist/commands/init.d.ts.map +1 -0
  12. package/dist/commands/init.js +63 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/login.d.ts +3 -0
  15. package/dist/commands/login.d.ts.map +1 -0
  16. package/dist/commands/login.js +65 -0
  17. package/dist/commands/login.js.map +1 -0
  18. package/dist/commands/logout.d.ts +3 -0
  19. package/dist/commands/logout.d.ts.map +1 -0
  20. package/dist/commands/logout.js +22 -0
  21. package/dist/commands/logout.js.map +1 -0
  22. package/dist/commands/projects.d.ts +3 -0
  23. package/dist/commands/projects.d.ts.map +1 -0
  24. package/dist/commands/projects.js +39 -0
  25. package/dist/commands/projects.js.map +1 -0
  26. package/dist/commands/whoami.d.ts +3 -0
  27. package/dist/commands/whoami.d.ts.map +1 -0
  28. package/dist/commands/whoami.js +24 -0
  29. package/dist/commands/whoami.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +35 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/lib/api.d.ts +104 -0
  35. package/dist/lib/api.d.ts.map +1 -0
  36. package/dist/lib/api.js +118 -0
  37. package/dist/lib/api.js.map +1 -0
  38. package/dist/lib/auth.d.ts +15 -0
  39. package/dist/lib/auth.d.ts.map +1 -0
  40. package/dist/lib/auth.js +81 -0
  41. package/dist/lib/auth.js.map +1 -0
  42. package/dist/lib/config.d.ts +13 -0
  43. package/dist/lib/config.d.ts.map +1 -0
  44. package/dist/lib/config.js +66 -0
  45. package/dist/lib/config.js.map +1 -0
  46. package/dist/lib/errors.d.ts +16 -0
  47. package/dist/lib/errors.d.ts.map +1 -0
  48. package/dist/lib/errors.js +34 -0
  49. package/dist/lib/errors.js.map +1 -0
  50. package/dist/lib/files.d.ts +11 -0
  51. package/dist/lib/files.d.ts.map +1 -0
  52. package/dist/lib/files.js +60 -0
  53. package/dist/lib/files.js.map +1 -0
  54. package/dist/lib/ignore.d.ts +3 -0
  55. package/dist/lib/ignore.d.ts.map +1 -0
  56. package/dist/lib/ignore.js +20 -0
  57. package/dist/lib/ignore.js.map +1 -0
  58. package/dist/lib/output.d.ts +5 -0
  59. package/dist/lib/output.d.ts.map +1 -0
  60. package/dist/lib/output.js +15 -0
  61. package/dist/lib/output.js.map +1 -0
  62. package/dist/services/auth-service.d.ts +15 -0
  63. package/dist/services/auth-service.d.ts.map +1 -0
  64. package/dist/services/auth-service.js +65 -0
  65. package/dist/services/auth-service.js.map +1 -0
  66. package/dist/services/deploy-key-service.d.ts +9 -0
  67. package/dist/services/deploy-key-service.d.ts.map +1 -0
  68. package/dist/services/deploy-key-service.js +16 -0
  69. package/dist/services/deploy-key-service.js.map +1 -0
  70. package/dist/services/deploy-service.d.ts +19 -0
  71. package/dist/services/deploy-service.d.ts.map +1 -0
  72. package/dist/services/deploy-service.js +68 -0
  73. package/dist/services/deploy-service.js.map +1 -0
  74. package/dist/services/project-service.d.ts +10 -0
  75. package/dist/services/project-service.d.ts.map +1 -0
  76. package/dist/services/project-service.js +29 -0
  77. package/dist/services/project-service.js.map +1 -0
  78. package/package.json +49 -0
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # kl — King's Landing CLI
2
+
3
+ Deploy static sites to [King's Landing](https://kingslanding.io) from any terminal or CI/CD pipeline.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @kingslanding/cli
9
+ ```
10
+
11
+ Or run without installing:
12
+
13
+ ```bash
14
+ npx @kingslanding/cli deploy ./dist
15
+ ```
16
+
17
+ Or with Docker (no Node.js required):
18
+
19
+ ```bash
20
+ docker run --rm -v $(pwd):/app -w /app ghcr.io/boxshopio/kl deploy ./dist
21
+ ```
22
+
23
+ **Requirements:** Node.js >= 18 (npm install), or Docker.
24
+
25
+ ## Quick start
26
+
27
+ ```bash
28
+ # Authenticate
29
+ kl login
30
+
31
+ # Initialize a project config
32
+ kl init
33
+
34
+ # Deploy
35
+ kl deploy ./dist
36
+ ```
37
+
38
+ ## Commands
39
+
40
+ | Command | Description |
41
+ |---------|-------------|
42
+ | `kl login` | Authenticate via browser |
43
+ | `kl logout` | Clear credentials |
44
+ | `kl init` | Create `kl.json` project config |
45
+ | `kl deploy [dir]` | Deploy a directory (default: `.`) |
46
+ | `kl projects` | List your projects |
47
+ | `kl whoami` | Show current user |
48
+ | `kl deploy-key create` | Generate a deploy key for CI/CD |
49
+ | `kl deploy-key status` | Check if a deploy key exists |
50
+ | `kl deploy-key revoke` | Revoke a deploy key |
51
+
52
+ ## Deploy
53
+
54
+ ```bash
55
+ # Deploy current directory
56
+ kl deploy
57
+
58
+ # Deploy a specific directory
59
+ kl deploy ./dist
60
+
61
+ # Deploy with a project name (skips kl.json)
62
+ kl deploy ./dist --project my-site
63
+
64
+ # Auto-create project if it doesn't exist (for CI)
65
+ kl deploy ./dist --project my-site --create
66
+
67
+ # Detailed output
68
+ kl deploy ./dist --verbose
69
+ ```
70
+
71
+ ## Project config
72
+
73
+ Run `kl init` to create a `kl.json` in your project root:
74
+
75
+ ```json
76
+ {
77
+ "project": "my-site",
78
+ "directory": "dist",
79
+ "team": null
80
+ }
81
+ ```
82
+
83
+ | Field | Description | Default |
84
+ |-------|-------------|---------|
85
+ | `project` | Project name on King's Landing | *required* |
86
+ | `directory` | Directory to deploy | `.` |
87
+ | `team` | Team slug (for team-owned projects) | `null` |
88
+
89
+ ## CI/CD
90
+
91
+ ### GitHub Actions
92
+
93
+ ```yaml
94
+ name: Deploy
95
+ on:
96
+ push:
97
+ branches: [main]
98
+
99
+ jobs:
100
+ deploy:
101
+ runs-on: ubuntu-latest
102
+ steps:
103
+ - uses: actions/checkout@v4
104
+ - run: npx @kingslanding/cli deploy ./dist --project my-site --create
105
+ env:
106
+ KL_DEPLOY_KEY: ${{ secrets.KL_DEPLOY_KEY }}
107
+ ```
108
+
109
+ ### Generate a deploy key
110
+
111
+ ```bash
112
+ kl deploy-key create --project my-site
113
+ ```
114
+
115
+ The key is shown once. Add it as `KL_DEPLOY_KEY` in your CI secrets.
116
+
117
+ ### Any CI provider
118
+
119
+ The CLI detects `KL_DEPLOY_KEY` automatically. No `kl login` needed.
120
+
121
+ ```bash
122
+ export KL_DEPLOY_KEY=kl_your_key_here
123
+ npx @kingslanding/cli deploy ./dist --project my-site --create
124
+ ```
125
+
126
+ ## File filtering
127
+
128
+ Create a `.klignore` file (gitignore syntax) to control which files are deployed:
129
+
130
+ ```
131
+ node_modules
132
+ .git
133
+ .env*
134
+ .DS_Store
135
+ ```
136
+
137
+ If no `.klignore` exists, these defaults apply automatically.
138
+
139
+ ## Docker usage
140
+
141
+ For environments without Node.js:
142
+
143
+ ```bash
144
+ # Deploy
145
+ docker run --rm -v $(pwd):/app -w /app ghcr.io/boxshopio/kl deploy ./dist --project my-site --create
146
+
147
+ # With deploy key
148
+ docker run --rm -e KL_DEPLOY_KEY=$KL_DEPLOY_KEY -v $(pwd):/app -w /app ghcr.io/boxshopio/kl deploy ./dist
149
+
150
+ # Shell alias for convenience
151
+ alias kl='docker run --rm -e KL_DEPLOY_KEY -v $(pwd):/app -w /app ghcr.io/boxshopio/kl'
152
+ kl deploy ./dist
153
+ ```
154
+
155
+ ## License
156
+
157
+ Proprietary. See [kingslanding.io](https://kingslanding.io) for terms.
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerDeployKeyCommand(program: Command): void;
3
+ //# sourceMappingURL=deploy-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-key.d.ts","sourceRoot":"","sources":["../../src/commands/deploy-key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBzC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsH/D"}
@@ -0,0 +1,113 @@
1
+ import { confirm } from "@inquirer/prompts";
2
+ import { ApiClient } from "../lib/api.js";
3
+ import { resolveApiUrl, loadProjectConfig } from "../lib/config.js";
4
+ import { getAuthHeader } from "../lib/auth.js";
5
+ import { CLIError, AuthError } from "../lib/errors.js";
6
+ import { DeployKeyService } from "../services/deploy-key-service.js";
7
+ import { ProjectService } from "../services/project-service.js";
8
+ function resolveProjectAndTeam(options) {
9
+ const config = loadProjectConfig(process.cwd());
10
+ const projectName = options.project ?? config?.project;
11
+ if (!projectName) {
12
+ throw new CLIError("No project name. Use --project <name> or run `kl init`.");
13
+ }
14
+ const teamSlug = options.team ?? config?.team ?? undefined;
15
+ return { projectName, teamSlug };
16
+ }
17
+ export function registerDeployKeyCommand(program) {
18
+ const cmd = program
19
+ .command("deploy-key")
20
+ .description("Manage deploy keys for CI/CD");
21
+ cmd
22
+ .command("create")
23
+ .description("Create a deploy key for a project")
24
+ .option("-p, --project <name>", "Project name")
25
+ .option("-t, --team <slug>", "Team slug")
26
+ .action(async (options) => {
27
+ const apiUrl = resolveApiUrl();
28
+ const authHeader = getAuthHeader(apiUrl);
29
+ if (!authHeader) {
30
+ throw new AuthError("Not logged in. Run `kl login` first.");
31
+ }
32
+ const { projectName, teamSlug } = resolveProjectAndTeam(options);
33
+ const api = new ApiClient(apiUrl, authHeader);
34
+ let teamId;
35
+ if (teamSlug) {
36
+ const projectService = new ProjectService(api);
37
+ teamId = await projectService.resolveTeamId(teamSlug);
38
+ }
39
+ const deployKeyService = new DeployKeyService(api);
40
+ const result = await deployKeyService.create(projectName, teamId);
41
+ console.log();
42
+ console.log("Deploy key created for " + projectName + ":");
43
+ console.log();
44
+ console.log(" " + result.key);
45
+ console.log();
46
+ console.log("Save this key now — it will not be shown again.");
47
+ console.log("Set it as KL_DEPLOY_KEY in your CI/CD environment.");
48
+ });
49
+ cmd
50
+ .command("revoke")
51
+ .description("Revoke the deploy key for a project")
52
+ .option("-p, --project <name>", "Project name")
53
+ .option("-t, --team <slug>", "Team slug")
54
+ .action(async (options) => {
55
+ const apiUrl = resolveApiUrl();
56
+ const authHeader = getAuthHeader(apiUrl);
57
+ if (!authHeader) {
58
+ throw new AuthError("Not logged in. Run `kl login` first.");
59
+ }
60
+ const { projectName, teamSlug } = resolveProjectAndTeam(options);
61
+ const shouldRevoke = await confirm({
62
+ message: "Revoke the deploy key for " +
63
+ projectName +
64
+ "? This cannot be undone.",
65
+ default: false,
66
+ });
67
+ if (!shouldRevoke) {
68
+ console.log("Cancelled.");
69
+ return;
70
+ }
71
+ const api = new ApiClient(apiUrl, authHeader);
72
+ let teamId;
73
+ if (teamSlug) {
74
+ const projectService = new ProjectService(api);
75
+ teamId = await projectService.resolveTeamId(teamSlug);
76
+ }
77
+ const deployKeyService = new DeployKeyService(api);
78
+ await deployKeyService.revoke(projectName, teamId);
79
+ console.log("Deploy key revoked for " + projectName + ".");
80
+ });
81
+ cmd
82
+ .command("status")
83
+ .description("Check deploy key status for a project")
84
+ .option("-p, --project <name>", "Project name")
85
+ .option("-t, --team <slug>", "Team slug")
86
+ .action(async (options) => {
87
+ const apiUrl = resolveApiUrl();
88
+ const authHeader = getAuthHeader(apiUrl);
89
+ if (!authHeader) {
90
+ throw new AuthError("Not logged in. Run `kl login` first.");
91
+ }
92
+ const { projectName, teamSlug } = resolveProjectAndTeam(options);
93
+ const api = new ApiClient(apiUrl, authHeader);
94
+ let teamId;
95
+ if (teamSlug) {
96
+ const projectService = new ProjectService(api);
97
+ teamId = await projectService.resolveTeamId(teamSlug);
98
+ }
99
+ const deployKeyService = new DeployKeyService(api);
100
+ const result = await deployKeyService.status(projectName, teamId);
101
+ if (result.exists) {
102
+ console.log("Deploy key active for " + projectName);
103
+ console.log(" Prefix: " + result.key_prefix);
104
+ if (result.created_at) {
105
+ console.log(" Created: " + new Date(result.created_at * 1000).toISOString());
106
+ }
107
+ }
108
+ else {
109
+ console.log("No deploy key configured for " + projectName + ".");
110
+ }
111
+ });
112
+ }
113
+ //# sourceMappingURL=deploy-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-key.js","sourceRoot":"","sources":["../../src/commands/deploy-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerDeployCommand(program: Command): void;
3
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+J5D"}
@@ -0,0 +1,139 @@
1
+ import * as path from "node:path";
2
+ import { confirm } from "@inquirer/prompts";
3
+ import { ApiClient } from "../lib/api.js";
4
+ import { resolveApiUrl, loadProjectConfig } from "../lib/config.js";
5
+ import { getAuthHeader, loadCredentials, isDeployKeyAuth } from "../lib/auth.js";
6
+ import { buildFileManifest } from "../lib/files.js";
7
+ import { createSpinner, formatBytes } from "../lib/output.js";
8
+ import { CLIError, ApiError, AuthError } from "../lib/errors.js";
9
+ import { AuthService } from "../services/auth-service.js";
10
+ import { DeployService, defaultReadFile } from "../services/deploy-service.js";
11
+ import { ProjectService } from "../services/project-service.js";
12
+ export function registerDeployCommand(program) {
13
+ program
14
+ .command("deploy")
15
+ .description("Deploy a directory to King's Landing")
16
+ .argument("[dir]", "Directory to deploy")
17
+ .option("-p, --project <name>", "Project name")
18
+ .option("-t, --team <slug>", "Team slug")
19
+ .option("--create", "Create project if it does not exist")
20
+ .option("-v, --verbose", "Show detailed output")
21
+ .action(async (dirArg, options) => {
22
+ const cwd = process.cwd();
23
+ const config = loadProjectConfig(cwd);
24
+ const apiUrl = resolveApiUrl(cwd);
25
+ // Resolve project name
26
+ const projectName = options.project ?? config?.project;
27
+ if (!projectName) {
28
+ throw new CLIError("No project name. Use --project <name> or run `kl init`.");
29
+ }
30
+ // Resolve deploy directory
31
+ const relativeDir = dirArg ?? config?.directory ?? ".";
32
+ const deployDir = path.resolve(cwd, relativeDir);
33
+ // Resolve team
34
+ let teamId;
35
+ const teamSlug = options.team ?? config?.team;
36
+ // Ensure auth
37
+ let authHeader = getAuthHeader(apiUrl);
38
+ if (!authHeader) {
39
+ throw new AuthError("Not logged in. Run `kl login` first.");
40
+ }
41
+ const api = new ApiClient(apiUrl, authHeader);
42
+ // Refresh token if needed (JWT only, not deploy keys)
43
+ if (!isDeployKeyAuth()) {
44
+ const creds = loadCredentials(apiUrl);
45
+ if (creds) {
46
+ const authService = new AuthService(api, apiUrl);
47
+ await authService.refreshIfNeeded(creds);
48
+ // Re-read auth header after potential refresh
49
+ authHeader = getAuthHeader(apiUrl);
50
+ if (authHeader) {
51
+ api.updateAuthHeader(authHeader);
52
+ }
53
+ }
54
+ }
55
+ // Resolve team slug to ID
56
+ if (teamSlug) {
57
+ const projectService = new ProjectService(api);
58
+ teamId = await projectService.resolveTeamId(teamSlug);
59
+ }
60
+ // Build manifest
61
+ const files = buildFileManifest(deployDir, cwd);
62
+ if (options.verbose) {
63
+ console.log("Deploying " +
64
+ files.length +
65
+ " files (" +
66
+ formatBytes(files.reduce((sum, f) => sum + f.size, 0)) +
67
+ ") from " +
68
+ deployDir);
69
+ }
70
+ const deployService = new DeployService(api);
71
+ const spinner = createSpinner("Deploying...");
72
+ spinner.start();
73
+ const startTime = Date.now();
74
+ const runDeploy = async (create) => {
75
+ return deployService.deploy({
76
+ projectName,
77
+ files,
78
+ readFile: defaultReadFile,
79
+ onProgress: (completed, total) => {
80
+ spinner.text = "Uploading " + completed + "/" + total + " files...";
81
+ },
82
+ create,
83
+ teamId,
84
+ });
85
+ };
86
+ try {
87
+ let result;
88
+ try {
89
+ result = await runDeploy(options.create);
90
+ }
91
+ catch (err) {
92
+ if (err instanceof ApiError &&
93
+ err.status === 404 &&
94
+ !options.create) {
95
+ spinner.stop();
96
+ const isTTY = process.stdout.isTTY;
97
+ if (isTTY) {
98
+ const shouldCreate = await confirm({
99
+ message: 'Project "' +
100
+ projectName +
101
+ '" does not exist. Create it?',
102
+ default: true,
103
+ });
104
+ if (!shouldCreate) {
105
+ throw new CLIError("Deploy cancelled.");
106
+ }
107
+ spinner.start();
108
+ result = await runDeploy(true);
109
+ }
110
+ else {
111
+ throw new CLIError('Project "' +
112
+ projectName +
113
+ '" not found. Use --create to create it.');
114
+ }
115
+ }
116
+ else {
117
+ throw err;
118
+ }
119
+ }
120
+ spinner.stop();
121
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
122
+ if (options.verbose) {
123
+ console.log("Deployed " +
124
+ result.files +
125
+ " files (" +
126
+ formatBytes(result.total_size) +
127
+ ") in " +
128
+ elapsed +
129
+ "s");
130
+ }
131
+ console.log("Done. " + result.url);
132
+ }
133
+ catch (err) {
134
+ spinner.stop();
135
+ throw err;
136
+ }
137
+ });
138
+ }
139
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerInitCommand(program: Command): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6D1D"}
@@ -0,0 +1,63 @@
1
+ import { input, select } from "@inquirer/prompts";
2
+ import { ApiClient } from "../lib/api.js";
3
+ import { resolveApiUrl, loadProjectConfig, writeProjectConfig, } from "../lib/config.js";
4
+ import { getAuthHeader } from "../lib/auth.js";
5
+ import { CLIError } from "../lib/errors.js";
6
+ import { ProjectService } from "../services/project-service.js";
7
+ const PROJECT_NAME_REGEX = /^[a-z0-9][a-z0-9-]{2,61}[a-z0-9]$/;
8
+ export function registerInitCommand(program) {
9
+ program
10
+ .command("init")
11
+ .description("Create a kl.json config in the current directory")
12
+ .action(async () => {
13
+ const cwd = process.cwd();
14
+ const existing = loadProjectConfig(cwd);
15
+ if (existing) {
16
+ throw new CLIError("kl.json already exists in this directory. Delete it first to re-initialize.");
17
+ }
18
+ const project = await input({
19
+ message: "Project name",
20
+ validate: (value) => {
21
+ if (!PROJECT_NAME_REGEX.test(value)) {
22
+ return "Must be 4-63 characters, lowercase alphanumeric and hyphens, start/end with alphanumeric.";
23
+ }
24
+ return true;
25
+ },
26
+ });
27
+ const directory = await input({
28
+ message: "Deploy directory",
29
+ default: ".",
30
+ });
31
+ let team = null;
32
+ const apiUrl = resolveApiUrl(cwd);
33
+ const authHeader = getAuthHeader(apiUrl);
34
+ if (authHeader) {
35
+ try {
36
+ const api = new ApiClient(apiUrl, authHeader);
37
+ const projectService = new ProjectService(api);
38
+ const teams = await projectService.getUserTeams();
39
+ if (teams.length > 0) {
40
+ const choices = [
41
+ { name: "Personal (no team)", value: "" },
42
+ ...teams.map((t) => ({
43
+ name: t.team.name + " (" + t.team.slug + ")",
44
+ value: t.team.slug,
45
+ })),
46
+ ];
47
+ const selected = await select({
48
+ message: "Team",
49
+ choices,
50
+ });
51
+ if (selected)
52
+ team = selected;
53
+ }
54
+ }
55
+ catch {
56
+ // If we can't fetch teams (not logged in, etc.), skip the prompt
57
+ }
58
+ }
59
+ writeProjectConfig(cwd, { project, directory, team });
60
+ console.log("Created kl.json");
61
+ });
62
+ }
63
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,kBAAkB,GAAG,mCAAmC,CAAC;AAE/D,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,kDAAkD,CAAC;SAC/D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,6EAA6E,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC;YAC1B,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACpC,OAAO,2FAA2F,CAAC;gBACrG,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC;YAC5B,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,GAAG;SACb,CAAC,CAAC;QAEH,IAAI,IAAI,GAAkB,IAAI,CAAC;QAE/B,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC9C,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC;gBAC/C,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,YAAY,EAAE,CAAC;gBAElD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrB,MAAM,OAAO,GAAG;wBACd,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,EAAE,EAAE;wBACzC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;4BACnB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG;4BAC5C,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;yBACnB,CAAC,CAAC;qBACJ,CAAC;oBAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;wBAC5B,OAAO,EAAE,MAAM;wBACf,OAAO;qBACR,CAAC,CAAC;oBACH,IAAI,QAAQ;wBAAE,IAAI,GAAG,QAAQ,CAAC;gBAChC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;YACnE,CAAC;QACH,CAAC;QAED,kBAAkB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerLoginCommand(program: Command): void;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyD3D"}
@@ -0,0 +1,65 @@
1
+ import { exec } from "node:child_process";
2
+ import { ApiClient } from "../lib/api.js";
3
+ import { resolveApiUrl, isLocalMode } from "../lib/config.js";
4
+ import { getAuthHeader, loadCredentials, isTokenExpiringSoon, } from "../lib/auth.js";
5
+ import { createSpinner } from "../lib/output.js";
6
+ import { AuthService } from "../services/auth-service.js";
7
+ function tryOpenBrowser(url) {
8
+ const cmd = process.platform === "darwin" ? "open" : "xdg-open";
9
+ exec(`${cmd} ${JSON.stringify(url)}`, () => {
10
+ // Silent failure — user can copy/paste the URL
11
+ });
12
+ }
13
+ export function registerLoginCommand(program) {
14
+ program
15
+ .command("login")
16
+ .description("Authenticate with King's Landing")
17
+ .action(async () => {
18
+ const apiUrl = resolveApiUrl();
19
+ if (isLocalMode(apiUrl)) {
20
+ console.log("Local mode — no login required.");
21
+ return;
22
+ }
23
+ const creds = loadCredentials(apiUrl);
24
+ if (creds && !isTokenExpiringSoon(creds)) {
25
+ const api = new ApiClient(apiUrl, "Bearer " + creds.access_token);
26
+ try {
27
+ const account = await api.getAccount();
28
+ console.log("Already logged in as " + account.email);
29
+ return;
30
+ }
31
+ catch {
32
+ // Token invalid — proceed with login
33
+ }
34
+ }
35
+ const authHeader = getAuthHeader(apiUrl);
36
+ const api = new ApiClient(apiUrl, authHeader);
37
+ const authService = new AuthService(api, apiUrl);
38
+ const spinner = createSpinner("Waiting for browser authorization...");
39
+ await authService.login((userCode, verificationUrl) => {
40
+ console.log();
41
+ console.log("Open this URL in your browser:");
42
+ console.log(" " + verificationUrl);
43
+ console.log();
44
+ console.log("Enter code: " + userCode);
45
+ console.log();
46
+ tryOpenBrowser(verificationUrl);
47
+ spinner.start();
48
+ });
49
+ spinner.stop();
50
+ const newCreds = loadCredentials(apiUrl);
51
+ if (!newCreds) {
52
+ console.log("Logged in.");
53
+ return;
54
+ }
55
+ api.updateAuthHeader("Bearer " + newCreds.access_token);
56
+ try {
57
+ const account = await api.getAccount();
58
+ console.log("Logged in as " + account.email);
59
+ }
60
+ catch {
61
+ console.log("Logged in.");
62
+ }
63
+ });
64
+ }
65
+ //# 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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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerLogoutCommand(program: Command): void;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkB5D"}
@@ -0,0 +1,22 @@
1
+ import { ApiClient } from "../lib/api.js";
2
+ import { resolveApiUrl } from "../lib/config.js";
3
+ import { loadCredentials } from "../lib/auth.js";
4
+ import { AuthService } from "../services/auth-service.js";
5
+ export function registerLogoutCommand(program) {
6
+ program
7
+ .command("logout")
8
+ .description("Clear stored credentials")
9
+ .action(async () => {
10
+ const apiUrl = resolveApiUrl();
11
+ const creds = loadCredentials(apiUrl);
12
+ if (!creds) {
13
+ console.log("Not logged in.");
14
+ return;
15
+ }
16
+ const api = new ApiClient(apiUrl, "Bearer " + creds.access_token);
17
+ const authService = new AuthService(api, apiUrl);
18
+ await authService.logout(creds.refresh_token);
19
+ console.log("Logged out.");
20
+ });
21
+ }
22
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerProjectsCommand(program: Command): void;
3
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0C9D"}