@lizard-build/cli 0.1.0 → 0.3.30

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 (184) hide show
  1. package/.github/workflows/release.yml +90 -0
  2. package/AGENTS.md +113 -0
  3. package/README.md +41 -0
  4. package/dist/commands/add.js +318 -45
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/config.d.ts +2 -0
  7. package/dist/commands/config.js +68 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/docs.d.ts +2 -0
  10. package/dist/commands/docs.js +13 -0
  11. package/dist/commands/docs.js.map +1 -0
  12. package/dist/commands/domain.d.ts +9 -0
  13. package/dist/commands/domain.js +195 -0
  14. package/dist/commands/domain.js.map +1 -0
  15. package/dist/commands/git.js +175 -36
  16. package/dist/commands/git.js.map +1 -1
  17. package/dist/commands/init.d.ts +24 -0
  18. package/dist/commands/init.js +128 -86
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/link.d.ts +7 -0
  21. package/dist/commands/link.js +104 -33
  22. package/dist/commands/link.js.map +1 -1
  23. package/dist/commands/login.js +4 -3
  24. package/dist/commands/login.js.map +1 -1
  25. package/dist/commands/logs.js +223 -30
  26. package/dist/commands/logs.js.map +1 -1
  27. package/dist/commands/open.js +3 -2
  28. package/dist/commands/open.js.map +1 -1
  29. package/dist/commands/port.d.ts +7 -0
  30. package/dist/commands/port.js +49 -0
  31. package/dist/commands/port.js.map +1 -0
  32. package/dist/commands/projects.js +36 -6
  33. package/dist/commands/projects.js.map +1 -1
  34. package/dist/commands/ps.js +32 -39
  35. package/dist/commands/ps.js.map +1 -1
  36. package/dist/commands/redeploy.js +48 -8
  37. package/dist/commands/redeploy.js.map +1 -1
  38. package/dist/commands/regions.js +2 -5
  39. package/dist/commands/regions.js.map +1 -1
  40. package/dist/commands/restart.js +84 -10
  41. package/dist/commands/restart.js.map +1 -1
  42. package/dist/commands/run.d.ts +9 -0
  43. package/dist/commands/run.js +61 -22
  44. package/dist/commands/run.js.map +1 -1
  45. package/dist/commands/scale.d.ts +10 -0
  46. package/dist/commands/scale.js +166 -0
  47. package/dist/commands/scale.js.map +1 -0
  48. package/dist/commands/secrets.js +200 -89
  49. package/dist/commands/secrets.js.map +1 -1
  50. package/dist/commands/service-set.d.ts +49 -0
  51. package/dist/commands/service-set.js +552 -0
  52. package/dist/commands/service-set.js.map +1 -0
  53. package/dist/commands/service-show.d.ts +11 -0
  54. package/dist/commands/service-show.js +44 -0
  55. package/dist/commands/service-show.js.map +1 -0
  56. package/dist/commands/service.d.ts +8 -0
  57. package/dist/commands/service.js +262 -0
  58. package/dist/commands/service.js.map +1 -0
  59. package/dist/commands/skill.d.ts +2 -0
  60. package/dist/commands/skill.js +146 -0
  61. package/dist/commands/skill.js.map +1 -0
  62. package/dist/commands/ssh.d.ts +2 -0
  63. package/dist/commands/ssh.js +161 -0
  64. package/dist/commands/ssh.js.map +1 -0
  65. package/dist/commands/status.d.ts +7 -0
  66. package/dist/commands/status.js +49 -38
  67. package/dist/commands/status.js.map +1 -1
  68. package/dist/commands/unlink.d.ts +5 -0
  69. package/dist/commands/unlink.js +18 -0
  70. package/dist/commands/unlink.js.map +1 -0
  71. package/dist/commands/up.d.ts +9 -0
  72. package/dist/commands/up.js +417 -0
  73. package/dist/commands/up.js.map +1 -0
  74. package/dist/commands/upgrade.d.ts +2 -0
  75. package/dist/commands/upgrade.js +79 -0
  76. package/dist/commands/upgrade.js.map +1 -0
  77. package/dist/commands/whoami.js +26 -6
  78. package/dist/commands/whoami.js.map +1 -1
  79. package/dist/commands/workspace.d.ts +8 -0
  80. package/dist/commands/workspace.js +36 -0
  81. package/dist/commands/workspace.js.map +1 -0
  82. package/dist/index.js +209 -82
  83. package/dist/index.js.map +1 -1
  84. package/dist/lib/api.d.ts +17 -2
  85. package/dist/lib/api.js +85 -51
  86. package/dist/lib/api.js.map +1 -1
  87. package/dist/lib/auth.d.ts +3 -11
  88. package/dist/lib/auth.js +16 -36
  89. package/dist/lib/auth.js.map +1 -1
  90. package/dist/lib/config.d.ts +36 -15
  91. package/dist/lib/config.js +71 -58
  92. package/dist/lib/config.js.map +1 -1
  93. package/dist/lib/format.d.ts +1 -0
  94. package/dist/lib/format.js +17 -4
  95. package/dist/lib/format.js.map +1 -1
  96. package/dist/lib/name.d.ts +11 -0
  97. package/dist/lib/name.js +26 -0
  98. package/dist/lib/name.js.map +1 -0
  99. package/dist/lib/picker.d.ts +32 -0
  100. package/dist/lib/picker.js +91 -0
  101. package/dist/lib/picker.js.map +1 -0
  102. package/dist/lib/resolve.d.ts +85 -0
  103. package/dist/lib/resolve.js +203 -0
  104. package/dist/lib/resolve.js.map +1 -0
  105. package/dist/lib/updater.d.ts +16 -0
  106. package/dist/lib/updater.js +102 -0
  107. package/dist/lib/updater.js.map +1 -0
  108. package/lizard-wrapper.sh +2 -0
  109. package/package.json +11 -3
  110. package/skill-data/core/SKILL.md +239 -0
  111. package/src/commands/add.ts +388 -56
  112. package/src/commands/config.ts +80 -0
  113. package/src/commands/docs.ts +15 -0
  114. package/src/commands/domain.ts +248 -0
  115. package/src/commands/git.ts +201 -40
  116. package/src/commands/init.ts +149 -100
  117. package/src/commands/link.ts +127 -35
  118. package/src/commands/login.ts +4 -3
  119. package/src/commands/logs.ts +283 -27
  120. package/src/commands/open.ts +3 -2
  121. package/src/commands/port.ts +57 -0
  122. package/src/commands/projects.ts +43 -6
  123. package/src/commands/ps.ts +39 -60
  124. package/src/commands/redeploy.ts +51 -10
  125. package/src/commands/regions.ts +2 -6
  126. package/src/commands/restart.ts +84 -10
  127. package/src/commands/run.ts +68 -24
  128. package/src/commands/scale.ts +216 -0
  129. package/src/commands/secrets.ts +277 -100
  130. package/src/commands/service-set.ts +669 -0
  131. package/src/commands/service-show.ts +52 -0
  132. package/src/commands/service.ts +298 -0
  133. package/src/commands/skill.ts +157 -0
  134. package/src/commands/ssh.ts +176 -0
  135. package/src/commands/status.ts +51 -46
  136. package/src/commands/unlink.ts +17 -0
  137. package/src/commands/up.ts +461 -0
  138. package/src/commands/upgrade.ts +87 -0
  139. package/src/commands/whoami.ts +34 -6
  140. package/src/commands/workspace.ts +44 -0
  141. package/src/index.ts +219 -85
  142. package/src/lib/api.ts +114 -51
  143. package/src/lib/auth.ts +22 -46
  144. package/src/lib/config.ts +100 -65
  145. package/src/lib/format.ts +18 -4
  146. package/src/lib/name.ts +27 -0
  147. package/src/lib/picker.ts +133 -0
  148. package/src/lib/resolve.ts +285 -0
  149. package/src/lib/updater.ts +106 -0
  150. package/test/cli.test.ts +491 -0
  151. package/test/fixtures/hello-app/Dockerfile +5 -0
  152. package/test/fixtures/hello-app/index.js +5 -0
  153. package/test/unit/api.test.ts +66 -0
  154. package/test/unit/config.test.ts +94 -0
  155. package/test/unit/init.test.ts +211 -0
  156. package/test/unit/json.test.ts +208 -0
  157. package/test/unit/picker.test.ts +161 -0
  158. package/test/unit/resolve.test.ts +124 -0
  159. package/test/unit/service-set.test.ts +355 -0
  160. package/vitest.config.ts +10 -0
  161. package/dist/commands/connect.d.ts +0 -2
  162. package/dist/commands/connect.js +0 -117
  163. package/dist/commands/connect.js.map +0 -1
  164. package/dist/commands/context.d.ts +0 -2
  165. package/dist/commands/context.js +0 -71
  166. package/dist/commands/context.js.map +0 -1
  167. package/dist/commands/deploy.d.ts +0 -2
  168. package/dist/commands/deploy.js +0 -120
  169. package/dist/commands/deploy.js.map +0 -1
  170. package/dist/commands/destroy.d.ts +0 -2
  171. package/dist/commands/destroy.js +0 -51
  172. package/dist/commands/destroy.js.map +0 -1
  173. package/dist/commands/update.d.ts +0 -2
  174. package/dist/commands/update.js +0 -41
  175. package/dist/commands/update.js.map +0 -1
  176. package/dist/commands/version.d.ts +0 -2
  177. package/dist/commands/version.js +0 -37
  178. package/dist/commands/version.js.map +0 -1
  179. package/src/commands/connect.ts +0 -145
  180. package/src/commands/context.ts +0 -93
  181. package/src/commands/deploy.ts +0 -153
  182. package/src/commands/destroy.ts +0 -51
  183. package/src/commands/update.ts +0 -44
  184. package/src/commands/version.ts +0 -37
package/dist/lib/api.js CHANGED
@@ -1,18 +1,42 @@
1
1
  import { getToken } from "./auth.js";
2
+ import { CURRENT_VERSION } from "./updater.js";
3
+ import * as https from "node:https";
4
+ import * as http from "node:http";
2
5
  const DEFAULT_BASE_URL = "https://lizard.build";
3
- const USER_AGENT = "lizard-cli/0.1";
6
+ const USER_AGENT = `lizard-cli/${CURRENT_VERSION}`;
4
7
  let baseURL = process.env.LIZARD_API_URL || DEFAULT_BASE_URL;
5
8
  let _accessToken = null;
6
9
  export function setBaseURL(url) { baseURL = url; }
7
10
  export function getBaseURL() { return baseURL; }
8
11
  export function setAccessToken(token) { _accessToken = token; }
12
+ export function withQuery(path, params) {
13
+ const search = new URLSearchParams();
14
+ for (const [key, value] of Object.entries(params)) {
15
+ if (value === null || value === undefined || value === "")
16
+ continue;
17
+ search.set(key, String(value));
18
+ }
19
+ const query = search.toString();
20
+ if (!query)
21
+ return path;
22
+ return `${path}${path.includes("?") ? "&" : "?"}${query}`;
23
+ }
24
+ export function withScope(path, scope) {
25
+ if (!scope)
26
+ return path;
27
+ return withQuery(path, {
28
+ workspaceId: scope.workspaceId,
29
+ });
30
+ }
9
31
  export class APIError extends Error {
10
32
  status;
11
33
  code;
12
- constructor(status, message, code = "") {
34
+ body;
35
+ constructor(status, message, code = "", body = null) {
13
36
  super(message);
14
37
  this.status = status;
15
38
  this.code = code;
39
+ this.body = body;
16
40
  }
17
41
  }
18
42
  export function isNotFound(err) {
@@ -21,11 +45,12 @@ export function isNotFound(err) {
21
45
  export function isAuthError(err) {
22
46
  return err instanceof APIError && (err.status === 401 || err.status === 403);
23
47
  }
24
- async function request(method, path, body) {
48
+ async function request(method, path, body, extraHeaders = {}) {
25
49
  const url = baseURL + path;
26
50
  const token = _accessToken || getToken();
27
51
  const headers = {
28
52
  "User-Agent": USER_AGENT,
53
+ ...extraHeaders,
29
54
  };
30
55
  if (token) {
31
56
  headers["Authorization"] = `Bearer ${token}`;
@@ -41,13 +66,15 @@ async function request(method, path, body) {
41
66
  if (!res.ok) {
42
67
  let msg = res.statusText;
43
68
  let code = "";
69
+ let body = null;
44
70
  try {
45
71
  const j = (await res.json());
72
+ body = j;
46
73
  msg = j.error || j.message || msg;
47
74
  code = j.code || "";
48
75
  }
49
76
  catch { }
50
- throw new APIError(res.status, msg, code);
77
+ throw new APIError(res.status, msg, code, body);
51
78
  }
52
79
  const text = await res.text();
53
80
  if (!text)
@@ -56,59 +83,66 @@ async function request(method, path, body) {
56
83
  }
57
84
  export const api = {
58
85
  get: (path) => request("GET", path),
59
- post: (path, body) => request("POST", path, body),
86
+ post: (path, body, headers) => request("POST", path, body, headers),
60
87
  put: (path, body) => request("PUT", path, body),
61
88
  patch: (path, body) => request("PATCH", path, body),
62
89
  delete: (path) => request("DELETE", path),
63
90
  };
64
91
  /** Stream SSE and call handler for each data line. Return false to stop. */
65
- export async function streamSSE(path, handler) {
66
- const url = baseURL + path;
67
- const token = _accessToken || getToken();
68
- const headers = {
69
- "User-Agent": USER_AGENT,
70
- Accept: "text/event-stream",
71
- };
72
- if (token)
73
- headers["Authorization"] = `Bearer ${token}`;
74
- const res = await fetch(url, { headers });
75
- if (!res.ok) {
76
- throw new APIError(res.status, `SSE failed: ${res.statusText}`);
77
- }
78
- if (!res.body)
79
- return;
80
- const reader = res.body.getReader();
81
- const decoder = new TextDecoder();
82
- let buffer = "";
83
- let currentEvent = "";
84
- let currentData = "";
85
- while (true) {
86
- const { done, value } = await reader.read();
87
- if (done)
88
- break;
89
- buffer += decoder.decode(value, { stream: true });
90
- const lines = buffer.split("\n");
91
- buffer = lines.pop() || "";
92
- for (const line of lines) {
93
- const trimmed = line.replace(/\r$/, "");
94
- if (trimmed === "") {
95
- if (currentData) {
96
- const cont = handler(currentEvent, currentData);
97
- if (cont === false) {
98
- reader.cancel();
99
- return;
92
+ export function streamSSE(path, handler) {
93
+ return new Promise((resolve, reject) => {
94
+ const url = new URL(baseURL + path);
95
+ const token = _accessToken || getToken();
96
+ const reqHeaders = {
97
+ "User-Agent": USER_AGENT,
98
+ Accept: "text/event-stream",
99
+ };
100
+ if (token)
101
+ reqHeaders["Authorization"] = `Bearer ${token}`;
102
+ const transport = url.protocol === "https:" ? https : http;
103
+ const req = transport.request({ hostname: url.hostname, port: url.port || (url.protocol === "https:" ? 443 : 80),
104
+ path: url.pathname + url.search, method: "GET", headers: reqHeaders }, (res) => {
105
+ if (res.statusCode && res.statusCode >= 400) {
106
+ let body = "";
107
+ res.on("data", (c) => body += c.toString());
108
+ res.on("end", () => reject(new APIError(res.statusCode, `SSE failed: ${body}`)));
109
+ return;
110
+ }
111
+ let buffer = "";
112
+ let currentEvent = "";
113
+ let currentData = "";
114
+ res.setEncoding("utf8");
115
+ res.on("data", (chunk) => {
116
+ buffer += chunk;
117
+ const lines = buffer.split("\n");
118
+ buffer = lines.pop() ?? "";
119
+ for (const line of lines) {
120
+ const trimmed = line.replace(/\r$/, "");
121
+ if (trimmed === "") {
122
+ if (currentData) {
123
+ const cont = handler(currentEvent, currentData);
124
+ if (cont === false) {
125
+ req.destroy();
126
+ resolve();
127
+ return;
128
+ }
129
+ }
130
+ currentEvent = "";
131
+ currentData = "";
132
+ }
133
+ else if (trimmed.startsWith("event:")) {
134
+ currentEvent = trimmed.slice(6).trim();
135
+ }
136
+ else if (trimmed.startsWith("data:")) {
137
+ currentData = trimmed.slice(5).trimStart();
100
138
  }
101
139
  }
102
- currentEvent = "";
103
- currentData = "";
104
- }
105
- else if (trimmed.startsWith("event:")) {
106
- currentEvent = trimmed.slice(6).trim();
107
- }
108
- else if (trimmed.startsWith("data:")) {
109
- currentData = trimmed.slice(5).trimStart();
110
- }
111
- }
112
- }
140
+ });
141
+ res.on("end", resolve);
142
+ res.on("error", reject);
143
+ });
144
+ req.on("error", reject);
145
+ req.end();
146
+ });
113
147
  }
114
148
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,6 @@
1
- export interface Credentials {
2
- accessToken: string;
3
- refreshToken?: string;
4
- expiresAt?: string;
5
- userId: string;
6
- username: string;
7
- email?: string;
8
- avatarUrl?: string;
9
- }
10
- export declare function setTokenOverride(token: string): void;
11
- /** Get the active token in priority order: override → env → file */
1
+ import { type Credentials } from "./config.js";
2
+ export type { Credentials } from "./config.js";
3
+ /** Get the active token in priority order: env → file */
12
4
  export declare function getToken(): string | null;
13
5
  export declare function loadCredentials(): Credentials | null;
14
6
  export declare function saveCredentials(creds: Credentials): void;
package/dist/lib/auth.js CHANGED
@@ -1,42 +1,23 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import os from "node:os";
4
1
  import open from "open";
5
- const LIZARD_DIR = path.join(os.homedir(), ".lizard");
6
- const CREDENTIALS_FILE = path.join(LIZARD_DIR, "credentials.json");
7
- let tokenOverride = null;
8
- export function setTokenOverride(token) {
9
- tokenOverride = token;
10
- }
11
- /** Get the active token in priority order: override → env → file */
2
+ import { loadConfig, saveConfig, } from "./config.js";
3
+ /** Get the active token in priority order: env → file */
12
4
  export function getToken() {
13
- if (tokenOverride)
14
- return tokenOverride;
15
5
  if (process.env.LIZARD_TOKEN)
16
6
  return process.env.LIZARD_TOKEN;
17
- const creds = loadCredentials();
18
- return creds?.accessToken ?? null;
7
+ return loadCredentials()?.accessToken ?? null;
19
8
  }
20
9
  export function loadCredentials() {
21
- try {
22
- const data = fs.readFileSync(CREDENTIALS_FILE, "utf-8");
23
- return JSON.parse(data);
24
- }
25
- catch {
26
- return null;
27
- }
10
+ return loadConfig().credentials ?? null;
28
11
  }
29
12
  export function saveCredentials(creds) {
30
- fs.mkdirSync(LIZARD_DIR, { recursive: true });
31
- fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), {
32
- mode: 0o600,
33
- });
13
+ const config = loadConfig();
14
+ config.credentials = creds;
15
+ saveConfig(config);
34
16
  }
35
17
  export function clearCredentials() {
36
- try {
37
- fs.unlinkSync(CREDENTIALS_FILE);
38
- }
39
- catch { }
18
+ const config = loadConfig();
19
+ delete config.credentials;
20
+ saveConfig(config);
40
21
  }
41
22
  export function isLoggedIn() {
42
23
  return getToken() !== null;
@@ -49,10 +30,9 @@ function isTTY() {
49
30
  * Returns credentials or throws.
50
31
  */
51
32
  export async function requireAuth() {
52
- // Token override or env var — we don't have full Credentials, fake it
53
- if (tokenOverride || process.env.LIZARD_TOKEN) {
33
+ if (process.env.LIZARD_TOKEN) {
54
34
  return {
55
- accessToken: (tokenOverride || process.env.LIZARD_TOKEN),
35
+ accessToken: process.env.LIZARD_TOKEN,
56
36
  userId: "",
57
37
  username: "",
58
38
  };
@@ -60,11 +40,11 @@ export async function requireAuth() {
60
40
  const creds = loadCredentials();
61
41
  if (creds)
62
42
  return creds;
63
- // Not logged in
64
43
  if (!isTTY()) {
65
- throw new Error("Not authenticated. Set LIZARD_TOKEN or run `lizard login` first.");
44
+ const err = new Error("Not authenticated. Set LIZARD_TOKEN or run `lizard login` first.");
45
+ err.code = "NOT_AUTHENTICATED";
46
+ throw err;
66
47
  }
67
- // Auto-login
68
48
  const { performLogin } = await import("../commands/login.js");
69
49
  return performLogin();
70
50
  }
@@ -76,7 +56,7 @@ export async function openURL(url) {
76
56
  !process.env.DISPLAY &&
77
57
  !process.env.WAYLAND_DISPLAY;
78
58
  if (isSSH || isCI || noDisplay) {
79
- return false; // caller should show URL manually
59
+ return false;
80
60
  }
81
61
  try {
82
62
  await open(url);
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,UAAU,EACV,UAAU,GAEX,MAAM,aAAa,CAAC;AAIrB,yDAAyD;AACzD,MAAM,UAAU,QAAQ;IACtB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC9D,OAAO,eAAe,EAAE,EAAE,WAAW,IAAI,IAAI,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,EAAE,CAAC,WAAW,IAAI,IAAI,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;IAC3B,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,WAAW,CAAC;IAC1B,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,EAAE,KAAK,IAAI,CAAC;AAC7B,CAAC;AAED,SAAS,KAAK;IACZ,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;YACrC,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;SACb,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IAExB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,KAAK,CACnB,kEAAkE,CACvC,CAAC;QAC9B,GAAG,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAC9D,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,MAAM,KAAK,GAAG,OAAO,CACnB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAC5E,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,SAAS,GACb,OAAO,CAAC,QAAQ,KAAK,OAAO;QAC5B,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO;QACpB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAE/B,IAAI,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,23 +1,44 @@
1
- export interface ProjectConfig {
2
- workspaceId?: string;
1
+ export declare const DEFAULT_REGION = "us-east-1";
2
+ export interface Credentials {
3
+ accessToken: string;
4
+ refreshToken?: string;
5
+ expiresAt?: string;
6
+ userId: string;
7
+ username: string;
8
+ email?: string;
9
+ avatarUrl?: string;
10
+ }
11
+ export interface ProjectLink {
3
12
  projectId: string;
4
13
  projectName?: string;
5
- environment?: string;
14
+ /** Workspace the project belongs to. Lazy-filled for legacy links. */
15
+ workspaceId?: string;
16
+ workspaceName?: string;
17
+ /** Active service for this cwd. `appId/appName` are kept as aliases for backwards compat. */
18
+ serviceId?: string;
19
+ serviceName?: string;
20
+ /** @deprecated use serviceId */
21
+ appId?: string;
22
+ /** @deprecated use serviceName */
23
+ appName?: string;
6
24
  }
7
- export interface GlobalSettings {
8
- defaultWorkspace?: string;
25
+ export interface Config {
26
+ credentials?: Credentials;
27
+ projects?: Record<string, ProjectLink>;
9
28
  }
10
- /** Find project config by walking up from cwd */
11
- export declare function findProjectConfig(): ProjectConfig | null;
12
- /** Save project config in cwd */
13
- export declare function saveProjectConfig(config: ProjectConfig): void;
14
- export declare function loadGlobalSettings(): GlobalSettings;
15
- export declare function saveGlobalSettings(settings: GlobalSettings): void;
29
+ export declare function loadConfig(): Config;
30
+ export declare function saveConfig(config: Config): void;
16
31
  /**
17
- * Resolve projectId from: --project flag .lizard/config.json → error
32
+ * Read the link for a directory. Normalises legacy `appId/appName` into
33
+ * `serviceId/serviceName` so callers only have to look at one pair.
18
34
  */
19
- export declare function resolveProjectId(flagValue?: string): string;
35
+ export declare function getProjectLink(cwd?: string): ProjectLink | null;
36
+ export declare function setProjectLink(link: ProjectLink, cwd?: string): void;
37
+ export declare function updateProjectLink(patch: Partial<ProjectLink>, cwd?: string): void;
38
+ export declare function clearProjectLink(cwd?: string): void;
20
39
  /**
21
- * Resolve environment from: --environment flag .lizard/config.json "production"
40
+ * Resolve a project flag (name, slug, or ID) to an actual project ID.
41
+ * When no flag is given, falls back to the linked cwd. Hits the API only
42
+ * when a flag is provided so name/slug lookups work as advertised.
22
43
  */
23
- export declare function resolveEnvironment(flagValue?: string): string;
44
+ export declare function resolveProjectId(flagValue?: string): Promise<string>;
@@ -1,77 +1,90 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import os from "node:os";
4
- const CONFIG_DIR = ".lizard";
5
- const CONFIG_FILE = "config.json";
6
- const GLOBAL_SETTINGS_FILE = path.join(os.homedir(), ".lizard", "settings.json");
7
- /** Find project config by walking up from cwd */
8
- export function findProjectConfig() {
9
- let dir = process.cwd();
10
- while (true) {
11
- const configPath = path.join(dir, CONFIG_DIR, CONFIG_FILE);
12
- if (fs.existsSync(configPath)) {
13
- try {
14
- return JSON.parse(fs.readFileSync(configPath, "utf-8"));
15
- }
16
- catch {
17
- return null;
18
- }
19
- }
20
- const parent = path.dirname(dir);
21
- if (parent === dir)
22
- break;
23
- dir = parent;
24
- }
25
- return null;
4
+ export const DEFAULT_REGION = "us-east-1";
5
+ // Resolve at every call so tests (and exotic shells that mutate HOME) get a
6
+ // fresh path. Cost is negligible — we hit disk anyway. LIZARD_HOME lets tests
7
+ // (and power users) point the config dir somewhere other than ~/.lizard.
8
+ function configDir() {
9
+ return process.env.LIZARD_HOME
10
+ ? path.join(process.env.LIZARD_HOME, ".lizard")
11
+ : path.join(os.homedir(), ".lizard");
26
12
  }
27
- /** Save project config in cwd */
28
- export function saveProjectConfig(config) {
29
- const dir = path.join(process.cwd(), CONFIG_DIR);
30
- fs.mkdirSync(dir, { recursive: true });
31
- fs.writeFileSync(path.join(dir, CONFIG_FILE), JSON.stringify(config, null, 2));
32
- // Add .lizard/ to .gitignore if not already there
33
- const gitignorePath = path.join(process.cwd(), ".gitignore");
34
- try {
35
- const existing = fs.existsSync(gitignorePath)
36
- ? fs.readFileSync(gitignorePath, "utf-8")
37
- : "";
38
- if (!existing.includes(".lizard/")) {
39
- fs.appendFileSync(gitignorePath, (existing.endsWith("\n") ? "" : "\n") + ".lizard/\n");
40
- }
41
- }
42
- catch { }
13
+ function configFile() {
14
+ return path.join(configDir(), "config.json");
43
15
  }
44
- export function loadGlobalSettings() {
16
+ export function loadConfig() {
45
17
  try {
46
- return JSON.parse(fs.readFileSync(GLOBAL_SETTINGS_FILE, "utf-8"));
18
+ return JSON.parse(fs.readFileSync(configFile(), "utf-8"));
47
19
  }
48
20
  catch {
49
21
  return {};
50
22
  }
51
23
  }
52
- export function saveGlobalSettings(settings) {
53
- const dir = path.dirname(GLOBAL_SETTINGS_FILE);
54
- fs.mkdirSync(dir, { recursive: true });
55
- fs.writeFileSync(GLOBAL_SETTINGS_FILE, JSON.stringify(settings, null, 2));
24
+ export function saveConfig(config) {
25
+ fs.mkdirSync(configDir(), { recursive: true });
26
+ fs.writeFileSync(configFile(), JSON.stringify(config, null, 2), {
27
+ mode: 0o600,
28
+ });
56
29
  }
57
30
  /**
58
- * Resolve projectId from: --project flag .lizard/config.json → error
31
+ * Read the link for a directory. Normalises legacy `appId/appName` into
32
+ * `serviceId/serviceName` so callers only have to look at one pair.
59
33
  */
60
- export function resolveProjectId(flagValue) {
61
- if (flagValue)
62
- return flagValue;
63
- const config = findProjectConfig();
64
- if (config?.projectId)
65
- return config.projectId;
66
- throw new Error("No project linked. Run `lizard init` or `lizard link` first, or use --project <id>.");
34
+ export function getProjectLink(cwd = process.cwd()) {
35
+ const raw = loadConfig().projects?.[cwd];
36
+ if (!raw)
37
+ return null;
38
+ return {
39
+ ...raw,
40
+ serviceId: raw.serviceId ?? raw.appId,
41
+ serviceName: raw.serviceName ?? raw.appName,
42
+ };
43
+ }
44
+ export function setProjectLink(link, cwd = process.cwd()) {
45
+ const config = loadConfig();
46
+ config.projects ??= {};
47
+ // Mirror service↔app for older readers.
48
+ const normalised = {
49
+ ...link,
50
+ appId: link.serviceId ?? link.appId,
51
+ appName: link.serviceName ?? link.appName,
52
+ serviceId: link.serviceId ?? link.appId,
53
+ serviceName: link.serviceName ?? link.appName,
54
+ };
55
+ config.projects[cwd] = normalised;
56
+ saveConfig(config);
57
+ }
58
+ export function updateProjectLink(patch, cwd = process.cwd()) {
59
+ const existing = getProjectLink(cwd);
60
+ if (!existing)
61
+ return;
62
+ setProjectLink({ ...existing, ...patch }, cwd);
63
+ }
64
+ export function clearProjectLink(cwd = process.cwd()) {
65
+ const config = loadConfig();
66
+ if (config.projects) {
67
+ delete config.projects[cwd];
68
+ saveConfig(config);
69
+ }
67
70
  }
68
71
  /**
69
- * Resolve environment from: --environment flag .lizard/config.json "production"
72
+ * Resolve a project flag (name, slug, or ID) to an actual project ID.
73
+ * When no flag is given, falls back to the linked cwd. Hits the API only
74
+ * when a flag is provided so name/slug lookups work as advertised.
70
75
  */
71
- export function resolveEnvironment(flagValue) {
72
- if (flagValue)
73
- return flagValue;
74
- const config = findProjectConfig();
75
- return config?.environment ?? "production";
76
+ export async function resolveProjectId(flagValue) {
77
+ if (!flagValue) {
78
+ const link = getProjectLink();
79
+ if (link?.projectId)
80
+ return link.projectId;
81
+ throw new Error("No project linked. Run `lizard init` or pass --project <id>.");
82
+ }
83
+ const { api } = await import("./api.js");
84
+ const projects = await api.get("/api/projects");
85
+ const match = projects.find((p) => p.id === flagValue || p.slug === flagValue || p.name === flagValue);
86
+ if (!match)
87
+ throw new Error(`Project "${flagValue}" not found.`);
88
+ return match.id;
76
89
  }
77
90
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export declare function success(msg: string): void;
6
6
  export declare function error(msg: string): void;
7
7
  export declare function warn(msg: string): void;
8
8
  export declare function info(msg: string): void;
9
+ export declare function link(url: string, text?: string): string;
9
10
  export declare function table(headers: string[], rows: string[][]): void;
10
11
  export declare function statusColor(status: string): string;
11
12
  export declare function timeAgo(ts: number | string): string;
@@ -28,24 +28,37 @@ export function info(msg) {
28
28
  return;
29
29
  process.stderr.write(msg + "\n");
30
30
  }
31
+ export function link(url, text) {
32
+ const label = text ?? url;
33
+ if (!isTTY())
34
+ return label;
35
+ return `\x1b]8;;${url}\x1b\\${label}\x1b]8;;\x1b\\`;
36
+ }
37
+ const ANSI_RE = /\x1b\[[0-9;]*m/g;
38
+ function visibleLength(s) {
39
+ return s.replace(ANSI_RE, "").length;
40
+ }
41
+ function padVisible(s, width) {
42
+ return s + " ".repeat(Math.max(0, width - visibleLength(s)));
43
+ }
31
44
  export function table(headers, rows) {
32
45
  if (rows.length === 0)
33
46
  return;
34
- const widths = headers.map((h) => h.length);
47
+ const widths = headers.map((h) => visibleLength(h));
35
48
  for (const row of rows) {
36
49
  for (let i = 0; i < row.length; i++) {
37
50
  if (i < widths.length) {
38
- widths[i] = Math.max(widths[i], (row[i] || "").length);
51
+ widths[i] = Math.max(widths[i], visibleLength(row[i] || ""));
39
52
  }
40
53
  }
41
54
  }
42
55
  const header = headers
43
- .map((h, i) => h.toUpperCase().padEnd(widths[i]))
56
+ .map((h, i) => padVisible(h.toUpperCase(), widths[i]))
44
57
  .join(" ");
45
58
  console.log(chalk.dim(header));
46
59
  for (const row of rows) {
47
60
  const line = headers
48
- .map((_, i) => (row[i] || "").padEnd(widths[i]))
61
+ .map((_, i) => padVisible(row[i] || "", widths[i]))
49
62
  .join(" ");
50
63
  console.log(line);
51
64
  }