howone 0.1.3 → 0.1.5
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/bin/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { say, spinner } from "@astrojs/cli-kit";
|
|
4
|
+
import { cancel, confirm, isCancel, select, text } from "@clack/prompts";
|
|
5
5
|
import { readdir, rename, stat, writeFile } from "node:fs/promises";
|
|
6
6
|
import { copy, emptyDir, ensureDir, pathExists } from "fs-extra/esm";
|
|
7
|
-
import pc from "picocolors";
|
|
8
7
|
import path from "node:path";
|
|
9
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
+
import pc from "picocolors";
|
|
10
10
|
import validatePackageName from "validate-npm-package-name";
|
|
11
|
+
import yargsParser from "yargs-parser";
|
|
11
12
|
//#region src/index.ts
|
|
12
13
|
const packageJson = createRequire(import.meta.url)("../package.json");
|
|
13
14
|
const DEFAULT_PROJECT_NAME = "howone-app";
|
|
@@ -25,78 +26,108 @@ var CliError = class extends Error {
|
|
|
25
26
|
this.name = "CliError";
|
|
26
27
|
}
|
|
27
28
|
};
|
|
28
|
-
|
|
29
|
-
cli.version(packageJson.version, "-v, --version");
|
|
30
|
-
cli.help();
|
|
31
|
-
cli.command("create [projectName] [legacyProjectName]", "Create a new project from a HowOne template.").alias("new").alias("init").option("-t, --template <template>", "Template to use: vite, nextjs").option("--vite", "Shortcut for --template vite").option("--nextjs", "Shortcut for --template nextjs").option("--next", "Alias for --nextjs").option("-f, --force", "Overwrite an existing non-empty target directory").option("-y, --yes", "Disable prompts and accept defaults where possible").option("--json", "Print machine-readable JSON output").option("--cwd <dir>", "Directory in which to create the project").example("howone vite my-app").example("howone next my-app").example("howone create my-app --template vite").example("howone create my-app --template nextjs --yes").example("howone create my-app --template vite --json --yes").example("howone create template --vite my-app").action((projectName, legacyProjectName, options) => {
|
|
32
|
-
runCreate(projectName, legacyProjectName, options).catch((error) => handleFatalError(error, Boolean(options.json)));
|
|
33
|
-
});
|
|
34
|
-
try {
|
|
35
|
-
cli.parse(normalizeCliArgv(process.argv), { run: true });
|
|
36
|
-
} catch (error) {
|
|
29
|
+
main().catch((error) => {
|
|
37
30
|
handleFatalError(error, process.argv.includes("--json"));
|
|
31
|
+
});
|
|
32
|
+
async function main() {
|
|
33
|
+
const command = parseCommand(process.argv.slice(2));
|
|
34
|
+
if (command.options.version) {
|
|
35
|
+
console.log(packageJson.version);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (command.options.help || command.path.length === 0) {
|
|
39
|
+
printHelp(command.path);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const [scope, subcommand, ...rest] = command.path;
|
|
43
|
+
if (isTemplateAlias(scope)) {
|
|
44
|
+
await runInitApp(compact([subcommand, ...rest]), {
|
|
45
|
+
...command.options,
|
|
46
|
+
template: resolveTemplateAlias(scope)
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (scope === "init" || scope === "new") {
|
|
51
|
+
await runInitApp(subcommand === "app" ? rest : compact([subcommand, ...rest]), command.options);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (scope === "create") {
|
|
55
|
+
await runCreatePlaceholder(command.options);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (scope === "deploy") {
|
|
59
|
+
await runDeploy(command.options);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (scope === "ai" && subcommand === "run") {
|
|
63
|
+
await runAiRun(rest, command.options);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
throw new CliError("E_COMMAND_UNKNOWN", `Unknown command: ${command.path.join(" ")}`);
|
|
38
67
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
template
|
|
79
|
-
];
|
|
80
|
-
}
|
|
81
|
-
function resolveTemplateAlias(value) {
|
|
82
|
-
if (!value) return void 0;
|
|
83
|
-
const normalized = TEMPLATE_ALIASES[value];
|
|
84
|
-
return normalized && isTemplate(normalized) ? normalized : void 0;
|
|
68
|
+
function parseCommand(args) {
|
|
69
|
+
const hasHelp = args.includes("--help") || args.includes("-h");
|
|
70
|
+
const hasVersion = args.includes("--version") || args.includes("-v");
|
|
71
|
+
const parsed = yargsParser(args, {
|
|
72
|
+
alias: {
|
|
73
|
+
h: "help",
|
|
74
|
+
v: "version",
|
|
75
|
+
t: "template",
|
|
76
|
+
f: "force",
|
|
77
|
+
y: "yes"
|
|
78
|
+
},
|
|
79
|
+
boolean: [
|
|
80
|
+
"help",
|
|
81
|
+
"version",
|
|
82
|
+
"vite",
|
|
83
|
+
"nextjs",
|
|
84
|
+
"next",
|
|
85
|
+
"force",
|
|
86
|
+
"yes",
|
|
87
|
+
"json"
|
|
88
|
+
],
|
|
89
|
+
string: ["template", "cwd"],
|
|
90
|
+
configuration: { "camel-case-expansion": false }
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
path: parsed._.map(String),
|
|
94
|
+
options: {
|
|
95
|
+
template: typeof parsed.template === "string" ? parsed.template : void 0,
|
|
96
|
+
vite: Boolean(parsed.vite),
|
|
97
|
+
nextjs: Boolean(parsed.nextjs),
|
|
98
|
+
next: Boolean(parsed.next),
|
|
99
|
+
force: Boolean(parsed.force),
|
|
100
|
+
yes: Boolean(parsed.yes),
|
|
101
|
+
json: Boolean(parsed.json),
|
|
102
|
+
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
|
|
103
|
+
help: Boolean(parsed.help) || hasHelp,
|
|
104
|
+
version: Boolean(parsed.version) || hasVersion
|
|
105
|
+
}
|
|
106
|
+
};
|
|
85
107
|
}
|
|
86
|
-
function
|
|
87
|
-
return
|
|
108
|
+
function compact(values) {
|
|
109
|
+
return values.filter((value) => Boolean(value));
|
|
88
110
|
}
|
|
89
|
-
async function
|
|
90
|
-
const plan = await resolveCreatePlan(
|
|
91
|
-
|
|
92
|
-
await createTemplate(plan,
|
|
111
|
+
async function runInitApp(pathArgs, options) {
|
|
112
|
+
const plan = await resolveCreatePlan(pathArgs, options, path.resolve(options.cwd ?? process.cwd()), process.stdout.isTTY && !options.yes && !options.json);
|
|
113
|
+
const howoneContext = resolveHowoneCreateContext();
|
|
114
|
+
if (options.json) await createTemplate(plan, howoneContext, true);
|
|
115
|
+
else {
|
|
116
|
+
await say(pc.bold("HowOne"));
|
|
117
|
+
await createTemplate(plan, howoneContext, false);
|
|
118
|
+
}
|
|
93
119
|
const result = {
|
|
94
120
|
ok: true,
|
|
95
|
-
command: "
|
|
121
|
+
command: "init app",
|
|
96
122
|
template: plan.template,
|
|
97
123
|
projectName: plan.projectName,
|
|
98
124
|
targetDir: plan.targetDir,
|
|
99
125
|
packageManager: "bun",
|
|
126
|
+
...howoneContext ? { howone: {
|
|
127
|
+
projectId: howoneContext.projectId,
|
|
128
|
+
env: howoneContext.env,
|
|
129
|
+
envFile: path.join(plan.targetDir, ".env")
|
|
130
|
+
} } : {},
|
|
100
131
|
nextSteps: [
|
|
101
132
|
`cd ${formatPathForShell(path.relative(plan.cwd, plan.targetDir) || ".")}`,
|
|
102
133
|
"bun install",
|
|
@@ -107,16 +138,51 @@ async function runCreate(projectNameArg, legacyProjectNameArg, options) {
|
|
|
107
138
|
console.log(JSON.stringify(result, null, 2));
|
|
108
139
|
return;
|
|
109
140
|
}
|
|
110
|
-
|
|
111
|
-
`${pc.green("Created")} ${pc.bold(plan.template)} template in ${pc.cyan(path.relative(plan.cwd, plan.targetDir) || ".")}`,
|
|
112
|
-
"",
|
|
113
|
-
pc.bold("Next steps:"),
|
|
114
|
-
...result.nextSteps.map((step) => ` ${step}`)
|
|
115
|
-
].join("\n"));
|
|
141
|
+
printCreateSuccess(plan, result);
|
|
116
142
|
}
|
|
117
|
-
async function
|
|
143
|
+
async function runCreatePlaceholder(options) {
|
|
144
|
+
const result = {
|
|
145
|
+
ok: true,
|
|
146
|
+
command: "create",
|
|
147
|
+
status: "pending",
|
|
148
|
+
message: "howone create is reserved for a future workflow."
|
|
149
|
+
};
|
|
150
|
+
if (options.json) {
|
|
151
|
+
console.log(JSON.stringify(result, null, 2));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
printPending("howone create", result.message ?? "howone create is reserved for a future workflow.");
|
|
155
|
+
}
|
|
156
|
+
async function runDeploy(options) {
|
|
157
|
+
const result = {
|
|
158
|
+
ok: true,
|
|
159
|
+
command: "deploy",
|
|
160
|
+
status: "pending",
|
|
161
|
+
message: "howone deploy is not implemented yet."
|
|
162
|
+
};
|
|
163
|
+
if (options.json) {
|
|
164
|
+
console.log(JSON.stringify(result, null, 2));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
printPending("howone deploy", "Deploy is not implemented yet.");
|
|
168
|
+
}
|
|
169
|
+
async function runAiRun(pathArgs, options) {
|
|
170
|
+
const aiId = pathArgs[0];
|
|
171
|
+
const result = {
|
|
172
|
+
ok: true,
|
|
173
|
+
command: "ai run",
|
|
174
|
+
status: "pending",
|
|
175
|
+
message: aiId ? `howone ai run ${aiId} is not implemented yet.` : "howone ai run is not implemented yet."
|
|
176
|
+
};
|
|
177
|
+
if (options.json) {
|
|
178
|
+
console.log(JSON.stringify(result, null, 2));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
printPending("howone ai run", result.message ?? "AI run is not implemented yet.");
|
|
182
|
+
}
|
|
183
|
+
async function resolveCreatePlan(pathArgs, options, cwd, isInteractive) {
|
|
118
184
|
const template = resolveTemplateOption(options);
|
|
119
|
-
const projectName =
|
|
185
|
+
const projectName = pathArgs[0] === "template" ? pathArgs[1] : pathArgs[0];
|
|
120
186
|
const resolvedTemplate = template ?? (isInteractive ? await promptTemplate() : void 0);
|
|
121
187
|
if (!resolvedTemplate) throw new CliError("E_TEMPLATE_REQUIRED", "Missing template. Use --template vite or --template nextjs.");
|
|
122
188
|
const resolvedProjectName = projectName ?? (isInteractive ? await promptProjectName() : DEFAULT_PROJECT_NAME);
|
|
@@ -130,7 +196,8 @@ async function resolveCreatePlan(projectNameArg, legacyProjectNameArg, options,
|
|
|
130
196
|
entries: entries.slice(0, 20),
|
|
131
197
|
retryWithForce: [
|
|
132
198
|
"howone",
|
|
133
|
-
"
|
|
199
|
+
"init",
|
|
200
|
+
"app",
|
|
134
201
|
resolvedProjectName,
|
|
135
202
|
"--template",
|
|
136
203
|
resolvedTemplate,
|
|
@@ -145,10 +212,11 @@ async function resolveCreatePlan(projectNameArg, legacyProjectNameArg, options,
|
|
|
145
212
|
message: `Directory "${path.relative(cwd, targetDir) || "."}" is not empty. Overwrite it?`,
|
|
146
213
|
initialValue: false
|
|
147
214
|
});
|
|
148
|
-
if (isCancel(shouldOverwrite)
|
|
215
|
+
if (isCancel(shouldOverwrite)) {
|
|
149
216
|
cancel("Cancelled.");
|
|
150
217
|
process.exit(0);
|
|
151
218
|
}
|
|
219
|
+
if (!shouldOverwrite) throw new CliError("E_CANCELLED", "Cancelled.");
|
|
152
220
|
}
|
|
153
221
|
await assertTargetWritable(targetDir);
|
|
154
222
|
return {
|
|
@@ -210,12 +278,21 @@ async function promptProjectName() {
|
|
|
210
278
|
cancel("Cancelled.");
|
|
211
279
|
process.exit(0);
|
|
212
280
|
}
|
|
213
|
-
return value;
|
|
281
|
+
return String(value || DEFAULT_PROJECT_NAME);
|
|
214
282
|
}
|
|
215
|
-
async function createTemplate(plan, json) {
|
|
283
|
+
async function createTemplate(plan, howoneContext, json) {
|
|
284
|
+
if (json) {
|
|
285
|
+
await performCreateTemplate(plan, howoneContext);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
await spinner({
|
|
289
|
+
start: "Creating project",
|
|
290
|
+
end: "Project created",
|
|
291
|
+
while: () => performCreateTemplate(plan, howoneContext)
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async function performCreateTemplate(plan, howoneContext) {
|
|
216
295
|
const templateDir = getTemplateDir(plan.template);
|
|
217
|
-
const task = json ? null : spinner();
|
|
218
|
-
task?.start("Creating project");
|
|
219
296
|
if (plan.force && await pathExists(plan.targetDir)) await emptyDir(plan.targetDir);
|
|
220
297
|
else await ensureDir(plan.targetDir);
|
|
221
298
|
await copy(templateDir, plan.targetDir, {
|
|
@@ -226,9 +303,8 @@ async function createTemplate(plan, json) {
|
|
|
226
303
|
}
|
|
227
304
|
});
|
|
228
305
|
await restoreGitignore(plan.targetDir);
|
|
229
|
-
await writeHowoneEnvFile(plan);
|
|
306
|
+
await writeHowoneEnvFile(plan, howoneContext);
|
|
230
307
|
await assertTemplateCopied(plan);
|
|
231
|
-
task?.stop("Project created");
|
|
232
308
|
}
|
|
233
309
|
function normalizeHowoneEnv(value) {
|
|
234
310
|
const normalized = value?.trim().toLowerCase();
|
|
@@ -238,7 +314,7 @@ function normalizeHowoneEnv(value) {
|
|
|
238
314
|
if (normalized === "local" || normalized === "dev" || normalized === "prod") return normalized;
|
|
239
315
|
return "dev";
|
|
240
316
|
}
|
|
241
|
-
function
|
|
317
|
+
function resolveHowoneCreateContext() {
|
|
242
318
|
const projectId = process.env.HOWONE_PROJECT_ID?.trim();
|
|
243
319
|
if (!projectId) return null;
|
|
244
320
|
return {
|
|
@@ -250,10 +326,9 @@ function getTemplateEnvEntries(template, context) {
|
|
|
250
326
|
if (template === "vite") return [["VITE_HOWONE_PROJECT_ID", context.projectId], ["VITE_HOWONE_ENV", context.env]];
|
|
251
327
|
return [["NEXT_PUBLIC_HOWONE_PROJECT_ID", context.projectId], ["NEXT_PUBLIC_HOWONE_ENV", context.env]];
|
|
252
328
|
}
|
|
253
|
-
async function writeHowoneEnvFile(plan) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const lines = getTemplateEnvEntries(plan.template, context).map(([key, value]) => `${key}=${value}`);
|
|
329
|
+
async function writeHowoneEnvFile(plan, howoneContext) {
|
|
330
|
+
if (!howoneContext) return;
|
|
331
|
+
const lines = getTemplateEnvEntries(plan.template, howoneContext).map(([key, value]) => `${key}=${value}`);
|
|
257
332
|
await writeFile(path.join(plan.targetDir, ".env"), [...lines, ""].join("\n"), "utf-8");
|
|
258
333
|
}
|
|
259
334
|
function getTemplateDir(template) {
|
|
@@ -288,19 +363,106 @@ function validateProjectName(projectName) {
|
|
|
288
363
|
if (result.validForNewPackages) return;
|
|
289
364
|
throw new CliError("E_PROJECT_NAME_INVALID", [...result.errors ?? [], ...result.warnings ?? []][0] ?? `Invalid project name: ${projectName}`);
|
|
290
365
|
}
|
|
366
|
+
function resolveTemplateAlias(value) {
|
|
367
|
+
if (!value) return void 0;
|
|
368
|
+
const normalized = TEMPLATE_ALIASES[value];
|
|
369
|
+
return normalized && isTemplate(normalized) ? normalized : void 0;
|
|
370
|
+
}
|
|
371
|
+
function isTemplateAlias(value) {
|
|
372
|
+
return Boolean(resolveTemplateAlias(value));
|
|
373
|
+
}
|
|
291
374
|
function isTemplate(value) {
|
|
292
|
-
return TEMPLATES.includes(value);
|
|
375
|
+
return typeof value === "string" && TEMPLATES.includes(value);
|
|
293
376
|
}
|
|
294
377
|
function formatPathForShell(value) {
|
|
295
378
|
return value.includes(" ") ? JSON.stringify(value) : value;
|
|
296
379
|
}
|
|
297
|
-
function
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
380
|
+
function printHelp(pathArgs) {
|
|
381
|
+
const topic = pathArgs.join(" ");
|
|
382
|
+
if (topic === "init" || topic === "init app" || topic === "new" || topic === "new app") {
|
|
383
|
+
printInitHelp();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (topic === "create") {
|
|
387
|
+
printReservedHelp("howone create", "Reserved for a future create workflow.");
|
|
388
|
+
return;
|
|
301
389
|
}
|
|
302
|
-
|
|
303
|
-
|
|
390
|
+
if (topic === "deploy") {
|
|
391
|
+
printReservedHelp("howone deploy", "Deploy support is reserved and not implemented yet.");
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (topic === "ai" || topic === "ai run") {
|
|
395
|
+
printReservedHelp("howone ai run [aiId]", "AI run support is reserved and not implemented yet.");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
printRootHelp();
|
|
399
|
+
}
|
|
400
|
+
function printRootHelp() {
|
|
401
|
+
console.log(formatPanel(`${pc.bold("HowOne CLI")} ${pc.dim(`v${packageJson.version}`)}`, [
|
|
402
|
+
`${pc.dim("Usage")} howone <command> [options]`,
|
|
403
|
+
"",
|
|
404
|
+
pc.bold("Commands"),
|
|
405
|
+
formatCommand("init app [name]", "Create an app from a template"),
|
|
406
|
+
formatCommand("create", "Reserved placeholder"),
|
|
407
|
+
formatCommand("deploy", "Reserved placeholder"),
|
|
408
|
+
formatCommand("ai run [aiId]", "Reserved placeholder"),
|
|
409
|
+
"",
|
|
410
|
+
pc.bold("Options"),
|
|
411
|
+
formatCommand("-h, --help", "Show help"),
|
|
412
|
+
formatCommand("-v, --version", "Show version"),
|
|
413
|
+
"",
|
|
414
|
+
pc.bold("Examples"),
|
|
415
|
+
` ${pc.cyan("howone init app my-app --template vite")}`,
|
|
416
|
+
` ${pc.cyan("howone deploy")}`,
|
|
417
|
+
` ${pc.cyan("howone ai run generateImage")}`
|
|
418
|
+
]));
|
|
419
|
+
}
|
|
420
|
+
function printInitHelp() {
|
|
421
|
+
console.log(formatPanel(`${pc.bold("Create an app")}`, [
|
|
422
|
+
`${pc.dim("Usage")} howone init app [name] [options]`,
|
|
423
|
+
"",
|
|
424
|
+
pc.bold("Options"),
|
|
425
|
+
formatCommand("-t, --template <template>", "Template to use: vite, nextjs"),
|
|
426
|
+
formatCommand("--vite", "Shortcut for --template vite"),
|
|
427
|
+
formatCommand("--nextjs", "Shortcut for --template nextjs"),
|
|
428
|
+
formatCommand("--next", "Alias for --nextjs"),
|
|
429
|
+
formatCommand("-f, --force", "Overwrite an existing non-empty directory"),
|
|
430
|
+
formatCommand("-y, --yes", "Disable prompts and accept defaults"),
|
|
431
|
+
formatCommand("--json", "Print machine-readable JSON output"),
|
|
432
|
+
formatCommand("--cwd <dir>", "Directory in which to create the app"),
|
|
433
|
+
"",
|
|
434
|
+
pc.bold("Examples"),
|
|
435
|
+
` ${pc.cyan("howone init app my-app --template vite")}`,
|
|
436
|
+
` ${pc.cyan("howone init app my-app --template nextjs --yes")}`
|
|
437
|
+
]));
|
|
438
|
+
}
|
|
439
|
+
function printReservedHelp(command, description) {
|
|
440
|
+
console.log(formatPanel(pc.bold(command), [
|
|
441
|
+
description,
|
|
442
|
+
"",
|
|
443
|
+
`${pc.yellow("Pending")} This command is available as a stable placeholder.`
|
|
444
|
+
]));
|
|
445
|
+
}
|
|
446
|
+
function printPending(command, message) {
|
|
447
|
+
console.log(formatPanel(pc.bold(command), [`${pc.yellow("Pending")} ${message}`]));
|
|
448
|
+
}
|
|
449
|
+
function printCreateSuccess(plan, result) {
|
|
450
|
+
const relativeTarget = path.relative(plan.cwd, plan.targetDir) || ".";
|
|
451
|
+
const lines = [`${pc.green("Created")} ${pc.bold(plan.template)} app in ${pc.cyan(relativeTarget)}`];
|
|
452
|
+
if (result.howone) lines.push("", pc.bold("HowOne context"), formatCommand("project", result.howone.projectId), formatCommand("env", result.howone.env), formatCommand("file", path.relative(plan.cwd, result.howone.envFile) || ".env"));
|
|
453
|
+
lines.push("", pc.bold("Next steps"), ...(result.nextSteps ?? []).map((step) => ` ${pc.cyan(step)}`));
|
|
454
|
+
console.log(formatPanel(pc.bold("App ready"), lines));
|
|
455
|
+
}
|
|
456
|
+
function formatPanel(title, lines) {
|
|
457
|
+
return [`${pc.green("◆")} ${title}`, ...lines.map((line) => line ? ` ${line}` : "")].join("\n");
|
|
458
|
+
}
|
|
459
|
+
function formatCommand(command, description) {
|
|
460
|
+
return ` ${pc.cyan(command.padEnd(28))} ${description}`;
|
|
461
|
+
}
|
|
462
|
+
function handleFatalError(error, json) {
|
|
463
|
+
const cliError = error instanceof CliError ? error : new CliError("E_UNEXPECTED", error instanceof Error ? error.message : String(error));
|
|
464
|
+
printError(cliError, json);
|
|
465
|
+
process.exit(cliError.code === "E_CANCELLED" ? 0 : 1);
|
|
304
466
|
}
|
|
305
467
|
function printError(error, json) {
|
|
306
468
|
const payload = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "howone",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "HowOne command line tools for creating app templates.",
|
|
6
6
|
"type": "module",
|
|
@@ -27,17 +27,19 @@
|
|
|
27
27
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@astrojs/cli-kit": "^0.4.1",
|
|
30
31
|
"@clack/prompts": "^1.3.0",
|
|
31
|
-
"cac": "^7.0.0",
|
|
32
32
|
"fs-extra": "^11.3.4",
|
|
33
33
|
"picocolors": "^1.1.1",
|
|
34
|
-
"validate-npm-package-name": "^7.0.2"
|
|
34
|
+
"validate-npm-package-name": "^7.0.2",
|
|
35
|
+
"yargs-parser": "^22.0.0"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@howone/tsconfig": "workspace:*",
|
|
38
39
|
"@types/fs-extra": "^11.0.4",
|
|
39
40
|
"@types/node": "^25.6.0",
|
|
40
41
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
42
|
+
"@types/yargs-parser": "^21.0.3",
|
|
41
43
|
"tsdown": "^0.21.10",
|
|
42
44
|
"typescript": "^5.7.3"
|
|
43
45
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { createClient, defineEntities, withEntities } from '@howone/sdk'
|
|
2
2
|
|
|
3
|
-
export const HOWONE_PROJECT_ID = process.env.NEXT_PUBLIC_HOWONE_PROJECT_ID ?? 'demo'
|
|
4
|
-
|
|
5
3
|
const client = createClient({
|
|
6
|
-
projectId:
|
|
7
|
-
env:
|
|
4
|
+
projectId: process.env.NEXT_PUBLIC_HOWONE_PROJECT_ID,
|
|
5
|
+
env: process.env.NEXT_PUBLIC_HOWONE_ENV,
|
|
8
6
|
})
|
|
9
7
|
|
|
10
8
|
export const entities = defineEntities({
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { createClient, defineEntities, withEntities } from '@howone/sdk'
|
|
2
2
|
|
|
3
|
-
export const HOWONE_PROJECT_ID = import.meta.env.VITE_HOWONE_PROJECT_ID
|
|
4
|
-
|
|
5
3
|
const client = createClient({
|
|
6
|
-
projectId:
|
|
7
|
-
env: import.meta.env.VITE_HOWONE_ENV
|
|
4
|
+
projectId: import.meta.env.VITE_HOWONE_PROJECT_ID,
|
|
5
|
+
env: import.meta.env.VITE_HOWONE_ENV,
|
|
8
6
|
})
|
|
9
7
|
|
|
10
8
|
export const entities = defineEntities({
|