howone 0.1.18 → 0.1.19
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 +36 -10
- package/package.json +1 -1
- package/templates/vite/AGENTS.md +49 -58
- package/templates/vite/package.json +1 -1
package/bin/index.mjs
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import {
|
|
4
|
-
import { cancel, confirm, isCancel, select, text } from "@clack/prompts";
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
5
4
|
import { readdir, rename, stat, writeFile } from "node:fs/promises";
|
|
6
|
-
import { copy, emptyDir, ensureDir, pathExists } from "fs-extra/esm";
|
|
7
5
|
import path from "node:path";
|
|
8
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { say, spinner } from "@astrojs/cli-kit";
|
|
9
|
+
import { cancel, confirm, isCancel, select, text } from "@clack/prompts";
|
|
10
|
+
import { copy, emptyDir, ensureDir, pathExists } from "fs-extra/esm";
|
|
9
11
|
import pc from "picocolors";
|
|
10
12
|
import validatePackageName from "validate-npm-package-name";
|
|
11
13
|
import yargsParser from "yargs-parser";
|
|
12
14
|
//#region src/index.ts
|
|
13
15
|
const packageJson = createRequire(import.meta.url)("../package.json");
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
14
17
|
const DEFAULT_PROJECT_NAME = "howone-app";
|
|
15
18
|
const TEMPLATES = ["vite", "nextjs"];
|
|
16
19
|
const TEMPLATE_ALIASES = {
|
|
@@ -111,10 +114,13 @@ function compact(values) {
|
|
|
111
114
|
async function runInitApp(pathArgs, options) {
|
|
112
115
|
const plan = await resolveCreatePlan(pathArgs, options, path.resolve(options.cwd ?? process.cwd()), process.stdout.isTTY && !options.yes && !options.json);
|
|
113
116
|
const howoneContext = resolveHowoneCreateContext();
|
|
114
|
-
if (options.json)
|
|
115
|
-
|
|
117
|
+
if (options.json) {
|
|
118
|
+
await createTemplate(plan, howoneContext, true);
|
|
119
|
+
await installTemplateDependencies(plan, true);
|
|
120
|
+
} else {
|
|
116
121
|
await say(pc.bold("HowOne"));
|
|
117
122
|
await createTemplate(plan, howoneContext, false);
|
|
123
|
+
await installTemplateDependencies(plan, false);
|
|
118
124
|
}
|
|
119
125
|
const result = {
|
|
120
126
|
ok: true,
|
|
@@ -128,11 +134,7 @@ async function runInitApp(pathArgs, options) {
|
|
|
128
134
|
env: howoneContext.env,
|
|
129
135
|
envFile: path.join(plan.targetDir, ".env")
|
|
130
136
|
} } : {},
|
|
131
|
-
nextSteps: [
|
|
132
|
-
`cd ${formatPathForShell(path.relative(plan.cwd, plan.targetDir) || ".")}`,
|
|
133
|
-
"bun install",
|
|
134
|
-
"bun run dev"
|
|
135
|
-
]
|
|
137
|
+
nextSteps: [`cd ${formatPathForShell(path.relative(plan.cwd, plan.targetDir) || ".")}`, "bun run dev"]
|
|
136
138
|
};
|
|
137
139
|
if (options.json) {
|
|
138
140
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -291,6 +293,30 @@ async function createTemplate(plan, howoneContext, json) {
|
|
|
291
293
|
while: () => performCreateTemplate(plan, howoneContext)
|
|
292
294
|
});
|
|
293
295
|
}
|
|
296
|
+
async function installTemplateDependencies(plan, json) {
|
|
297
|
+
const install = async () => {
|
|
298
|
+
try {
|
|
299
|
+
await execFileAsync("bun", ["install"], {
|
|
300
|
+
cwd: plan.targetDir,
|
|
301
|
+
maxBuffer: 10 * 1024 * 1024
|
|
302
|
+
});
|
|
303
|
+
} catch (error) {
|
|
304
|
+
throw new CliError("E_DEP_INSTALL_FAILED", "Failed to install dependencies with bun.", error && typeof error === "object" ? {
|
|
305
|
+
stdout: "stdout" in error ? String(error.stdout ?? "") : void 0,
|
|
306
|
+
stderr: "stderr" in error ? String(error.stderr ?? "") : void 0
|
|
307
|
+
} : void 0);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
if (json) {
|
|
311
|
+
await install();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
await spinner({
|
|
315
|
+
start: "Installing dependencies with bun",
|
|
316
|
+
end: "Dependencies installed",
|
|
317
|
+
while: install
|
|
318
|
+
});
|
|
319
|
+
}
|
|
294
320
|
async function performCreateTemplate(plan, howoneContext) {
|
|
295
321
|
const templateDir = getTemplateDir(plan.template);
|
|
296
322
|
if (plan.force && await pathExists(plan.targetDir)) await emptyDir(plan.targetDir);
|
package/package.json
CHANGED
package/templates/vite/AGENTS.md
CHANGED
|
@@ -1,53 +1,45 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This is a standard HowOne Vite app.
|
|
4
4
|
|
|
5
|
-
Read this file once when entering the project.
|
|
6
|
-
Follow it during implementation.
|
|
7
|
-
Do not repeatedly reread it unless it changes or the current task requires checking project rules again.
|
|
5
|
+
Read this file once when entering the project, follow it during implementation, and do not reread it unless it changes or the current task genuinely requires checking project rules again.
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## Project Defaults
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
- Package manager: `bun`
|
|
10
|
+
- Common commands: `bun run dev`, `bun run typecheck`, `bun run build`
|
|
11
|
+
- The scaffold normally installs dependencies during `howone init app`. If `node_modules` is missing, run `bun install` before validation instead of treating missing binaries as code failures.
|
|
12
|
+
- Default stack: React, Vite, TypeScript, Tailwind CSS, shadcn/ui-style components, `@howone/sdk`
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Source of Truth
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
- trusted libraries and framework assumptions
|
|
18
|
-
- context-loading rules
|
|
19
|
-
- validation rules
|
|
20
|
-
- project-specific constraints
|
|
16
|
+
Use project-local sources in this order:
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
1. Synced HowOne manifests under `.howone/`
|
|
19
|
+
2. Generated SDK bindings such as `src/lib/sdk.ts`
|
|
20
|
+
3. The smallest directly relevant app files
|
|
21
|
+
4. Package/config metadata
|
|
22
|
+
5. Dependency source only when a concrete mismatch or missing detail remains
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Do not guess generated entity names, AI action names, schemas, workflow IDs, or auth behavior when a synced manifest exists.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
- current phase: explore, implement, validate, fix, or done
|
|
28
|
-
- files already read
|
|
29
|
-
- files changed
|
|
30
|
-
- last validation command and result
|
|
31
|
-
- known blockers or open questions
|
|
26
|
+
## Context Discipline
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Do not reread this file unless:
|
|
36
|
-
|
|
37
|
-
- this file changed
|
|
38
|
-
- the project policy summary is unavailable
|
|
39
|
-
- the task enters a nested project with its own `AGENTS.md`
|
|
40
|
-
- validation errors suggest a project rule was missed
|
|
28
|
+
Start with the smallest useful context:
|
|
41
29
|
|
|
42
|
-
|
|
30
|
+
1. Read the smallest file that directly controls the requested behavior.
|
|
31
|
+
2. Prefer manifests, config, and public library APIs before local library internals.
|
|
32
|
+
3. Expand only when implementation, validation, or a concrete ambiguity requires it.
|
|
43
33
|
|
|
44
|
-
For
|
|
34
|
+
For ordinary page or feature work:
|
|
45
35
|
|
|
46
|
-
|
|
36
|
+
- Start with the relevant route, page, feature component, or entry file.
|
|
37
|
+
- Read additional local files only when they directly control the behavior being changed or resolve a specific uncertainty.
|
|
38
|
+
- If a manifest, config file, or validation error answers the question, prefer that over widening the file search.
|
|
47
39
|
|
|
48
|
-
|
|
40
|
+
## Trusted Libraries
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
Treat common public libraries as known dependencies during ordinary feature work:
|
|
51
43
|
|
|
52
44
|
- React
|
|
53
45
|
- Vite
|
|
@@ -59,39 +51,38 @@ Examples of trusted public libraries:
|
|
|
59
51
|
- clsx
|
|
60
52
|
- class-variance-authority
|
|
61
53
|
|
|
62
|
-
|
|
54
|
+
Do not inspect `src/components/ui/*` or other library-style source files just to rediscover standard APIs.
|
|
63
55
|
|
|
64
|
-
|
|
65
|
-
2. Read `package.json`, `components.json`, `tsconfig.json`, or alias config only when needed.
|
|
66
|
-
3. Implement the feature.
|
|
67
|
-
4. Run build/typecheck.
|
|
68
|
-
5. Inspect the smallest relevant local file only if validation fails or the API is genuinely unclear.
|
|
56
|
+
Using or importing a standard UI primitive is not by itself a reason to read its local source. For ordinary feature work, use the public component name and existing import path first.
|
|
69
57
|
|
|
70
|
-
|
|
58
|
+
Read local component or library-style source only when:
|
|
71
59
|
|
|
72
|
-
-
|
|
73
|
-
- imports cannot be resolved from
|
|
74
|
-
- the
|
|
75
|
-
- the task
|
|
76
|
-
- the project has custom wrappers,
|
|
60
|
+
- validation fails
|
|
61
|
+
- imports cannot be resolved from package/config metadata
|
|
62
|
+
- the API is genuinely unclear
|
|
63
|
+
- the task edits that component
|
|
64
|
+
- the project has custom wrappers, variants, or unusual exports
|
|
77
65
|
- the user explicitly asks to follow local component conventions
|
|
78
66
|
|
|
79
67
|
Prefer failure-driven inspection over speculative context loading.
|
|
80
68
|
|
|
81
|
-
##
|
|
82
|
-
|
|
83
|
-
Start with the smallest useful context:
|
|
69
|
+
## HowOne Runtime and Auth
|
|
84
70
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
71
|
+
- Use synced HowOne manifests plus `src/lib/sdk.ts` as the source of truth for generated entity and AI bindings.
|
|
72
|
+
- For SDK work, use the `howone-sdk` skill before relying on package internals.
|
|
73
|
+
- Choose auth posture from the schema access contract, not from guesswork:
|
|
74
|
+
- authenticated/private app data uses `howone.entities.*`; the backend derives ownership from the JWT
|
|
75
|
+
- public pages use `howone.public.entities.*` only when the manifest explicitly allows public access
|
|
76
|
+
- For private authenticated features, use the app-level HowOne auth flow instead of inventing unauthenticated fallback data paths.
|
|
77
|
+
- Do not pass owner fields such as `created_by_id`, `created_by_user_id`, `ownerId`, or `puid` into authenticated entity queries or writes.
|
|
89
78
|
|
|
90
|
-
|
|
79
|
+
## Validation
|
|
91
80
|
|
|
92
|
-
|
|
81
|
+
After meaningful code changes:
|
|
93
82
|
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
1. If dependencies are unavailable, run `bun install` first.
|
|
84
|
+
2. Run the narrowest relevant validation, usually `bun run typecheck`.
|
|
85
|
+
3. Run `bun run build` when the change affects app wiring, SDK integration, routes, or production bundling.
|
|
86
|
+
4. If validation fails, inspect the smallest failing surface before widening context.
|
|
96
87
|
|
|
97
|
-
|
|
88
|
+
Work is complete when the requested change is implemented, relevant validation has been run, and any remaining blocker is reported clearly.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@base-ui/react": "^1.4.1",
|
|
16
16
|
"@fontsource-variable/inter": "^5.2.8",
|
|
17
|
-
"@howone/sdk": "2.0.0-beta.
|
|
17
|
+
"@howone/sdk": "2.0.0-beta.16",
|
|
18
18
|
"@tailwindcss/vite": "^4.2.1",
|
|
19
19
|
"class-variance-authority": "^0.7.1",
|
|
20
20
|
"clsx": "^2.1.1",
|