@lizard-build/cli 0.1.0 → 0.3.29

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 (178) hide show
  1. package/.github/workflows/release.yml +90 -0
  2. package/README.md +41 -0
  3. package/dist/commands/add.js +318 -45
  4. package/dist/commands/add.js.map +1 -1
  5. package/dist/commands/config.d.ts +2 -0
  6. package/dist/commands/config.js +68 -0
  7. package/dist/commands/config.js.map +1 -0
  8. package/dist/commands/docs.d.ts +2 -0
  9. package/dist/commands/docs.js +13 -0
  10. package/dist/commands/docs.js.map +1 -0
  11. package/dist/commands/domain.d.ts +9 -0
  12. package/dist/commands/domain.js +195 -0
  13. package/dist/commands/domain.js.map +1 -0
  14. package/dist/commands/git.js +175 -36
  15. package/dist/commands/git.js.map +1 -1
  16. package/dist/commands/init.d.ts +24 -0
  17. package/dist/commands/init.js +128 -86
  18. package/dist/commands/init.js.map +1 -1
  19. package/dist/commands/link.d.ts +7 -0
  20. package/dist/commands/link.js +104 -33
  21. package/dist/commands/link.js.map +1 -1
  22. package/dist/commands/login.js +4 -3
  23. package/dist/commands/login.js.map +1 -1
  24. package/dist/commands/logs.js +223 -30
  25. package/dist/commands/logs.js.map +1 -1
  26. package/dist/commands/open.js +3 -2
  27. package/dist/commands/open.js.map +1 -1
  28. package/dist/commands/port.d.ts +7 -0
  29. package/dist/commands/port.js +49 -0
  30. package/dist/commands/port.js.map +1 -0
  31. package/dist/commands/projects.js +36 -6
  32. package/dist/commands/projects.js.map +1 -1
  33. package/dist/commands/ps.js +32 -39
  34. package/dist/commands/ps.js.map +1 -1
  35. package/dist/commands/redeploy.js +48 -8
  36. package/dist/commands/redeploy.js.map +1 -1
  37. package/dist/commands/regions.js +2 -5
  38. package/dist/commands/regions.js.map +1 -1
  39. package/dist/commands/restart.js +84 -10
  40. package/dist/commands/restart.js.map +1 -1
  41. package/dist/commands/run.d.ts +9 -0
  42. package/dist/commands/run.js +61 -22
  43. package/dist/commands/run.js.map +1 -1
  44. package/dist/commands/scale.d.ts +10 -0
  45. package/dist/commands/scale.js +166 -0
  46. package/dist/commands/scale.js.map +1 -0
  47. package/dist/commands/secrets.js +200 -89
  48. package/dist/commands/secrets.js.map +1 -1
  49. package/dist/commands/service-set.d.ts +49 -0
  50. package/dist/commands/service-set.js +552 -0
  51. package/dist/commands/service-set.js.map +1 -0
  52. package/dist/commands/service-show.d.ts +11 -0
  53. package/dist/commands/service-show.js +44 -0
  54. package/dist/commands/service-show.js.map +1 -0
  55. package/dist/commands/service.d.ts +8 -0
  56. package/dist/commands/service.js +262 -0
  57. package/dist/commands/service.js.map +1 -0
  58. package/dist/commands/ssh.d.ts +2 -0
  59. package/dist/commands/ssh.js +161 -0
  60. package/dist/commands/ssh.js.map +1 -0
  61. package/dist/commands/status.d.ts +7 -0
  62. package/dist/commands/status.js +49 -38
  63. package/dist/commands/status.js.map +1 -1
  64. package/dist/commands/unlink.d.ts +5 -0
  65. package/dist/commands/unlink.js +18 -0
  66. package/dist/commands/unlink.js.map +1 -0
  67. package/dist/commands/up.d.ts +9 -0
  68. package/dist/commands/up.js +417 -0
  69. package/dist/commands/up.js.map +1 -0
  70. package/dist/commands/upgrade.d.ts +2 -0
  71. package/dist/commands/upgrade.js +79 -0
  72. package/dist/commands/upgrade.js.map +1 -0
  73. package/dist/commands/whoami.js +26 -6
  74. package/dist/commands/whoami.js.map +1 -1
  75. package/dist/commands/workspace.d.ts +8 -0
  76. package/dist/commands/workspace.js +36 -0
  77. package/dist/commands/workspace.js.map +1 -0
  78. package/dist/index.js +204 -82
  79. package/dist/index.js.map +1 -1
  80. package/dist/lib/api.d.ts +17 -2
  81. package/dist/lib/api.js +85 -51
  82. package/dist/lib/api.js.map +1 -1
  83. package/dist/lib/auth.d.ts +3 -11
  84. package/dist/lib/auth.js +16 -36
  85. package/dist/lib/auth.js.map +1 -1
  86. package/dist/lib/config.d.ts +36 -15
  87. package/dist/lib/config.js +71 -58
  88. package/dist/lib/config.js.map +1 -1
  89. package/dist/lib/format.d.ts +1 -0
  90. package/dist/lib/format.js +17 -4
  91. package/dist/lib/format.js.map +1 -1
  92. package/dist/lib/name.d.ts +11 -0
  93. package/dist/lib/name.js +26 -0
  94. package/dist/lib/name.js.map +1 -0
  95. package/dist/lib/picker.d.ts +32 -0
  96. package/dist/lib/picker.js +91 -0
  97. package/dist/lib/picker.js.map +1 -0
  98. package/dist/lib/resolve.d.ts +85 -0
  99. package/dist/lib/resolve.js +203 -0
  100. package/dist/lib/resolve.js.map +1 -0
  101. package/dist/lib/updater.d.ts +16 -0
  102. package/dist/lib/updater.js +102 -0
  103. package/dist/lib/updater.js.map +1 -0
  104. package/lizard-wrapper.sh +2 -0
  105. package/package.json +11 -3
  106. package/src/commands/add.ts +388 -56
  107. package/src/commands/config.ts +80 -0
  108. package/src/commands/docs.ts +15 -0
  109. package/src/commands/domain.ts +248 -0
  110. package/src/commands/git.ts +201 -40
  111. package/src/commands/init.ts +149 -100
  112. package/src/commands/link.ts +127 -35
  113. package/src/commands/login.ts +4 -3
  114. package/src/commands/logs.ts +283 -27
  115. package/src/commands/open.ts +3 -2
  116. package/src/commands/port.ts +57 -0
  117. package/src/commands/projects.ts +43 -6
  118. package/src/commands/ps.ts +39 -60
  119. package/src/commands/redeploy.ts +51 -10
  120. package/src/commands/regions.ts +2 -6
  121. package/src/commands/restart.ts +84 -10
  122. package/src/commands/run.ts +68 -24
  123. package/src/commands/scale.ts +216 -0
  124. package/src/commands/secrets.ts +277 -100
  125. package/src/commands/service-set.ts +669 -0
  126. package/src/commands/service-show.ts +52 -0
  127. package/src/commands/service.ts +298 -0
  128. package/src/commands/ssh.ts +176 -0
  129. package/src/commands/status.ts +51 -46
  130. package/src/commands/unlink.ts +17 -0
  131. package/src/commands/up.ts +461 -0
  132. package/src/commands/upgrade.ts +87 -0
  133. package/src/commands/whoami.ts +34 -6
  134. package/src/commands/workspace.ts +44 -0
  135. package/src/index.ts +214 -85
  136. package/src/lib/api.ts +114 -51
  137. package/src/lib/auth.ts +22 -46
  138. package/src/lib/config.ts +100 -65
  139. package/src/lib/format.ts +18 -4
  140. package/src/lib/name.ts +27 -0
  141. package/src/lib/picker.ts +133 -0
  142. package/src/lib/resolve.ts +285 -0
  143. package/src/lib/updater.ts +106 -0
  144. package/test/cli.test.ts +491 -0
  145. package/test/fixtures/hello-app/Dockerfile +5 -0
  146. package/test/fixtures/hello-app/index.js +5 -0
  147. package/test/unit/api.test.ts +66 -0
  148. package/test/unit/config.test.ts +94 -0
  149. package/test/unit/init.test.ts +211 -0
  150. package/test/unit/json.test.ts +208 -0
  151. package/test/unit/picker.test.ts +161 -0
  152. package/test/unit/resolve.test.ts +124 -0
  153. package/test/unit/service-set.test.ts +355 -0
  154. package/vitest.config.ts +10 -0
  155. package/dist/commands/connect.d.ts +0 -2
  156. package/dist/commands/connect.js +0 -117
  157. package/dist/commands/connect.js.map +0 -1
  158. package/dist/commands/context.d.ts +0 -2
  159. package/dist/commands/context.js +0 -71
  160. package/dist/commands/context.js.map +0 -1
  161. package/dist/commands/deploy.d.ts +0 -2
  162. package/dist/commands/deploy.js +0 -120
  163. package/dist/commands/deploy.js.map +0 -1
  164. package/dist/commands/destroy.d.ts +0 -2
  165. package/dist/commands/destroy.js +0 -51
  166. package/dist/commands/destroy.js.map +0 -1
  167. package/dist/commands/update.d.ts +0 -2
  168. package/dist/commands/update.js +0 -41
  169. package/dist/commands/update.js.map +0 -1
  170. package/dist/commands/version.d.ts +0 -2
  171. package/dist/commands/version.js +0 -37
  172. package/dist/commands/version.js.map +0 -1
  173. package/src/commands/connect.ts +0 -145
  174. package/src/commands/context.ts +0 -93
  175. package/src/commands/deploy.ts +0 -153
  176. package/src/commands/destroy.ts +0 -51
  177. package/src/commands/update.ts +0 -44
  178. package/src/commands/version.ts +0 -37
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAE7C,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,OAAO,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * `lizard domain` — domain management.
4
+ * bare → if no domain, auto-generate one; otherwise show current
5
+ * <hostname> → attach a custom domain
6
+ * delete <h> → remove a domain
7
+ * generate → force-generate a fresh *.onlizard.com subdomain
8
+ */
9
+ export declare function registerDomain(program: Command): void;
@@ -0,0 +1,195 @@
1
+ import chalk from "chalk";
2
+ import * as p from "@clack/prompts";
3
+ import { api } from "../lib/api.js";
4
+ import { resolveProjectId } from "../lib/config.js";
5
+ import { getActiveService } from "../lib/resolve.js";
6
+ import { success, isJSONMode, printJSON, isTTY } from "../lib/format.js";
7
+ /**
8
+ * `lizard domain` — domain management.
9
+ * bare → if no domain, auto-generate one; otherwise show current
10
+ * <hostname> → attach a custom domain
11
+ * delete <h> → remove a domain
12
+ * generate → force-generate a fresh *.onlizard.com subdomain
13
+ */
14
+ export function registerDomain(program) {
15
+ const dom = program
16
+ .command("domain")
17
+ .alias("domains")
18
+ .argument("[hostname]", "Custom domain to attach (e.g. app.example.com)")
19
+ .description("Manage service domains")
20
+ .option("-s, --service <name>", "Service name or ID")
21
+ .option("-p, --project <id>", "Project name, slug, or ID")
22
+ .option("--port <n>", "Port to expose", parseIntOption)
23
+ .action(async (hostname, opts, _cmd) => {
24
+ const projectId = await resolveProjectId(opts.project);
25
+ const service = await getActiveService(opts.service, projectId);
26
+ if (!hostname) {
27
+ // Bare `lizard domain` — show or auto-generate.
28
+ const appRow = await api
29
+ .get(`/api/apps/${service.id}`)
30
+ .catch(() => null);
31
+ const existing = appRow?.domain;
32
+ if (existing) {
33
+ if (isJSONMode()) {
34
+ printJSON({ hostname: existing, generated: false });
35
+ }
36
+ else {
37
+ console.log(chalk.cyan(`https://${existing}`));
38
+ console.log(chalk.dim(` Reference from other services: ${chalk.cyan(`\${{${service.name}.LIZARD_PUBLIC_DOMAIN}}`)}`));
39
+ }
40
+ return;
41
+ }
42
+ const result = await api
43
+ .post(`/api/apps/${service.id}/domains`, { generate: true })
44
+ .catch((err) => {
45
+ if (err?.status === 404) {
46
+ throw new Error("Domain endpoint not yet implemented. The API needs " +
47
+ "`POST /api/apps/{id}/domains` with body { generate: true }.");
48
+ }
49
+ throw err;
50
+ });
51
+ if (isJSONMode()) {
52
+ printJSON(result);
53
+ }
54
+ else {
55
+ success(`Domain generated: ${chalk.cyan(`https://${result.hostname}`)}`);
56
+ console.log(chalk.dim(` Reference from other services: ${chalk.cyan(`\${{${service.name}.LIZARD_PUBLIC_DOMAIN}}`)}`));
57
+ }
58
+ return;
59
+ }
60
+ // Attach custom hostname
61
+ const result = await api
62
+ .post(`/api/apps/${service.id}/domains`, {
63
+ hostname,
64
+ port: opts.port,
65
+ })
66
+ .catch((err) => {
67
+ if (err?.status === 404) {
68
+ throw new Error("Domain endpoint not yet implemented. The API needs " +
69
+ "`POST /api/apps/{id}/domains` with body { hostname }.");
70
+ }
71
+ throw err;
72
+ });
73
+ if (isJSONMode()) {
74
+ printJSON(result);
75
+ return;
76
+ }
77
+ // Custom domain — print verification + DNS instructions
78
+ success(`Custom domain ${chalk.cyan(hostname)} registered (pending verification)`);
79
+ console.log();
80
+ console.log(chalk.bold("1) Verify ownership — add this TXT record at your DNS provider:"));
81
+ console.log(` ${chalk.dim("Name: ")}${chalk.cyan(result.txtRecord || `_lizard-verify.${hostname}`)}`);
82
+ console.log(` ${chalk.dim("Value:")} ${chalk.cyan(result.txtValue || "")}`);
83
+ console.log();
84
+ if (result.cnameTarget) {
85
+ console.log(chalk.bold("2) Point traffic — add this CNAME record:"));
86
+ console.log(` ${chalk.dim("Name: ")}${chalk.cyan(hostname)}`);
87
+ console.log(` ${chalk.dim("Value:")} ${chalk.cyan(result.cnameTarget)}`);
88
+ console.log(chalk.dim(` (${result.cnameTarget} is a multi-A record across all load balancers — no IP to track.)`));
89
+ console.log();
90
+ }
91
+ console.log(chalk.bold("3) Once both records propagate, run:"));
92
+ console.log(` ${chalk.cyan(`lizard domain verify ${hostname}`)}`);
93
+ console.log();
94
+ console.log(chalk.dim("HTTPS certificate will be issued automatically by Let's Encrypt on first request."));
95
+ });
96
+ // Subcommands intentionally don't redeclare -s/-p: Commander 14 binds a
97
+ // duplicate short flag to the parent, leaving the subcommand action with
98
+ // `opts.service === undefined`. Read parent values via optsWithGlobals().
99
+ dom
100
+ .command("generate")
101
+ .description("Generate a fresh *.onlizard.com subdomain")
102
+ .action(async (_opts, sub) => {
103
+ const opts = sub.optsWithGlobals();
104
+ const projectId = await resolveProjectId(opts.project);
105
+ const service = await getActiveService(opts.service, projectId);
106
+ const result = await api
107
+ .post(`/api/apps/${service.id}/domains`, { generate: true })
108
+ .catch((err) => {
109
+ if (err?.status === 404) {
110
+ throw new Error("Domain endpoint not yet implemented. The API needs " +
111
+ "`POST /api/apps/{id}/domains` with body { generate: true }.");
112
+ }
113
+ throw err;
114
+ });
115
+ if (isJSONMode()) {
116
+ printJSON(result);
117
+ }
118
+ else {
119
+ success(`Domain generated: ${chalk.cyan(`https://${result.hostname}`)}`);
120
+ console.log(chalk.dim(` Reference from other services: ${chalk.cyan(`\${{${service.name}.LIZARD_PUBLIC_DOMAIN}}`)}`));
121
+ }
122
+ });
123
+ dom
124
+ .command("verify")
125
+ .argument("<hostname>", "Custom domain to verify")
126
+ .description("Check the TXT record and activate the domain")
127
+ .action(async (hostname, _opts, sub) => {
128
+ const opts = sub.optsWithGlobals();
129
+ const projectId = await resolveProjectId(opts.project);
130
+ const service = await getActiveService(opts.service, projectId);
131
+ const result = await api
132
+ .post(`/api/apps/${service.id}/domains/verify`, { hostname })
133
+ .catch((err) => {
134
+ if (err?.status === 404) {
135
+ throw new Error(`No pending verification for ${hostname}. Run \`lizard domain ${hostname}\` first.`);
136
+ }
137
+ throw err;
138
+ });
139
+ if (isJSONMode()) {
140
+ printJSON(result);
141
+ return;
142
+ }
143
+ if (result.verified) {
144
+ success(`Domain ${chalk.cyan(hostname)} verified and active`);
145
+ console.log(chalk.dim(`https://${hostname} — TLS issues on first HTTPS request.`));
146
+ }
147
+ else {
148
+ console.log(chalk.yellow(`Not verified yet.`));
149
+ if (result.message)
150
+ console.log(chalk.dim(` ${result.message}`));
151
+ }
152
+ });
153
+ dom
154
+ .command("delete")
155
+ .alias("rm")
156
+ .argument("<hostname>", "Domain to remove")
157
+ .description("Remove a domain")
158
+ .option("-y, --yes", "Skip confirmation")
159
+ .action(async (hostname, _opts, sub) => {
160
+ const opts = sub.optsWithGlobals();
161
+ const projectId = await resolveProjectId(opts.project);
162
+ const service = await getActiveService(opts.service, projectId);
163
+ if (!opts.yes) {
164
+ if (!isTTY())
165
+ throw new Error("Use -y to confirm in non-interactive mode");
166
+ const confirm = await p.confirm({
167
+ message: `Remove domain ${chalk.bold(hostname)} from ${chalk.bold(service.name)}?`,
168
+ });
169
+ if (p.isCancel(confirm) || !confirm)
170
+ process.exit(5);
171
+ }
172
+ await api
173
+ .delete(`/api/apps/${service.id}/domains/${encodeURIComponent(hostname)}`)
174
+ .catch((err) => {
175
+ if (err?.status === 404) {
176
+ throw new Error("Domain delete endpoint not yet implemented. The API needs " +
177
+ "`DELETE /api/apps/{id}/domains/{hostname}`.");
178
+ }
179
+ throw err;
180
+ });
181
+ if (isJSONMode()) {
182
+ printJSON({ domain: hostname, status: "deleted" });
183
+ }
184
+ else {
185
+ success(`Domain ${chalk.cyan(hostname)} removed`);
186
+ }
187
+ });
188
+ }
189
+ function parseIntOption(v) {
190
+ const n = parseInt(v, 10);
191
+ if (Number.isNaN(n))
192
+ throw new Error(`Invalid number: ${v}`);
193
+ return n;
194
+ }
195
+ //# sourceMappingURL=domain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"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"}
@@ -1,67 +1,206 @@
1
1
  import chalk from "chalk";
2
- import { api } from "../lib/api.js";
3
- import { resolveProjectId } from "../lib/config.js";
4
- import { info, isJSONMode, printJSON } from "../lib/format.js";
2
+ import ora from "ora";
3
+ import * as readline from "node:readline";
4
+ import { api, getBaseURL, streamSSE, withScope } from "../lib/api.js";
5
+ import { openURL } from "../lib/auth.js";
6
+ import { resolveProjectScope, resolveService } from "../lib/resolve.js";
7
+ import { success, error, info, isJSONMode, printJSON, isTTY, link } from "../lib/format.js";
5
8
  export function registerGit(program) {
6
9
  const git = program
7
10
  .command("git")
8
- .description("Git integration");
11
+ .description("Git and GitHub integration");
12
+ // lizard git connect — install GitHub App for private repo access
9
13
  git
10
14
  .command("connect")
11
- .argument("<repo>", "GitHub repository (user/repo)")
12
- .description("Connect Git repository for auto-deploy")
13
- .option("--branch <name>", "Branch for auto-deploy", "main")
14
- .action(async (repo, opts) => {
15
- const projectId = resolveProjectId(program.opts().project);
16
- // This requires a server endpoint for programmatic webhook setup
17
- // For now, guide the user to use the dashboard
18
- if (isJSONMode()) {
19
- printJSON({
20
- error: "not_implemented",
21
- message: "Git connect via CLI requires server endpoint. Use the dashboard.",
22
- });
15
+ .description("Connect GitHub App to access private repositories")
16
+ .action(async () => {
17
+ // Check current status
18
+ const status = await api.get("/api/github/status");
19
+ if (status.installed) {
20
+ if (isJSONMode()) {
21
+ printJSON({
22
+ installed: true,
23
+ installationId: status.installationId,
24
+ alreadyConnected: true,
25
+ });
26
+ return;
27
+ }
28
+ success("GitHub App is already connected.");
29
+ info(chalk.dim(" Use `lizard git status` to see connected repositories."));
30
+ return;
31
+ }
32
+ const installUrl = `${getBaseURL()}/api/auth/github/install`;
33
+ // Non-interactive callers (--json, piped) can't press Enter; return
34
+ // the install URL so they can drive the flow themselves and re-run.
35
+ if (isJSONMode() || !isTTY()) {
36
+ if (isJSONMode()) {
37
+ printJSON({ installed: false, installUrl });
38
+ return;
39
+ }
40
+ info(`Open this URL to connect GitHub:\n ${chalk.cyan(installUrl)}`);
41
+ return;
42
+ }
43
+ const opened = await openURL(installUrl);
44
+ if (opened) {
45
+ info("Opening GitHub to install the Lizard GitHub App...");
46
+ }
47
+ else {
48
+ info(`Open this URL to connect GitHub:\n ${chalk.cyan(installUrl)}`);
49
+ }
50
+ // Wait for user to complete installation in browser
51
+ await pressEnter(chalk.dim("\nPress Enter after completing GitHub installation..."));
52
+ // Verify
53
+ const spinner = ora("Verifying GitHub connection...").start();
54
+ const newStatus = await api.get("/api/github/status");
55
+ spinner.stop();
56
+ if (newStatus.installed) {
57
+ success("GitHub connected! You can now deploy private repositories.");
58
+ info(chalk.dim(" Run `lizard deploy` to deploy your project."));
23
59
  }
24
60
  else {
25
- info(`To connect ${chalk.cyan(repo)} for auto-deploy:`);
26
- info(` 1. Open your project on lizard.build`);
27
- info(` 2. Go to Settings → Git Integration`);
28
- info(` 3. Connect ${repo} (branch: ${opts.branch})`);
29
- info("");
30
- info(chalk.dim("CLI git connect will be available in a future update."));
61
+ error("GitHub App not detected. Please try again or connect via the dashboard.");
62
+ process.exit(1);
31
63
  }
32
64
  });
65
+ // lizard git checkout <service> <branch> — switch branch and redeploy
33
66
  git
34
- .command("disconnect")
35
- .description("Disconnect Git auto-deploy")
36
- .action(async () => {
37
- info(chalk.dim("Git disconnect via CLI will be available in a future update."));
67
+ .command("checkout")
68
+ .description("Switch a service to a different branch and redeploy")
69
+ .argument("<service>", "Service name (as shown in the project)")
70
+ .argument("<branch>", "Branch name to switch to")
71
+ .option("--detach", "Start redeploy and exit without streaming logs")
72
+ .option("-p, --project <id>", "Project name, slug, or ID")
73
+ .action(async (serviceArg, branch, opts) => {
74
+ const { projectId, scope } = await resolveProjectScope(opts.project);
75
+ // Resolve service by name
76
+ const svc = await resolveService(projectId, serviceArg);
77
+ if (svc.kind !== "app")
78
+ throw new Error(`"${serviceArg}" is not an app`);
79
+ const serviceId = svc.id;
80
+ const serviceName = svc.name ?? serviceArg;
81
+ // Patch the branch
82
+ const spinner = ora(`Switching ${chalk.bold(serviceName)} to branch ${chalk.cyan(branch)}...`).start();
83
+ await api.post(withScope(`/api/projects/${projectId}/config:apply`, scope), {
84
+ services: [{ name: serviceName, branch }],
85
+ });
86
+ spinner.succeed(`Branch set to ${chalk.cyan(branch)}`);
87
+ // Trigger redeploy
88
+ const deploySpinner = ora("Starting redeploy...").start();
89
+ await api.post(withScope(`/api/apps/${serviceId}/redeploy`, scope));
90
+ deploySpinner.stop();
91
+ if (opts.detach || isJSONMode()) {
92
+ if (isJSONMode())
93
+ printJSON({ id: serviceId, branch, status: "deploying" });
94
+ else
95
+ success(`Redeploy started on branch ${chalk.cyan(branch)}`);
96
+ return;
97
+ }
98
+ info(`Redeploying ${chalk.bold(serviceName)} on ${chalk.cyan(branch)}...`);
99
+ // Wait for build to appear
100
+ let buildId = null;
101
+ for (let i = 0; i < 30; i++) {
102
+ await new Promise((r) => setTimeout(r, 2000));
103
+ try {
104
+ const app = await api.get(`/api/apps/${serviceId}`);
105
+ const latest = app.builds?.[0];
106
+ if (latest && ["building", "deploying", "running", "failed"].includes(latest.status)) {
107
+ buildId = latest.id;
108
+ break;
109
+ }
110
+ }
111
+ catch { }
112
+ }
113
+ if (buildId) {
114
+ await streamSSE(`/api/builds/${buildId}/logs`, (event, data) => {
115
+ if (event === "done" || event === "error") {
116
+ if (event === "error")
117
+ error(`Build failed: ${data}`);
118
+ return false;
119
+ }
120
+ try {
121
+ const parsed = JSON.parse(data);
122
+ process.stdout.write((typeof parsed === "string" ? parsed : (parsed.line ?? data)) + "\n");
123
+ }
124
+ catch {
125
+ process.stdout.write(data + "\n");
126
+ }
127
+ return true;
128
+ });
129
+ }
130
+ const app = await api.get(`/api/apps/${serviceId}`);
131
+ if (app.status === "running") {
132
+ success(`Deployed! ${app.domain ? chalk.cyan(`https://${app.domain}`) : ""}`);
133
+ }
134
+ else {
135
+ error("Deploy failed");
136
+ }
38
137
  });
138
+ // lizard git status
39
139
  git
40
140
  .command("status")
41
- .description("Show Git integration status")
42
- .action(async () => {
43
- const projectId = resolveProjectId(program.opts().project);
44
- // Get apps to check for repo info
45
- const services = await api.get(`/api/projects/${projectId}/services`);
46
- const appsWithRepo = (services.apps || []).filter((a) => a.repo);
141
+ .description("Show GitHub connection and repository status")
142
+ .option("-p, --project <id>", "Project name, slug, or ID")
143
+ .action(async (opts) => {
144
+ const { projectId, scope } = await resolveProjectScope(opts.project);
145
+ const [githubStatus, services] = await Promise.all([
146
+ api.get("/api/github/status"),
147
+ api.get(withScope(`/api/projects/${projectId}/services`, scope)),
148
+ ]);
149
+ const appsWithRepo = (services.apps || []).filter((a) => a.repo || a.repoUrl);
47
150
  if (isJSONMode()) {
48
151
  printJSON({
49
- connected: appsWithRepo.length > 0,
152
+ github: {
153
+ installed: githubStatus.installed,
154
+ installationId: githubStatus.installationId,
155
+ installations: githubStatus.installations ?? [],
156
+ manageUrl: githubStatus.manageUrl,
157
+ },
50
158
  apps: appsWithRepo.map((a) => ({
51
159
  name: a.name,
52
- repo: a.repo,
160
+ repo: a.repo || a.repoUrl,
53
161
  branch: a.branch,
54
162
  })),
55
163
  });
56
164
  return;
57
165
  }
166
+ // GitHub App status
167
+ if (githubStatus.installed) {
168
+ info(`GitHub App: ${chalk.green("connected")}`);
169
+ const installs = githubStatus.installations ?? [];
170
+ for (const inst of installs) {
171
+ const typeLabel = inst.account.type === "Organization" ? "org" : "user";
172
+ const repoLabel = inst.repoCount !== null
173
+ ? chalk.dim(`${inst.repoCount} repos${inst.privateCount ? `, ${inst.privateCount} private` : ""}`)
174
+ : "";
175
+ info(` ${chalk.bold(inst.account.login)} ${chalk.dim(`(${typeLabel}, installation #${inst.id})`)} ${repoLabel}`);
176
+ }
177
+ const manageUrl = githubStatus.manageUrl ?? `https://github.com/apps/lizard-app/installations/select_target`;
178
+ info(chalk.dim(` Manage: ${link(manageUrl)}`));
179
+ }
180
+ else {
181
+ info(`GitHub App: ${chalk.yellow("not connected")} ${chalk.dim("→ run `lizard git connect`")}`);
182
+ if (githubStatus.error) {
183
+ info(chalk.dim(` (${githubStatus.error})`));
184
+ }
185
+ }
186
+ // Connected repos
58
187
  if (appsWithRepo.length === 0) {
59
- console.log("No Git repositories connected.");
188
+ info(chalk.dim("\nNo repositories connected to this project."));
60
189
  return;
61
190
  }
191
+ info("");
62
192
  for (const app of appsWithRepo) {
63
- console.log(`${chalk.bold(app.name)}: ${chalk.cyan(app.repo)} (${app.branch || "main"})`);
193
+ info(`${chalk.bold(app.name)}: ${chalk.cyan(app.repo || app.repoUrl)} ${chalk.dim(`(${app.branch || "main"})`)}`);
64
194
  }
65
195
  });
66
196
  }
197
+ function pressEnter(question) {
198
+ return new Promise((resolve) => {
199
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
200
+ rl.question(question, () => {
201
+ rl.close();
202
+ resolve();
203
+ });
204
+ });
205
+ }
67
206
  //# sourceMappingURL=git.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,26 @@
1
1
  import { Command } from "commander";
2
+ import { type Workspace } from "../lib/api.js";
3
+ import { type ProjectLink } from "../lib/config.js";
4
+ /**
5
+ * Ensure the current directory is linked to a project. If already linked and
6
+ * `force` is false, returns the existing link. Otherwise runs the
7
+ * create-or-select flow.
8
+ *
9
+ * Flow (mirrors Railway's `link` wizard):
10
+ * 1. Workspace — selected by --workspace, single workspace auto-pick,
11
+ * or interactive select. Skipped when only one workspace exists.
12
+ * 2. Project — matched by --name within the workspace, picked from the
13
+ * workspace's project list, or created.
14
+ *
15
+ * `projectName` (from --name / --project) is matched against existing
16
+ * projects inside the resolved workspace; if not found, a new project
17
+ * with that name is created in the resolved workspace.
18
+ */
19
+ export declare function ensureLinked(opts?: {
20
+ projectName?: string;
21
+ workspaceFlag?: string;
22
+ force?: boolean;
23
+ relinkPrompt?: boolean;
24
+ }): Promise<ProjectLink>;
2
25
  export declare function registerInit(program: Command): void;
26
+ export type { Workspace };