howone 0.1.1 → 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 {
|
|
5
|
-
import { readdir, rename, stat } from "node:fs/promises";
|
|
3
|
+
import { say, spinner } from "@astrojs/cli-kit";
|
|
4
|
+
import { cancel, confirm, isCancel, select, text } from "@clack/prompts";
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
141
|
+
printCreateSuccess(plan, result);
|
|
142
|
+
}
|
|
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.");
|
|
116
168
|
}
|
|
117
|
-
async function
|
|
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);
|
|
282
|
+
}
|
|
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
|
+
});
|
|
214
293
|
}
|
|
215
|
-
async function
|
|
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,8 +303,33 @@ async function createTemplate(plan, json) {
|
|
|
226
303
|
}
|
|
227
304
|
});
|
|
228
305
|
await restoreGitignore(plan.targetDir);
|
|
306
|
+
await writeHowoneEnvFile(plan, howoneContext);
|
|
229
307
|
await assertTemplateCopied(plan);
|
|
230
|
-
|
|
308
|
+
}
|
|
309
|
+
function normalizeHowoneEnv(value) {
|
|
310
|
+
const normalized = value?.trim().toLowerCase();
|
|
311
|
+
if (!normalized) return "dev";
|
|
312
|
+
if (normalized === "development") return "dev";
|
|
313
|
+
if (normalized === "production") return "prod";
|
|
314
|
+
if (normalized === "local" || normalized === "dev" || normalized === "prod") return normalized;
|
|
315
|
+
return "dev";
|
|
316
|
+
}
|
|
317
|
+
function resolveHowoneCreateContext() {
|
|
318
|
+
const projectId = process.env.HOWONE_PROJECT_ID?.trim();
|
|
319
|
+
if (!projectId) return null;
|
|
320
|
+
return {
|
|
321
|
+
projectId,
|
|
322
|
+
env: normalizeHowoneEnv(process.env.HOWONE_ENV ?? process.env.APP_ENV)
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function getTemplateEnvEntries(template, context) {
|
|
326
|
+
if (template === "vite") return [["VITE_HOWONE_PROJECT_ID", context.projectId], ["VITE_HOWONE_ENV", context.env]];
|
|
327
|
+
return [["NEXT_PUBLIC_HOWONE_PROJECT_ID", context.projectId], ["NEXT_PUBLIC_HOWONE_ENV", context.env]];
|
|
328
|
+
}
|
|
329
|
+
async function writeHowoneEnvFile(plan, howoneContext) {
|
|
330
|
+
if (!howoneContext) return;
|
|
331
|
+
const lines = getTemplateEnvEntries(plan.template, howoneContext).map(([key, value]) => `${key}=${value}`);
|
|
332
|
+
await writeFile(path.join(plan.targetDir, ".env"), [...lines, ""].join("\n"), "utf-8");
|
|
231
333
|
}
|
|
232
334
|
function getTemplateDir(template) {
|
|
233
335
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -261,19 +363,106 @@ function validateProjectName(projectName) {
|
|
|
261
363
|
if (result.validForNewPackages) return;
|
|
262
364
|
throw new CliError("E_PROJECT_NAME_INVALID", [...result.errors ?? [], ...result.warnings ?? []][0] ?? `Invalid project name: ${projectName}`);
|
|
263
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
|
+
}
|
|
264
374
|
function isTemplate(value) {
|
|
265
|
-
return TEMPLATES.includes(value);
|
|
375
|
+
return typeof value === "string" && TEMPLATES.includes(value);
|
|
266
376
|
}
|
|
267
377
|
function formatPathForShell(value) {
|
|
268
378
|
return value.includes(" ") ? JSON.stringify(value) : value;
|
|
269
379
|
}
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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;
|
|
389
|
+
}
|
|
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;
|
|
274
397
|
}
|
|
275
|
-
|
|
276
|
-
|
|
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);
|
|
277
466
|
}
|
|
278
467
|
function printError(error, json) {
|
|
279
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,9 +1,8 @@
|
|
|
1
1
|
import { createClient, defineEntities, withEntities } from '@howone/sdk'
|
|
2
2
|
|
|
3
|
-
export const HOWONE_PROJECT_ID = 'demo'
|
|
4
|
-
|
|
5
3
|
const client = createClient({
|
|
6
|
-
projectId:
|
|
4
|
+
projectId: process.env.NEXT_PUBLIC_HOWONE_PROJECT_ID,
|
|
5
|
+
env: process.env.NEXT_PUBLIC_HOWONE_ENV,
|
|
7
6
|
})
|
|
8
7
|
|
|
9
8
|
export const entities = defineEntities({
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createClient, defineEntities, withEntities } from '@howone/sdk'
|
|
2
2
|
|
|
3
|
-
export const HOWONE_PROJECT_ID = 'demo'
|
|
4
|
-
|
|
5
3
|
const client = createClient({
|
|
6
|
-
projectId:
|
|
4
|
+
projectId: import.meta.env.VITE_HOWONE_PROJECT_ID,
|
|
5
|
+
env: import.meta.env.VITE_HOWONE_ENV,
|
|
7
6
|
})
|
|
8
7
|
|
|
9
8
|
export const entities = defineEntities({
|