creek 0.3.0-alpha.11 → 0.3.0-alpha.13
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/dist/commands/claim.d.ts +10 -0
- package/dist/commands/claim.js +15 -6
- package/dist/commands/deploy.d.ts +15 -5
- package/dist/commands/deploy.js +156 -63
- package/dist/commands/env.js +19 -2
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.js +14 -5
- package/dist/commands/login.d.ts +10 -0
- package/dist/commands/login.js +12 -3
- package/dist/commands/whoami.d.ts +12 -1
- package/dist/commands/whoami.js +17 -1
- package/dist/utils/output.d.ts +38 -0
- package/dist/utils/output.js +45 -0
- package/dist/utils/sandbox.js +3 -6
- package/package.json +1 -1
package/dist/commands/claim.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export declare const claimCommand: import("citty").CommandDef<{
|
|
2
|
+
json: {
|
|
3
|
+
type: "boolean";
|
|
4
|
+
description: string;
|
|
5
|
+
default: boolean;
|
|
6
|
+
};
|
|
7
|
+
yes: {
|
|
8
|
+
type: "boolean";
|
|
9
|
+
description: string;
|
|
10
|
+
default: boolean;
|
|
11
|
+
};
|
|
2
12
|
sandboxId: {
|
|
3
13
|
type: "positional";
|
|
4
14
|
description: string;
|
package/dist/commands/claim.js
CHANGED
|
@@ -2,6 +2,7 @@ import { defineCommand } from "citty";
|
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import { CreekClient } from "@solcreek/sdk";
|
|
4
4
|
import { getToken, getApiUrl, getSandboxApiUrl } from "../utils/config.js";
|
|
5
|
+
import { globalArgs, resolveJsonMode, jsonOutput } from "../utils/output.js";
|
|
5
6
|
export const claimCommand = defineCommand({
|
|
6
7
|
meta: {
|
|
7
8
|
name: "claim",
|
|
@@ -13,10 +14,14 @@ export const claimCommand = defineCommand({
|
|
|
13
14
|
description: "Sandbox ID to claim (shown after sandbox deploy)",
|
|
14
15
|
required: true,
|
|
15
16
|
},
|
|
17
|
+
...globalArgs,
|
|
16
18
|
},
|
|
17
19
|
async run({ args }) {
|
|
20
|
+
const jsonMode = resolveJsonMode(args);
|
|
18
21
|
const token = getToken();
|
|
19
22
|
if (!token) {
|
|
23
|
+
if (jsonMode)
|
|
24
|
+
jsonOutput({ ok: false, error: "not_authenticated", message: "Run `creek login` first" }, 1);
|
|
20
25
|
consola.error("You need to be logged in to claim a sandbox.");
|
|
21
26
|
consola.info("Run `creek login` first, then `creek claim` again.");
|
|
22
27
|
process.exit(1);
|
|
@@ -32,13 +37,14 @@ export const claimCommand = defineCommand({
|
|
|
32
37
|
}
|
|
33
38
|
const sandbox = (await statusRes.json());
|
|
34
39
|
if (!sandbox.claimable) {
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
const msg = sandbox.status === "expired"
|
|
41
|
+
? "This sandbox has expired and can no longer be claimed."
|
|
42
|
+
: `Sandbox is in '${sandbox.status}' state and cannot be claimed.`;
|
|
43
|
+
if (jsonMode)
|
|
44
|
+
jsonOutput({ ok: false, error: "not_claimable", status: sandbox.status, message: msg }, 1);
|
|
45
|
+
consola.error(msg);
|
|
46
|
+
if (sandbox.status === "expired")
|
|
37
47
|
consola.info("Run `creek deploy` to deploy your project permanently.");
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
consola.error(`Sandbox is in '${sandbox.status}' state and cannot be claimed.`);
|
|
41
|
-
}
|
|
42
48
|
process.exit(1);
|
|
43
49
|
}
|
|
44
50
|
// 2. Create permanent project
|
|
@@ -73,6 +79,9 @@ export const claimCommand = defineCommand({
|
|
|
73
79
|
catch {
|
|
74
80
|
// Best effort — claim status update is non-critical
|
|
75
81
|
}
|
|
82
|
+
if (jsonMode) {
|
|
83
|
+
jsonOutput({ ok: true, sandboxId, project: project.slug, projectId: project.id });
|
|
84
|
+
}
|
|
76
85
|
consola.success("Sandbox claimed!");
|
|
77
86
|
consola.info("");
|
|
78
87
|
consola.info("Next steps:");
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
export declare const deployCommand: import("citty").CommandDef<{
|
|
2
|
+
template: {
|
|
3
|
+
type: "string";
|
|
4
|
+
description: string;
|
|
5
|
+
required: false;
|
|
6
|
+
};
|
|
7
|
+
json: {
|
|
8
|
+
type: "boolean";
|
|
9
|
+
description: string;
|
|
10
|
+
default: boolean;
|
|
11
|
+
};
|
|
12
|
+
yes: {
|
|
13
|
+
type: "boolean";
|
|
14
|
+
description: string;
|
|
15
|
+
default: boolean;
|
|
16
|
+
};
|
|
2
17
|
dir: {
|
|
3
18
|
type: "positional";
|
|
4
19
|
description: string;
|
|
@@ -14,10 +29,5 @@ export declare const deployCommand: import("citty").CommandDef<{
|
|
|
14
29
|
description: string;
|
|
15
30
|
default: false;
|
|
16
31
|
};
|
|
17
|
-
template: {
|
|
18
|
-
type: "string";
|
|
19
|
-
description: string;
|
|
20
|
-
required: false;
|
|
21
|
-
};
|
|
22
32
|
}>;
|
|
23
33
|
//# sourceMappingURL=deploy.d.ts.map
|
package/dist/commands/deploy.js
CHANGED
|
@@ -8,6 +8,22 @@ import { getToken, getApiUrl } from "../utils/config.js";
|
|
|
8
8
|
import { collectAssets } from "../utils/bundle.js";
|
|
9
9
|
import { bundleSSRServer } from "../utils/ssr-bundle.js";
|
|
10
10
|
import { sandboxDeploy, pollSandboxStatus, printSandboxSuccess } from "../utils/sandbox.js";
|
|
11
|
+
import { isTTY, jsonOutput, resolveJsonMode, globalArgs } from "../utils/output.js";
|
|
12
|
+
function section(name) {
|
|
13
|
+
consola.log(`\n \x1b[2m[${name}]\x1b[0m`);
|
|
14
|
+
}
|
|
15
|
+
function assetSummary(fileList) {
|
|
16
|
+
const byExt = {};
|
|
17
|
+
for (const f of fileList) {
|
|
18
|
+
const ext = f.includes(".") ? `.${f.split(".").pop()}` : "(other)";
|
|
19
|
+
byExt[ext] = (byExt[ext] ?? 0) + 1;
|
|
20
|
+
}
|
|
21
|
+
const parts = Object.entries(byExt)
|
|
22
|
+
.sort((a, b) => b[1] - a[1])
|
|
23
|
+
.slice(0, 4)
|
|
24
|
+
.map(([ext, n]) => `${n} ${ext}`);
|
|
25
|
+
return parts.join(", ");
|
|
26
|
+
}
|
|
11
27
|
export const deployCommand = defineCommand({
|
|
12
28
|
meta: {
|
|
13
29
|
name: "deploy",
|
|
@@ -29,6 +45,7 @@ export const deployCommand = defineCommand({
|
|
|
29
45
|
description: "Deploy a sample site to see Creek in action",
|
|
30
46
|
default: false,
|
|
31
47
|
},
|
|
48
|
+
...globalArgs,
|
|
32
49
|
template: {
|
|
33
50
|
type: "string",
|
|
34
51
|
description: "Deploy a template (e.g., react-dashboard, astro-landing)",
|
|
@@ -36,9 +53,10 @@ export const deployCommand = defineCommand({
|
|
|
36
53
|
},
|
|
37
54
|
},
|
|
38
55
|
async run({ args }) {
|
|
56
|
+
const jsonMode = resolveJsonMode(args);
|
|
39
57
|
// --- Demo deploy (zero-friction showcase) ---
|
|
40
58
|
if (args.demo) {
|
|
41
|
-
return await deployDemo();
|
|
59
|
+
return await deployDemo(jsonMode);
|
|
42
60
|
}
|
|
43
61
|
// --- Template deploy ---
|
|
44
62
|
if (args.template) {
|
|
@@ -52,33 +70,40 @@ export const deployCommand = defineCommand({
|
|
|
52
70
|
// --- Explicit directory (creek deploy ./dist) ---
|
|
53
71
|
if (args.dir) {
|
|
54
72
|
if (!existsSync(cwd)) {
|
|
73
|
+
if (jsonMode)
|
|
74
|
+
jsonOutput({ error: "not_found", message: `Directory not found: ${args.dir}` }, 1);
|
|
55
75
|
consola.error(`Directory not found: ${args.dir}`);
|
|
56
76
|
process.exit(1);
|
|
57
77
|
}
|
|
58
|
-
return await deployDirectory(cwd);
|
|
78
|
+
return await deployDirectory(cwd, jsonMode);
|
|
59
79
|
}
|
|
60
80
|
// --- Authenticated deploy (creek.toml present) ---
|
|
61
81
|
if (hasConfig) {
|
|
62
82
|
if (!token) {
|
|
83
|
+
if (jsonMode)
|
|
84
|
+
jsonOutput({ error: "not_authenticated", message: "Run `creek login` first" }, 1);
|
|
63
85
|
consola.error("Not authenticated. Run `creek login` first.");
|
|
64
86
|
consola.info("Or deploy without an account: remove creek.toml and run `creek deploy` again.");
|
|
65
87
|
process.exit(1);
|
|
66
88
|
}
|
|
67
|
-
return await deployAuthenticated(cwd, configPath, token, args["skip-build"]);
|
|
89
|
+
return await deployAuthenticated(cwd, configPath, token, args["skip-build"], jsonMode);
|
|
68
90
|
}
|
|
69
91
|
// --- Sandbox deploy (has package.json → auto-detect + build) ---
|
|
70
92
|
if (existsSync(join(cwd, "package.json"))) {
|
|
71
|
-
return await deploySandbox(cwd, args["skip-build"]);
|
|
93
|
+
return await deploySandbox(cwd, args["skip-build"], jsonMode);
|
|
72
94
|
}
|
|
73
95
|
// --- Auto-detect build output dirs ---
|
|
74
96
|
for (const dir of ["dist", "build", "out", ".output/public"]) {
|
|
75
97
|
const fullPath = resolve(cwd, dir);
|
|
76
98
|
if (existsSync(fullPath)) {
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
if (!jsonMode)
|
|
100
|
+
consola.info(`Found build output: ${dir}/`);
|
|
101
|
+
return await deployDirectory(fullPath, jsonMode);
|
|
79
102
|
}
|
|
80
103
|
}
|
|
81
104
|
// --- Nothing found → guide the user ---
|
|
105
|
+
if (jsonMode)
|
|
106
|
+
jsonOutput({ error: "no_project", message: "No project found in this directory" }, 1);
|
|
82
107
|
consola.info("No project found in this directory.\n");
|
|
83
108
|
consola.info(" creek deploy ./dist Deploy a build output directory");
|
|
84
109
|
consola.info(" creek deploy --demo Deploy a sample site (see Creek in 5 seconds)");
|
|
@@ -124,15 +149,27 @@ code{background:#1a1a2e;padding:2px 8px;border-radius:4px;font-size:0.85rem;colo
|
|
|
124
149
|
<script>document.title="Creek Deploy Demo — "+new Date().toLocaleTimeString()</script>
|
|
125
150
|
</body>
|
|
126
151
|
</html>`;
|
|
127
|
-
async function deployDemo() {
|
|
128
|
-
|
|
152
|
+
async function deployDemo(jsonMode) {
|
|
153
|
+
if (!jsonMode)
|
|
154
|
+
consola.start("Deploying demo site...");
|
|
129
155
|
try {
|
|
130
156
|
const result = await sandboxDeploy({
|
|
131
157
|
assets: { "index.html": Buffer.from(DEMO_HTML).toString("base64") },
|
|
132
158
|
source: "cli-demo",
|
|
133
159
|
});
|
|
134
|
-
|
|
160
|
+
if (!jsonMode)
|
|
161
|
+
consola.start("Waiting for deployment...");
|
|
135
162
|
const status = await pollSandboxStatus(result.statusUrl);
|
|
163
|
+
if (jsonMode) {
|
|
164
|
+
jsonOutput({
|
|
165
|
+
ok: true,
|
|
166
|
+
sandboxId: result.sandboxId,
|
|
167
|
+
url: status.previewUrl,
|
|
168
|
+
deployDurationMs: status.deployDurationMs,
|
|
169
|
+
expiresAt: result.expiresAt,
|
|
170
|
+
mode: "demo",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
136
173
|
const duration = status.deployDurationMs
|
|
137
174
|
? `in ${(status.deployDurationMs / 1000).toFixed(1)}s`
|
|
138
175
|
: "in seconds";
|
|
@@ -142,50 +179,67 @@ async function deployDemo() {
|
|
|
142
179
|
consola.info(" cd your-project && npx creek deploy");
|
|
143
180
|
}
|
|
144
181
|
catch (err) {
|
|
145
|
-
|
|
182
|
+
const message = err instanceof Error ? err.message : "Demo deploy failed";
|
|
183
|
+
if (jsonMode)
|
|
184
|
+
jsonOutput({ ok: false, error: "deploy_failed", message }, 1);
|
|
185
|
+
consola.error(message);
|
|
146
186
|
process.exit(1);
|
|
147
187
|
}
|
|
148
188
|
}
|
|
149
189
|
// ============================================================================
|
|
150
190
|
// Directory deploy — deploy pre-built static files directly
|
|
151
191
|
// ============================================================================
|
|
152
|
-
async function deployDirectory(dir) {
|
|
153
|
-
|
|
154
|
-
|
|
192
|
+
async function deployDirectory(dir, jsonMode) {
|
|
193
|
+
if (!jsonMode)
|
|
194
|
+
section("Upload");
|
|
155
195
|
const { assets, fileList } = collectAssets(dir);
|
|
156
196
|
if (fileList.length === 0) {
|
|
197
|
+
if (jsonMode)
|
|
198
|
+
jsonOutput({ ok: false, error: "no_files", message: `No files found in ${dir}` }, 1);
|
|
157
199
|
consola.error(`No files found in ${dir}\n`);
|
|
158
200
|
consola.info(" creek deploy ./dist Deploy a build output directory");
|
|
159
201
|
consola.info(" creek deploy --demo Deploy a sample site (see Creek in 5 seconds)");
|
|
160
202
|
process.exit(1);
|
|
161
203
|
}
|
|
162
|
-
|
|
163
|
-
|
|
204
|
+
if (!jsonMode) {
|
|
205
|
+
consola.info(` ${fileList.length} files (${assetSummary(fileList)})`);
|
|
206
|
+
consola.info(" Mode: sandbox (60 min preview)");
|
|
207
|
+
section("Deploy");
|
|
208
|
+
consola.start(" Deploying to edge...");
|
|
209
|
+
}
|
|
164
210
|
try {
|
|
165
211
|
const result = await sandboxDeploy({ assets, source: "cli" });
|
|
166
|
-
consola.start("Waiting for deployment...");
|
|
167
212
|
const status = await pollSandboxStatus(result.statusUrl);
|
|
213
|
+
if (jsonMode) {
|
|
214
|
+
jsonOutput({
|
|
215
|
+
ok: true,
|
|
216
|
+
sandboxId: result.sandboxId,
|
|
217
|
+
url: status.previewUrl,
|
|
218
|
+
deployDurationMs: status.deployDurationMs,
|
|
219
|
+
expiresAt: result.expiresAt,
|
|
220
|
+
assetCount: fileList.length,
|
|
221
|
+
mode: "sandbox",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
168
224
|
printSandboxSuccess(status.previewUrl, result.expiresAt, result.sandboxId);
|
|
169
225
|
}
|
|
170
226
|
catch (err) {
|
|
171
|
-
|
|
227
|
+
const message = err instanceof Error ? err.message : "Deploy failed";
|
|
228
|
+
if (jsonMode)
|
|
229
|
+
jsonOutput({ ok: false, error: "deploy_failed", message }, 1);
|
|
230
|
+
consola.error(message);
|
|
172
231
|
process.exit(1);
|
|
173
232
|
}
|
|
174
233
|
}
|
|
175
234
|
// ============================================================================
|
|
176
235
|
// Sandbox deploy — auto-detect framework, build, deploy
|
|
177
236
|
// ============================================================================
|
|
178
|
-
async function deploySandbox(cwd, skipBuild) {
|
|
179
|
-
consola.info("Deploying to sandbox (60 min preview).");
|
|
180
|
-
consola.info("");
|
|
237
|
+
async function deploySandbox(cwd, skipBuild, jsonMode = false) {
|
|
181
238
|
const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
182
239
|
const framework = detectFramework(pkg);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
else {
|
|
187
|
-
consola.info("Framework: auto (static site)");
|
|
188
|
-
}
|
|
240
|
+
section("Detect");
|
|
241
|
+
consola.info(` Framework: ${framework ?? "static site"}`);
|
|
242
|
+
consola.info(" Mode: sandbox (60 min preview)");
|
|
189
243
|
// Build
|
|
190
244
|
const buildCommand = pkg.scripts?.build ? "npm run build" : null;
|
|
191
245
|
const outputDir = resolve(cwd, getDefaultBuildOutput(framework));
|
|
@@ -195,20 +249,20 @@ async function deploySandbox(cwd, skipBuild) {
|
|
|
195
249
|
consola.info("Add a 'build' script or use --skip-build if already built.");
|
|
196
250
|
process.exit(1);
|
|
197
251
|
}
|
|
198
|
-
|
|
252
|
+
section("Build");
|
|
253
|
+
consola.start(` ${buildCommand}`);
|
|
199
254
|
try {
|
|
200
255
|
execSync(buildCommand, { cwd, stdio: "inherit" });
|
|
201
256
|
}
|
|
202
257
|
catch {
|
|
203
258
|
consola.error("Build failed");
|
|
204
259
|
consola.info("");
|
|
205
|
-
consola.info("Common fixes:");
|
|
206
|
-
consola.info("
|
|
207
|
-
consola.info("
|
|
208
|
-
consola.info(` • Verify build works: ${buildCommand}`);
|
|
260
|
+
consola.info(" Common fixes:");
|
|
261
|
+
consola.info(" npm install (missing dependencies?)");
|
|
262
|
+
consola.info(" Check for TypeScript errors");
|
|
209
263
|
process.exit(1);
|
|
210
264
|
}
|
|
211
|
-
consola.success("Build complete");
|
|
265
|
+
consola.success(" Build complete");
|
|
212
266
|
}
|
|
213
267
|
if (!existsSync(outputDir)) {
|
|
214
268
|
consola.error(`Build output not found: ${outputDir}`);
|
|
@@ -226,24 +280,27 @@ async function deploySandbox(cwd, skipBuild) {
|
|
|
226
280
|
if (subdir)
|
|
227
281
|
clientAssetsDir = resolve(outputDir, subdir);
|
|
228
282
|
}
|
|
229
|
-
|
|
283
|
+
section("Upload");
|
|
230
284
|
const { assets: clientAssets, fileList } = collectAssets(clientAssetsDir);
|
|
231
|
-
consola.info(`
|
|
285
|
+
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
232
286
|
let serverFiles;
|
|
233
287
|
if (isSSR && framework) {
|
|
234
288
|
const serverEntry = getSSRServerEntry(framework);
|
|
235
289
|
if (serverEntry) {
|
|
236
290
|
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
237
291
|
if (existsSync(serverEntryPath)) {
|
|
238
|
-
consola.start("Bundling SSR server...");
|
|
292
|
+
consola.start(" Bundling SSR server...");
|
|
239
293
|
const bundled = await bundleSSRServer(serverEntryPath);
|
|
240
294
|
serverFiles = { "server.js": Buffer.from(bundled).toString("base64") };
|
|
241
|
-
consola.success(`SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
295
|
+
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
242
296
|
}
|
|
243
297
|
}
|
|
244
298
|
}
|
|
245
299
|
// Deploy to sandbox
|
|
246
|
-
|
|
300
|
+
if (!jsonMode) {
|
|
301
|
+
section("Deploy");
|
|
302
|
+
consola.start(" Deploying to edge...");
|
|
303
|
+
}
|
|
247
304
|
try {
|
|
248
305
|
const result = await sandboxDeploy({
|
|
249
306
|
assets: clientAssets,
|
|
@@ -251,12 +308,26 @@ async function deploySandbox(cwd, skipBuild) {
|
|
|
251
308
|
framework: framework ?? undefined,
|
|
252
309
|
source: "cli",
|
|
253
310
|
});
|
|
254
|
-
consola.start("Waiting for deployment...");
|
|
255
311
|
const status = await pollSandboxStatus(result.statusUrl);
|
|
312
|
+
if (jsonMode) {
|
|
313
|
+
jsonOutput({
|
|
314
|
+
ok: true,
|
|
315
|
+
sandboxId: result.sandboxId,
|
|
316
|
+
url: status.previewUrl,
|
|
317
|
+
deployDurationMs: status.deployDurationMs,
|
|
318
|
+
expiresAt: result.expiresAt,
|
|
319
|
+
framework: framework ?? null,
|
|
320
|
+
assetCount: fileList.length,
|
|
321
|
+
mode: "sandbox",
|
|
322
|
+
});
|
|
323
|
+
}
|
|
256
324
|
printSandboxSuccess(status.previewUrl, result.expiresAt, result.sandboxId);
|
|
257
325
|
}
|
|
258
326
|
catch (err) {
|
|
259
|
-
|
|
327
|
+
const message = err instanceof Error ? err.message : "Sandbox deploy failed";
|
|
328
|
+
if (jsonMode)
|
|
329
|
+
jsonOutput({ ok: false, error: "deploy_failed", message }, 1);
|
|
330
|
+
consola.error(message);
|
|
260
331
|
process.exit(1);
|
|
261
332
|
}
|
|
262
333
|
}
|
|
@@ -325,44 +396,49 @@ function cleanupDir(dir) {
|
|
|
325
396
|
// ============================================================================
|
|
326
397
|
// Authenticated deploy — existing flow
|
|
327
398
|
// ============================================================================
|
|
328
|
-
async function deployAuthenticated(cwd, configPath, token, skipBuild) {
|
|
399
|
+
async function deployAuthenticated(cwd, configPath, token, skipBuild, jsonMode = false) {
|
|
329
400
|
try {
|
|
330
401
|
const config = parseConfig(readFileSync(configPath, "utf-8"));
|
|
331
402
|
const client = new CreekClient(getApiUrl(), token);
|
|
332
|
-
|
|
403
|
+
section("Auth");
|
|
333
404
|
const session = await client.getSession();
|
|
334
405
|
if (!session?.user) {
|
|
335
406
|
consola.error("Token is invalid or expired. Run `creek login` to re-authenticate.");
|
|
336
407
|
process.exit(1);
|
|
337
408
|
}
|
|
338
|
-
consola.info(`Deploying as ${session.user.email}`);
|
|
339
|
-
consola.info(`Project: ${config.project.name}`);
|
|
409
|
+
consola.info(` Deploying as ${session.user.email}`);
|
|
410
|
+
consola.info(` Project: ${config.project.name}`);
|
|
340
411
|
// Ensure project exists — confirm before auto-creating
|
|
341
412
|
let project;
|
|
342
413
|
try {
|
|
343
414
|
project = await client.getProject(config.project.name);
|
|
344
415
|
}
|
|
345
416
|
catch {
|
|
346
|
-
|
|
347
|
-
if (!
|
|
348
|
-
consola.
|
|
349
|
-
|
|
417
|
+
// In --yes / non-TTY / JSON mode, auto-create without prompting (agent-friendly)
|
|
418
|
+
if (!jsonMode && isTTY) {
|
|
419
|
+
const confirm = await consola.prompt(`Project "${config.project.name}" does not exist. Create it?`, { type: "confirm" });
|
|
420
|
+
if (!confirm) {
|
|
421
|
+
consola.info("Deploy cancelled.");
|
|
422
|
+
process.exit(0);
|
|
423
|
+
}
|
|
350
424
|
}
|
|
351
425
|
const res = await client.createProject({
|
|
352
426
|
slug: config.project.name,
|
|
353
427
|
framework: config.project.framework,
|
|
354
428
|
});
|
|
355
429
|
project = res.project;
|
|
356
|
-
|
|
430
|
+
if (!jsonMode)
|
|
431
|
+
consola.success(` Created project: ${project.slug}`);
|
|
357
432
|
}
|
|
358
|
-
// Build
|
|
433
|
+
// Build
|
|
359
434
|
if (!skipBuild) {
|
|
360
435
|
const buildCmd = config.build.command;
|
|
361
436
|
if (!buildCmd || typeof buildCmd !== "string" || buildCmd.length > 500) {
|
|
362
437
|
consola.error("Invalid build command in creek.toml");
|
|
363
438
|
process.exit(1);
|
|
364
439
|
}
|
|
365
|
-
|
|
440
|
+
section("Build");
|
|
441
|
+
consola.start(` ${buildCmd}`);
|
|
366
442
|
try {
|
|
367
443
|
execSync(buildCmd, { cwd, stdio: "inherit" });
|
|
368
444
|
}
|
|
@@ -370,7 +446,7 @@ async function deployAuthenticated(cwd, configPath, token, skipBuild) {
|
|
|
370
446
|
consola.error("Build failed");
|
|
371
447
|
process.exit(1);
|
|
372
448
|
}
|
|
373
|
-
consola.success("Build complete");
|
|
449
|
+
consola.success(" Build complete");
|
|
374
450
|
}
|
|
375
451
|
const outputDir = resolve(cwd, config.build.output);
|
|
376
452
|
if (!existsSync(outputDir)) {
|
|
@@ -387,27 +463,28 @@ async function deployAuthenticated(cwd, configPath, token, skipBuild) {
|
|
|
387
463
|
clientAssetsDir = resolve(outputDir, clientSubdir);
|
|
388
464
|
}
|
|
389
465
|
}
|
|
390
|
-
|
|
466
|
+
section("Upload");
|
|
391
467
|
const { assets: clientAssets, fileList } = collectAssets(clientAssetsDir);
|
|
392
|
-
consola.info(`
|
|
468
|
+
consola.info(` ${fileList.length} assets (${assetSummary(fileList)})`);
|
|
393
469
|
let serverFiles;
|
|
394
470
|
if (isSSR && framework) {
|
|
395
471
|
const serverEntry = getSSRServerEntry(framework);
|
|
396
472
|
if (serverEntry) {
|
|
397
473
|
const serverEntryPath = resolve(outputDir, serverEntry);
|
|
398
474
|
if (existsSync(serverEntryPath)) {
|
|
399
|
-
consola.start("Bundling SSR server...");
|
|
475
|
+
consola.start(" Bundling SSR server...");
|
|
400
476
|
const bundled = await bundleSSRServer(serverEntryPath);
|
|
401
477
|
serverFiles = {
|
|
402
478
|
"server.js": Buffer.from(bundled).toString("base64"),
|
|
403
479
|
};
|
|
404
|
-
consola.success(`SSR
|
|
480
|
+
consola.success(` SSR bundled (${Math.round(bundled.length / 1024)}KB)`);
|
|
405
481
|
}
|
|
406
482
|
}
|
|
407
483
|
}
|
|
408
|
-
|
|
484
|
+
section("Deploy");
|
|
485
|
+
consola.start(" Creating deployment...");
|
|
409
486
|
const { deployment } = await client.createDeployment(project.id);
|
|
410
|
-
consola.start("Uploading...");
|
|
487
|
+
consola.start(" Uploading bundle...");
|
|
411
488
|
const bundle = {
|
|
412
489
|
manifest: {
|
|
413
490
|
assets: fileList,
|
|
@@ -426,10 +503,10 @@ async function deployAuthenticated(cwd, configPath, token, skipBuild) {
|
|
|
426
503
|
const POLL_TIMEOUT = 120_000;
|
|
427
504
|
const TERMINAL = new Set(["active", "failed", "cancelled"]);
|
|
428
505
|
const STEP_LABELS = {
|
|
429
|
-
queued: "Waiting...",
|
|
430
|
-
uploading: "Uploading
|
|
431
|
-
provisioning: "Provisioning resources...",
|
|
432
|
-
deploying: "Deploying to edge...",
|
|
506
|
+
queued: " Waiting...",
|
|
507
|
+
uploading: " Uploading...",
|
|
508
|
+
provisioning: " Provisioning resources...",
|
|
509
|
+
deploying: " Deploying to edge...",
|
|
433
510
|
};
|
|
434
511
|
let lastStatus = "";
|
|
435
512
|
const start = Date.now();
|
|
@@ -446,24 +523,40 @@ async function deployAuthenticated(cwd, configPath, token, skipBuild) {
|
|
|
446
523
|
lastStatus = status;
|
|
447
524
|
}
|
|
448
525
|
if (status === "active") {
|
|
449
|
-
|
|
526
|
+
if (jsonMode) {
|
|
527
|
+
jsonOutput({
|
|
528
|
+
ok: true,
|
|
529
|
+
url: res.url ?? res.previewUrl,
|
|
530
|
+
previewUrl: res.previewUrl,
|
|
531
|
+
deploymentId: deployment.id,
|
|
532
|
+
project: project.slug,
|
|
533
|
+
mode: "production",
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
consola.success(` Deployed! ${res.url ?? res.previewUrl}`);
|
|
450
537
|
if (res.url && res.previewUrl) {
|
|
451
|
-
consola.info(`Preview:
|
|
538
|
+
consola.info(` Preview: ${res.previewUrl}`);
|
|
452
539
|
}
|
|
453
540
|
return;
|
|
454
541
|
}
|
|
455
542
|
if (status === "failed") {
|
|
456
543
|
const step = failed_step ? ` at ${failed_step}` : "";
|
|
457
544
|
const msg = error_message ?? "Unknown error";
|
|
545
|
+
if (jsonMode)
|
|
546
|
+
jsonOutput({ ok: false, error: "deploy_failed", message: msg, failedStep: failed_step }, 1);
|
|
458
547
|
consola.error(`Deploy failed${step}: ${msg}`);
|
|
459
548
|
process.exit(1);
|
|
460
549
|
}
|
|
461
550
|
if (status === "cancelled") {
|
|
551
|
+
if (jsonMode)
|
|
552
|
+
jsonOutput({ ok: false, error: "cancelled", message: "Deploy was cancelled" }, 1);
|
|
462
553
|
consola.warn("Deploy was cancelled");
|
|
463
554
|
process.exit(1);
|
|
464
555
|
}
|
|
465
556
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
466
557
|
}
|
|
558
|
+
if (jsonMode)
|
|
559
|
+
jsonOutput({ ok: false, error: "timeout", message: "Deploy timed out after 2 minutes" }, 1);
|
|
467
560
|
consola.error("Deploy timed out after 2 minutes");
|
|
468
561
|
process.exit(1);
|
|
469
562
|
}
|
package/dist/commands/env.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { defineCommand } from "citty";
|
|
2
2
|
import consola from "consola";
|
|
3
|
-
import { CreekClient } from "@solcreek/sdk";
|
|
3
|
+
import { CreekClient, parseConfig } from "@solcreek/sdk";
|
|
4
4
|
import { getToken, getApiUrl } from "../utils/config.js";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
-
import {
|
|
7
|
+
import { globalArgs, resolveJsonMode, jsonOutput } from "../utils/output.js";
|
|
8
8
|
function getProjectSlug() {
|
|
9
9
|
const configPath = join(process.cwd(), "creek.toml");
|
|
10
10
|
if (!existsSync(configPath)) {
|
|
@@ -26,11 +26,15 @@ const envSet = defineCommand({
|
|
|
26
26
|
args: {
|
|
27
27
|
key: { type: "positional", description: "Variable name (e.g. DATABASE_URL)", required: true },
|
|
28
28
|
value: { type: "positional", description: "Variable value", required: true },
|
|
29
|
+
...globalArgs,
|
|
29
30
|
},
|
|
30
31
|
async run({ args }) {
|
|
32
|
+
const jsonMode = resolveJsonMode(args);
|
|
31
33
|
const client = getClient();
|
|
32
34
|
const slug = getProjectSlug();
|
|
33
35
|
await client.setEnvVar(slug, args.key, args.value);
|
|
36
|
+
if (jsonMode)
|
|
37
|
+
jsonOutput({ ok: true, key: args.key, project: slug });
|
|
34
38
|
consola.success(`Set ${args.key}`);
|
|
35
39
|
},
|
|
36
40
|
});
|
|
@@ -43,11 +47,20 @@ const envGet = defineCommand({
|
|
|
43
47
|
meta: { name: "ls", description: "List environment variables" },
|
|
44
48
|
args: {
|
|
45
49
|
show: { type: "boolean", description: "Show values in plaintext (default: redacted)", default: false },
|
|
50
|
+
...globalArgs,
|
|
46
51
|
},
|
|
47
52
|
async run({ args }) {
|
|
53
|
+
const jsonMode = resolveJsonMode(args);
|
|
48
54
|
const client = getClient();
|
|
49
55
|
const slug = getProjectSlug();
|
|
50
56
|
const vars = await client.listEnvVars(slug);
|
|
57
|
+
if (jsonMode) {
|
|
58
|
+
jsonOutput({
|
|
59
|
+
ok: true,
|
|
60
|
+
project: slug,
|
|
61
|
+
vars: vars.map((v) => ({ key: v.key, value: args.show ? v.value : redact(v.value) })),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
51
64
|
if (vars.length === 0) {
|
|
52
65
|
consola.info("No environment variables set.");
|
|
53
66
|
return;
|
|
@@ -65,11 +78,15 @@ const envRm = defineCommand({
|
|
|
65
78
|
meta: { name: "rm", description: "Remove an environment variable" },
|
|
66
79
|
args: {
|
|
67
80
|
key: { type: "positional", description: "Variable name to remove", required: true },
|
|
81
|
+
...globalArgs,
|
|
68
82
|
},
|
|
69
83
|
async run({ args }) {
|
|
84
|
+
const jsonMode = resolveJsonMode(args);
|
|
70
85
|
const client = getClient();
|
|
71
86
|
const slug = getProjectSlug();
|
|
72
87
|
await client.deleteEnvVar(slug, args.key);
|
|
88
|
+
if (jsonMode)
|
|
89
|
+
jsonOutput({ ok: true, key: args.key, removed: true, project: slug });
|
|
73
90
|
consola.success(`Removed ${args.key}`);
|
|
74
91
|
},
|
|
75
92
|
});
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export declare const initCommand: import("citty").CommandDef<{
|
|
2
|
+
json: {
|
|
3
|
+
type: "boolean";
|
|
4
|
+
description: string;
|
|
5
|
+
default: boolean;
|
|
6
|
+
};
|
|
7
|
+
yes: {
|
|
8
|
+
type: "boolean";
|
|
9
|
+
description: string;
|
|
10
|
+
default: boolean;
|
|
11
|
+
};
|
|
2
12
|
name: {
|
|
3
13
|
type: "string";
|
|
4
14
|
description: string;
|
package/dist/commands/init.js
CHANGED
|
@@ -4,6 +4,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
4
4
|
import { join, basename } from "node:path";
|
|
5
5
|
import { stringify } from "smol-toml";
|
|
6
6
|
import { detectFramework } from "@solcreek/sdk";
|
|
7
|
+
import { globalArgs, resolveJsonMode, jsonOutput, shouldAutoConfirm } from "../utils/output.js";
|
|
7
8
|
export const initCommand = defineCommand({
|
|
8
9
|
meta: {
|
|
9
10
|
name: "init",
|
|
@@ -15,15 +16,19 @@ export const initCommand = defineCommand({
|
|
|
15
16
|
description: "Project name",
|
|
16
17
|
required: false,
|
|
17
18
|
},
|
|
19
|
+
...globalArgs,
|
|
18
20
|
},
|
|
19
21
|
async run({ args }) {
|
|
22
|
+
const jsonMode = resolveJsonMode(args);
|
|
20
23
|
const cwd = process.cwd();
|
|
21
24
|
const configPath = join(cwd, "creek.toml");
|
|
22
25
|
if (existsSync(configPath)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
if (!shouldAutoConfirm(args)) {
|
|
27
|
+
consola.warn("creek.toml already exists");
|
|
28
|
+
const overwrite = await consola.prompt("Overwrite?", { type: "confirm" });
|
|
29
|
+
if (!overwrite)
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
// Detect framework
|
|
29
34
|
const pkgPath = join(cwd, "package.json");
|
|
@@ -33,7 +38,8 @@ export const initCommand = defineCommand({
|
|
|
33
38
|
const detected = detectFramework(pkg);
|
|
34
39
|
if (detected) {
|
|
35
40
|
framework = detected;
|
|
36
|
-
|
|
41
|
+
if (!jsonMode)
|
|
42
|
+
consola.info(`Detected framework: ${framework}`);
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
const defaultName = basename(cwd).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
@@ -54,6 +60,9 @@ export const initCommand = defineCommand({
|
|
|
54
60
|
},
|
|
55
61
|
};
|
|
56
62
|
writeFileSync(configPath, stringify(config));
|
|
63
|
+
if (jsonMode) {
|
|
64
|
+
jsonOutput({ ok: true, name, framework: framework ?? null, path: configPath });
|
|
65
|
+
}
|
|
57
66
|
consola.success(`Created creek.toml for "${name}"`);
|
|
58
67
|
},
|
|
59
68
|
});
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export declare const loginCommand: import("citty").CommandDef<{
|
|
2
|
+
json: {
|
|
3
|
+
type: "boolean";
|
|
4
|
+
description: string;
|
|
5
|
+
default: boolean;
|
|
6
|
+
};
|
|
7
|
+
yes: {
|
|
8
|
+
type: "boolean";
|
|
9
|
+
description: string;
|
|
10
|
+
default: boolean;
|
|
11
|
+
};
|
|
2
12
|
token: {
|
|
3
13
|
type: "string";
|
|
4
14
|
description: string;
|
package/dist/commands/login.js
CHANGED
|
@@ -4,6 +4,7 @@ import { execFileSync } from "node:child_process";
|
|
|
4
4
|
import { CreekClient } from "@solcreek/sdk";
|
|
5
5
|
import { writeCliConfig, readCliConfig, getApiUrl } from "../utils/config.js";
|
|
6
6
|
import { startAuthServer } from "../utils/auth-server.js";
|
|
7
|
+
import { globalArgs, resolveJsonMode, jsonOutput } from "../utils/output.js";
|
|
7
8
|
function getDashboardUrl() {
|
|
8
9
|
const apiUrl = getApiUrl();
|
|
9
10
|
// http://localhost:8787 → http://localhost:3000
|
|
@@ -41,11 +42,13 @@ export const loginCommand = defineCommand({
|
|
|
41
42
|
description: "Use headless mode (paste API key manually, for SSH/remote)",
|
|
42
43
|
default: false,
|
|
43
44
|
},
|
|
45
|
+
...globalArgs,
|
|
44
46
|
},
|
|
45
47
|
async run({ args }) {
|
|
48
|
+
const jsonMode = resolveJsonMode(args);
|
|
46
49
|
// Mode 1: --token (CI/CD)
|
|
47
50
|
if (args.token) {
|
|
48
|
-
return await saveAndVerify(args.token);
|
|
51
|
+
return await saveAndVerify(args.token, jsonMode);
|
|
49
52
|
}
|
|
50
53
|
// Mode 2: --headless (SSH/remote — prompt for API key)
|
|
51
54
|
if (args.headless) {
|
|
@@ -96,16 +99,22 @@ async function headlessLogin() {
|
|
|
96
99
|
/**
|
|
97
100
|
* Validate key against API, save to config, print success.
|
|
98
101
|
*/
|
|
99
|
-
async function saveAndVerify(apiKey) {
|
|
100
|
-
|
|
102
|
+
async function saveAndVerify(apiKey, jsonMode = false) {
|
|
103
|
+
if (!jsonMode)
|
|
104
|
+
consola.start("Verifying...");
|
|
101
105
|
const client = new CreekClient(getApiUrl(), apiKey);
|
|
102
106
|
const session = await client.getSession();
|
|
103
107
|
if (!session?.user) {
|
|
108
|
+
if (jsonMode)
|
|
109
|
+
jsonOutput({ ok: false, error: "invalid_token", message: "Invalid API key" }, 1);
|
|
104
110
|
consola.error("Invalid API key. Please check and try again.");
|
|
105
111
|
process.exit(1);
|
|
106
112
|
}
|
|
107
113
|
const config = readCliConfig();
|
|
108
114
|
writeCliConfig({ ...config, token: apiKey });
|
|
115
|
+
if (jsonMode) {
|
|
116
|
+
jsonOutput({ ok: true, user: session.user.name, email: session.user.email });
|
|
117
|
+
}
|
|
109
118
|
consola.success(`Logged in as ${session.user.name} (${session.user.email})`);
|
|
110
119
|
}
|
|
111
120
|
//# sourceMappingURL=login.js.map
|
|
@@ -1,2 +1,13 @@
|
|
|
1
|
-
export declare const whoamiCommand: import("citty").CommandDef<
|
|
1
|
+
export declare const whoamiCommand: import("citty").CommandDef<{
|
|
2
|
+
json: {
|
|
3
|
+
type: "boolean";
|
|
4
|
+
description: string;
|
|
5
|
+
default: boolean;
|
|
6
|
+
};
|
|
7
|
+
yes: {
|
|
8
|
+
type: "boolean";
|
|
9
|
+
description: string;
|
|
10
|
+
default: boolean;
|
|
11
|
+
};
|
|
12
|
+
}>;
|
|
2
13
|
//# sourceMappingURL=whoami.d.ts.map
|
package/dist/commands/whoami.js
CHANGED
|
@@ -2,23 +2,39 @@ import { defineCommand } from "citty";
|
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import { CreekClient } from "@solcreek/sdk";
|
|
4
4
|
import { getToken, getApiUrl } from "../utils/config.js";
|
|
5
|
+
import { globalArgs, resolveJsonMode, jsonOutput } from "../utils/output.js";
|
|
5
6
|
export const whoamiCommand = defineCommand({
|
|
6
7
|
meta: {
|
|
7
8
|
name: "whoami",
|
|
8
9
|
description: "Show the currently authenticated user",
|
|
9
10
|
},
|
|
10
|
-
|
|
11
|
+
args: { ...globalArgs },
|
|
12
|
+
async run({ args }) {
|
|
13
|
+
const jsonMode = resolveJsonMode(args);
|
|
11
14
|
const token = getToken();
|
|
12
15
|
if (!token) {
|
|
16
|
+
if (jsonMode)
|
|
17
|
+
jsonOutput({ ok: false, authenticated: false, error: "not_authenticated" }, 1);
|
|
13
18
|
consola.error("Not authenticated. Run `creek login` first.");
|
|
14
19
|
process.exit(1);
|
|
15
20
|
}
|
|
16
21
|
const client = new CreekClient(getApiUrl(), token);
|
|
17
22
|
const session = await client.getSession();
|
|
18
23
|
if (!session?.user) {
|
|
24
|
+
if (jsonMode)
|
|
25
|
+
jsonOutput({ ok: false, authenticated: false, error: "session_expired" }, 1);
|
|
19
26
|
consola.error("Session expired or invalid. Run `creek login` to re-authenticate.");
|
|
20
27
|
process.exit(1);
|
|
21
28
|
}
|
|
29
|
+
if (jsonMode) {
|
|
30
|
+
jsonOutput({
|
|
31
|
+
ok: true,
|
|
32
|
+
authenticated: true,
|
|
33
|
+
user: session.user.name,
|
|
34
|
+
email: session.user.email,
|
|
35
|
+
api: getApiUrl(),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
22
38
|
consola.log(` User: ${session.user.name}`);
|
|
23
39
|
consola.log(` Email: ${session.user.email}`);
|
|
24
40
|
consola.log(` API: ${getApiUrl()}`);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared output utilities for agent-friendly CLI.
|
|
3
|
+
*
|
|
4
|
+
* --json flag + non-TTY auto-detection ensures every command
|
|
5
|
+
* can produce structured output for agents, CI/CD, and pipes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isTTY: boolean;
|
|
8
|
+
/** Output structured JSON and exit. */
|
|
9
|
+
export declare function jsonOutput(data: Record<string, unknown>, exitCode?: number): never;
|
|
10
|
+
/** Resolve JSON mode: explicit --json flag OR non-TTY environment. */
|
|
11
|
+
export declare function resolveJsonMode(args: {
|
|
12
|
+
json?: boolean;
|
|
13
|
+
}): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Common --json and --yes args to spread into any command's args definition.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* args: { ...globalArgs, myArg: { ... } }
|
|
19
|
+
*/
|
|
20
|
+
export declare const globalArgs: {
|
|
21
|
+
json: {
|
|
22
|
+
type: "boolean";
|
|
23
|
+
description: string;
|
|
24
|
+
default: boolean;
|
|
25
|
+
};
|
|
26
|
+
yes: {
|
|
27
|
+
type: "boolean";
|
|
28
|
+
description: string;
|
|
29
|
+
default: boolean;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/** Should we skip interactive prompts? */
|
|
33
|
+
export declare function shouldAutoConfirm(args: {
|
|
34
|
+
yes?: boolean;
|
|
35
|
+
}): boolean;
|
|
36
|
+
/** Output an error in the appropriate format and exit. */
|
|
37
|
+
export declare function exitError(jsonMode: boolean, error: string, message: string, exitCode?: number): never;
|
|
38
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared output utilities for agent-friendly CLI.
|
|
3
|
+
*
|
|
4
|
+
* --json flag + non-TTY auto-detection ensures every command
|
|
5
|
+
* can produce structured output for agents, CI/CD, and pipes.
|
|
6
|
+
*/
|
|
7
|
+
export const isTTY = process.stdout.isTTY ?? false;
|
|
8
|
+
/** Output structured JSON and exit. */
|
|
9
|
+
export function jsonOutput(data, exitCode = 0) {
|
|
10
|
+
process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
11
|
+
process.exit(exitCode);
|
|
12
|
+
}
|
|
13
|
+
/** Resolve JSON mode: explicit --json flag OR non-TTY environment. */
|
|
14
|
+
export function resolveJsonMode(args) {
|
|
15
|
+
return args.json === true || !isTTY;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Common --json and --yes args to spread into any command's args definition.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* args: { ...globalArgs, myArg: { ... } }
|
|
22
|
+
*/
|
|
23
|
+
export const globalArgs = {
|
|
24
|
+
json: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
description: "Output results as JSON (auto-enabled in CI/CD and pipes)",
|
|
27
|
+
default: false,
|
|
28
|
+
},
|
|
29
|
+
yes: {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
description: "Skip confirmation prompts (auto-enabled in non-TTY)",
|
|
32
|
+
default: false,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
/** Should we skip interactive prompts? */
|
|
36
|
+
export function shouldAutoConfirm(args) {
|
|
37
|
+
return args.yes === true || !isTTY;
|
|
38
|
+
}
|
|
39
|
+
/** Output an error in the appropriate format and exit. */
|
|
40
|
+
export function exitError(jsonMode, error, message, exitCode = 1) {
|
|
41
|
+
if (jsonMode)
|
|
42
|
+
jsonOutput({ ok: false, error, message }, exitCode);
|
|
43
|
+
return process.exit(exitCode);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=output.js.map
|
package/dist/utils/sandbox.js
CHANGED
|
@@ -46,12 +46,9 @@ export async function pollSandboxStatus(statusUrl) {
|
|
|
46
46
|
* Print sandbox success message with claim instructions.
|
|
47
47
|
*/
|
|
48
48
|
export function printSandboxSuccess(previewUrl, expiresAt, sandboxId) {
|
|
49
|
-
consola.success(`
|
|
49
|
+
consola.success(` Live → ${previewUrl}`);
|
|
50
50
|
consola.info("");
|
|
51
|
-
consola.info("
|
|
52
|
-
consola.info("");
|
|
53
|
-
consola.info("Want to keep it? Make it permanent:");
|
|
54
|
-
consola.info(` creek login`);
|
|
55
|
-
consola.info(` creek claim ${sandboxId}`);
|
|
51
|
+
consola.info(" Free preview — available for 60 minutes.");
|
|
52
|
+
consola.info(" Make it permanent: creek login && creek claim " + sandboxId);
|
|
56
53
|
}
|
|
57
54
|
//# sourceMappingURL=sandbox.js.map
|