@akanjs/cli 3.0.0-alpha.5 → 3.0.0-alpha.7
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/.build-stamp +1 -1
- package/{agent.command-b0fcx3r2.js → agent.command-pggr92jj.js} +6 -6
- package/{application.command-cgmy00gd.js → application.command-692yap1d.js} +4 -4
- package/{applicationBuildRunner-n1svrwgt.js → applicationBuildRunner-ha3y8ew8.js} +1 -1
- package/buildBatch.proc.js +2 -2
- package/{capacitorApp-yyw35vg4.js → capacitorApp-p0z5yab2.js} +4 -2
- package/{cloud.command-1m7hfdpk.js → cloud.command-wqfsyzv2.js} +7 -7
- package/{context.command-b5heat2a.js → context.command-9bxtdn0w.js} +13 -13
- package/{guideline.command-9ew6aqhm.js → guideline.command-nfqahxex.js} +3 -3
- package/incrementalBuilder.proc.js +1 -1
- package/{index-m4kpmmtj.js → index-2c3e2xh8.js} +1 -1
- package/{index-hrwzz2wf.js → index-4hek879p.js} +1 -1
- package/{index-nx1vbtsc.js → index-5dw57f0d.js} +5 -5
- package/{index-c94nq3c1.js → index-5pmx7bkg.js} +3 -3
- package/{index-jkynkyfk.js → index-6rhabeev.js} +1 -1
- package/{index-qp089jp0.js → index-7myvn0f0.js} +1 -1
- package/{index-exhpp31y.js → index-a1e0j63x.js} +2 -2
- package/{index-meh7mmz9.js → index-azv0xjb5.js} +2 -2
- package/{index-pfrt7qwh.js → index-bz2sfzzt.js} +4 -4
- package/{index-nfxq39kj.js → index-gex7c8kd.js} +4 -4
- package/{index-wrrb8rxk.js → index-gmy45vz2.js} +3 -3
- package/{index-mn96y1nk.js → index-js368gk9.js} +5 -5
- package/{index-jn9vfpwz.js → index-mssqn2sq.js} +2 -2
- package/{index-p6txr1ss.js → index-p3f4q532.js} +3 -3
- package/{index-0fj4yg7k.js → index-qb61h0k7.js} +2 -2
- package/{index-47qxw1tz.js → index-vg0sj9nc.js} +1 -1
- package/{index-60a3jfcz.js → index-vtj3zps1.js} +5 -5
- package/{index-p69fcwe1.js → index-w6wbb612.js} +11 -11
- package/{index-mterpj70.js → index-xhgtkekh.js} +86 -17
- package/{index-6npsfpxr.js → index-ztpw544k.js} +3 -3
- package/index.js +18 -18
- package/{library.command-aa1g8nsa.js → library.command-md9715jz.js} +3 -3
- package/{localRegistry.command-kshva1ck.js → localRegistry.command-exkbamyj.js} +6 -6
- package/{module.command-b1zzgqde.js → module.command-w5aaddxk.js} +6 -6
- package/{package.command-9qv6vr9s.js → package.command-yfkrcy0z.js} +3 -3
- package/package.json +2 -2
- package/{page.command-k16pw244.js → page.command-echbavp4.js} +3 -3
- package/{primitive.command-s60dn1ae.js → primitive.command-9fbhspw2.js} +7 -7
- package/{quality.command-p3vaze52.js → quality.command-3pnt9yep.js} +4 -17
- package/{repair.command-mfv749ha.js → repair.command-carj4vax.js} +5 -5
- package/{routeSourceValidator-cncd92fv.js → routeSourceValidator-e4jmbfcx.js} +2 -38
- package/{scalar.command-hs3nwzv1.js → scalar.command-51ryzypc.js} +5 -5
- package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +3 -2
- package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +1 -0
- package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +41 -0
- package/templates/workspaceRoot/AGENTS.md.template +12 -7
- package/templates/workspaceRoot/biome.json.template +25 -1
- package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +4 -1
- package/{workflow.command-z0e0fk0z.js → workflow.command-91wmvm8k.js} +10 -10
- package/{workspace.command-3q1d6kk4.js → workspace.command-wa10mfd9.js} +19 -19
|
@@ -56,3 +56,44 @@ alwaysApply: false
|
|
|
56
56
|
- Declare an image/file field as a relation to `File`: `image: field(File).optional()` for one, `images: field([File])` for many (see `libs/shared/lib/user/user.constant.ts`, `libs/shared/lib/banner/banner.constant.ts`).
|
|
57
57
|
- The store then auto-generates an `upload<Field>On<Model>(fileList)` action that calls the framework upload mutation and polls file status until it leaves `"uploading"` (`pkgs/akanjs/store/action.ts`).
|
|
58
58
|
- Storage is wired through the `StorageAdaptor` DI role (default `BlobStorage`, `pkgs/akanjs/service/predefinedAdaptor/storage.adaptor.ts`); the reference implementation is the `file` lib (`libs/shared/lib/file/*`). Do not hand-roll data-URL fallbacks.
|
|
59
|
+
|
|
60
|
+
### Cascade Remove — the `cascade` option
|
|
61
|
+
|
|
62
|
+
**The value names the direction, and getting it wrong is a data loss.** The two actions can sit on the same field
|
|
63
|
+
shape, so `cascade` never means "related" — it means one of exactly these:
|
|
64
|
+
|
|
65
|
+
- `removeRef` — *when I am removed, remove what this field points at.* Declared on the relation the owner holds:
|
|
66
|
+
`image: field(File, { cascade: "removeRef" })`, arrays included. Only a relation accepts it; a primitive, a bare
|
|
67
|
+
`ID`, and a scalar each fail the class build, because none of them names a document to remove.
|
|
68
|
+
- `removeWith` — *when what this field points at is removed, remove me.* Declared on the child's own reference to
|
|
69
|
+
its owner, so the owner never learns about its children and a lib model can be extended by an app's. Three forms:
|
|
70
|
+
a relation (`agentSession: field(AgentSession, { cascade: "removeWith" })`), an id with `ref`
|
|
71
|
+
(`field(ID, { ref: "agentSession", cascade: "removeWith" })`), or a polymorphic id with `refPath`
|
|
72
|
+
(`field(ID, { refPath: "parentType", cascade: "removeWith" })`). An array, a Map, `ref` together with `refPath`,
|
|
73
|
+
and a field naming no owner each fail the class build.
|
|
74
|
+
- **A `refPath` must name an `enumOf` field.** A free-form owner type is unknowable at build time, so every model's
|
|
75
|
+
removal would have to sweep the polymorphic table on the chance it is the owner. The enum names the candidates and
|
|
76
|
+
the reverse index reaches only them.
|
|
77
|
+
- **A cascade goes through the target's service, never its model** — unless it provably makes no difference. The
|
|
78
|
+
service path is what runs the target's `_postRemove`, which is where a module puts the side effect the removal has
|
|
79
|
+
to carry (`FileService._postRemove` deletes the stored blob there).
|
|
80
|
+
- **Bulk is decided at boot, per target model, for both directions.** When the target has no `remove` schema hook, no
|
|
81
|
+
`_pre`/`_postRemove` (its own or a lib's), no cascade of its own, and no children, one `removeManyByQuery` leaves
|
|
82
|
+
exactly the rows the loop would, so the framework takes it. Adding a `_postRemove` to that model silently flips it
|
|
83
|
+
back to one document at a time — the boot log (`info` summary, `verbose` per edge) is the only place that shows.
|
|
84
|
+
- **The plan is sealed after every service is live**, so a `listenPost("remove")` registered in `onInit` still counts
|
|
85
|
+
and a `removeRef` target the app never mounted fails the boot rather than the first removal. An unmounted
|
|
86
|
+
`removeWith` owner fails the boot too; an unmounted `refPath` candidate only warns, since that list spans optional
|
|
87
|
+
modules by design.
|
|
88
|
+
- **Nothing checks whether another document still references the same target.** `File` in particular is deduped by
|
|
89
|
+
`origin`, so two parents can share one row; declaring `removeRef` says the field owns its target exclusively, and
|
|
90
|
+
that judgement is the declaring model's to make.
|
|
91
|
+
- Removal is soft (`removedAt`) but the storage delete a `_postRemove` performs is not — a cascade is not
|
|
92
|
+
restorable, and reviving the owner does not revive what went with it.
|
|
93
|
+
- A `removeWith` declaration **auto-creates its index** (`{ removedAt, fk }`, or `{ removedAt, typeKey, fk }` when
|
|
94
|
+
polymorphic). Every non-base field lives in the `_doc` JSON column, so the lookup would otherwise scan the table
|
|
95
|
+
on every owner removal.
|
|
96
|
+
- **Query-level removes fire no hooks and therefore no cascade.** `removeManyByQuery` / `updateManyByQuery`, the generated `remove<Filter>` / `update<Filter>`, and the facade's `removeById` / `updateById` stamp
|
|
97
|
+
`removedAt` in one atomic UPDATE, so nothing downstream runs. Remove one document at a time when it cascades.
|
|
98
|
+
- Cascades are **idempotent**: `removedAt IS NULL` is ANDed into every query-level write, so a retry after a partial
|
|
99
|
+
failure re-stamps nothing. Cycles are cut by a visited set carried down the whole chain, with a depth cap of 16.
|
|
@@ -261,8 +261,10 @@ final fallback when no CLI command covers the change.
|
|
|
261
261
|
| Use JS `#private` in `*.constant.ts`, `*.document.ts`, `*.service.ts`, or `*.store.ts` | `no-js-private-class-method.grit` bans `#private` in exactly those four file suffixes. The rule is scoped by file path, not class shape — `#private` stays the house style under `srvkit/`, including `adapt()` classes. | `private _methodName()` in those four files; `#methodName()` in `srvkit/` |
|
|
262
262
|
| Use `console.log()` | Biome lint forbids `console.log`. Only `console.error`, `console.info`, `console.warn` are allowed. | Use one of the three allowed console methods, or `this.logger.*` / `new Logger("ClassName")` on the server |
|
|
263
263
|
| Write a `//!` marker in `ui/`, `webkit/`, `common/`, `page/**/*.tsx`, `*.constant.ts`, `*.store.ts`, or a module component file | `no-bang-comment-in-client.grit` bans it. Bun classifies `//!` and `/*!` as legal comments and keeps them through minification, so the note ships to every visitor. | `// FIXME:` in browser-reachable code; `//!` stays legal in server, `srvkit/`, and CLI files |
|
|
264
|
-
| `
|
|
265
|
-
|
|
|
264
|
+
| `return` a value from a store action | `no-return-in-store-action.grit` bans it. Every method of a `store(...)` class dispatches through `st.do.<action>()`, which is typed `void` / `Promise<void>`, so the value never reaches the caller. | `this.set({ ... })` with the result; a bare `return;` guard, a `return` inside a nested callback, a getter, and a `static` helper all stay legal |
|
|
265
|
+
| `throw new Error("...")` | `no-throw-raw-error.grit` bans raw errors outside tests, `*.constant.ts`, `common/`, and `apps/akan/env/`. Raw errors carry no dictionary key, so they cannot be localized or toasted. | `throw new Err("task.error.<key>")` plus an `[en, ko]` entry in the module dictionary's `.error({})` |
|
|
266
|
+
| Hand-order Tailwind classes, or reorder them to "fix" a diff | `useSortedClasses` is an error and also sorts the string arguments to `cn()`. Sorter output like `font-bold text-2xl` looks wrong but is correct. | Write classes in any order and let `akan lint` sort them |
|
|
267
|
+
| A colour outside the semantic vocabulary — `bg-red-500`, `bg-[#3b82f6]`, `btn-primary`, `text-base-content`, `style={{ color: "#fff" }}` | The theme closes the vocabulary, so these produce **no CSS at all** — the element renders unstyled, and without the lint rules there is no error and no warning either. Raw-palette, arbitrary-colour, daisyUI-legacy and inline-colour rules all catch this. | Semantic tokens: `bg-primary`, `text-foreground/70`, `border-border`. A genuinely fixed colour takes a `// biome-ignore lint/plugin: <reason>` |
|
|
266
268
|
| `import` a third-party package inside a page, a barrel, or a module file | `no-import-external-library.grit` covers `page/**`, all barrels, and every `*.{constant,dictionary,document,service,signal,store}.ts` and `*.{Template,Unit,Util,View,Zone}.tsx`. | Re-export the symbol from a one-line shim in `base/`, `webkit/`, or `ui/` first, then import that |
|
|
267
269
|
| Import server APIs (`fs`, `Bun`, `process.env`) in `ui/`, `webkit/`, or `common/` | Server-only imports in client code cause build failures. | Keep server dependencies in `lib/`, `srvkit/`, or `private/` only |
|
|
268
270
|
| Skip running `akan sync` after deleting a file | Deleted files remain referenced in barrel exports, causing import errors everywhere. | Run `akan sync <name>` after every file add, remove, or rename |
|
|
@@ -421,11 +423,14 @@ is convention that keeps hand-written code reading like generated code.
|
|
|
421
423
|
`.Template.tsx` files contain zero `useState`: forms are store-driven with `Field.*`, `value={taskForm.x}`, and
|
|
422
424
|
`onChange={st.do.setXOnTask}` passed by reference.
|
|
423
425
|
- Read with `st.use.*` and write with `st.do.*`. Client components do not call `fetch.*`.
|
|
424
|
-
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
-
|
|
428
|
-
|
|
426
|
+
- Reach for a recipe before writing a look by hand: `buttonRecipe`, `badgeRecipe` and `inputRecipe` from
|
|
427
|
+
`akanjs/ui` carry the button, badge and field surfaces. Call them as `buttonRecipe(variants?, className?)` —
|
|
428
|
+
the second argument merges internally and takes an array, so never wrap it in `cn()`.
|
|
429
|
+
- Static class strings stay plain strings. Reach for `cn` only for a conditional or to merge an incoming
|
|
430
|
+
`className`, and merge the caller last: `cn("base", conditional, className)`. `cn` comes from `akanjs/client`
|
|
431
|
+
and is the only class-combining function — no `clsx`, no raw `twMerge`.
|
|
432
|
+
- Use semantic tokens with opacity modifiers (`text-foreground/60`, `bg-background/70`, `border-border`). Never
|
|
433
|
+
`dark:` — theming is the token block in `page/*/styles.css`, where each token has a `-foreground` pair.
|
|
429
434
|
- Hoist enum→class lookups to a module-scope `as const` map typed `{ [key in cnst.TaskStatus["value"]]: string }`,
|
|
430
435
|
not `Record<...>`.
|
|
431
436
|
|
|
@@ -143,7 +143,8 @@
|
|
|
143
143
|
"!**/*.spec.ts",
|
|
144
144
|
"!**/*.spec.tsx",
|
|
145
145
|
"!**/*.constant.ts",
|
|
146
|
-
"!**/common/**"
|
|
146
|
+
"!**/common/**",
|
|
147
|
+
"!apps/akan/env/**"
|
|
147
148
|
],
|
|
148
149
|
"plugins": ["./node_modules/@akanjs/devkit/lint/no-throw-raw-error.grit"]
|
|
149
150
|
},
|
|
@@ -162,6 +163,10 @@
|
|
|
162
163
|
"includes": ["**/*.constant.ts", "**/*.document.ts", "**/*.service.ts", "**/*.store.ts"],
|
|
163
164
|
"plugins": ["./node_modules/@akanjs/devkit/lint/no-js-private-class-method.grit"]
|
|
164
165
|
},
|
|
166
|
+
{
|
|
167
|
+
"includes": ["**/*.store.ts"],
|
|
168
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-return-in-store-action.grit"]
|
|
169
|
+
},
|
|
165
170
|
{
|
|
166
171
|
"includes": ["**/*.signal.ts"],
|
|
167
172
|
"plugins": ["./node_modules/@akanjs/devkit/lint/no-redeclare-predefined-endpoint.grit"]
|
|
@@ -232,6 +237,25 @@
|
|
|
232
237
|
"**/*.Zone.tsx"
|
|
233
238
|
],
|
|
234
239
|
"plugins": ["./node_modules/@akanjs/devkit/lint/no-import-external-library.grit"]
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"includes": [
|
|
243
|
+
"apps/**/*.ts",
|
|
244
|
+
"apps/**/*.tsx",
|
|
245
|
+
"libs/**/*.ts",
|
|
246
|
+
"libs/**/*.tsx",
|
|
247
|
+
"!**/*.test.ts",
|
|
248
|
+
"!**/*.test.tsx",
|
|
249
|
+
"!**/*.spec.ts",
|
|
250
|
+
"!**/*.spec.tsx"
|
|
251
|
+
],
|
|
252
|
+
"plugins": [
|
|
253
|
+
"./node_modules/@akanjs/devkit/lint/no-raw-palette-class.grit",
|
|
254
|
+
"./node_modules/@akanjs/devkit/lint/no-arbitrary-color.grit",
|
|
255
|
+
"./node_modules/@akanjs/devkit/lint/no-daisyui-legacy-class.grit",
|
|
256
|
+
"./node_modules/@akanjs/devkit/lint/no-inline-color.grit",
|
|
257
|
+
"./node_modules/@akanjs/devkit/lint/no-interpolated-arbitrary-class.grit"
|
|
258
|
+
]
|
|
235
259
|
}
|
|
236
260
|
]
|
|
237
261
|
}
|
|
@@ -49,8 +49,11 @@ See `docs/GENERATED.md` for the generated file list.
|
|
|
49
49
|
|
|
50
50
|
`AGENTS.md` holds the full style guide. The rules agents break most often:
|
|
51
51
|
|
|
52
|
-
- **Never hand-order Tailwind classes** — the linter sorts them, including inside `
|
|
52
|
+
- **Never hand-order Tailwind classes** — the linter sorts them, including inside `cn()`, and its output looks
|
|
53
53
|
unnatural on purpose.
|
|
54
|
+
- **Never use a colour outside the semantic vocabulary** — `bg-red-500`, `bg-[#3b82f6]` and `text-base-content`
|
|
55
|
+
compile to no CSS at all, so the element renders unstyled with no error. Use `bg-primary`, `text-foreground/70`
|
|
56
|
+
and the other tokens defined in `page/*/styles.css`.
|
|
54
57
|
- **Never `throw new Error`** — throw `new Err("<module>.error.<key>")` with an `[en, ko]` entry in the module
|
|
55
58
|
dictionary. `common/` cannot import `Err`, so keep throwing code out of it.
|
|
56
59
|
- **Never import a third-party package** from a page, a barrel, or a module file. Re-export it through a one-line
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
WorkflowRunner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-5pmx7bkg.js";
|
|
5
5
|
import {
|
|
6
6
|
PrimitiveScript
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-bz2sfzzt.js";
|
|
8
8
|
import {
|
|
9
9
|
ModuleScript
|
|
10
|
-
} from "./index-
|
|
11
|
-
import"./index-
|
|
10
|
+
} from "./index-vtj3zps1.js";
|
|
11
|
+
import"./index-4hek879p.js";
|
|
12
12
|
import {
|
|
13
13
|
ScalarScript
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-gmy45vz2.js";
|
|
15
15
|
import"./index-ss469dec.js";
|
|
16
16
|
import"./index-0cj2zxbm.js";
|
|
17
|
-
import"./index-
|
|
17
|
+
import"./index-mssqn2sq.js";
|
|
18
18
|
import {
|
|
19
19
|
createWorkflowStepRegistry
|
|
20
|
-
} from "./index-
|
|
21
|
-
import"./index-
|
|
20
|
+
} from "./index-2c3e2xh8.js";
|
|
21
|
+
import"./index-7myvn0f0.js";
|
|
22
22
|
import {
|
|
23
23
|
Workspace,
|
|
24
24
|
command,
|
|
25
25
|
script
|
|
26
|
-
} from "./index-
|
|
27
|
-
import"./index-
|
|
26
|
+
} from "./index-6rhabeev.js";
|
|
27
|
+
import"./index-vg0sj9nc.js";
|
|
28
28
|
import"./index-mxvakhsm.js";
|
|
29
29
|
import"./index-xys926f2.js";
|
|
30
30
|
import"./index-67546d0j.js";
|
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ContextScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-
|
|
4
|
+
} from "./index-w6wbb612.js";
|
|
5
|
+
import"./index-ztpw544k.js";
|
|
6
|
+
import"./index-5pmx7bkg.js";
|
|
7
|
+
import"./index-bz2sfzzt.js";
|
|
8
|
+
import"./index-vtj3zps1.js";
|
|
9
|
+
import"./index-4hek879p.js";
|
|
10
10
|
import {
|
|
11
11
|
CloudScript
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-js368gk9.js";
|
|
13
13
|
import {
|
|
14
14
|
getLatestPackageVersion,
|
|
15
15
|
getNpmRegistryUrl
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-p3f4q532.js";
|
|
17
17
|
import {
|
|
18
18
|
PackageScript
|
|
19
|
-
} from "./index-
|
|
20
|
-
import"./index-
|
|
19
|
+
} from "./index-azv0xjb5.js";
|
|
20
|
+
import"./index-gmy45vz2.js";
|
|
21
21
|
import"./index-ss469dec.js";
|
|
22
|
-
import"./index-
|
|
22
|
+
import"./index-xhgtkekh.js";
|
|
23
23
|
import {
|
|
24
24
|
GlobalConfig
|
|
25
25
|
} from "./index-0cj2zxbm.js";
|
|
26
26
|
import {
|
|
27
27
|
AgentScript
|
|
28
|
-
} from "./index-
|
|
29
|
-
import"./index-
|
|
30
|
-
import"./index-
|
|
31
|
-
import"./index-
|
|
28
|
+
} from "./index-gex7c8kd.js";
|
|
29
|
+
import"./index-mssqn2sq.js";
|
|
30
|
+
import"./index-2c3e2xh8.js";
|
|
31
|
+
import"./index-7myvn0f0.js";
|
|
32
32
|
import {
|
|
33
33
|
ApplicationScript
|
|
34
|
-
} from "./index-
|
|
34
|
+
} from "./index-5dw57f0d.js";
|
|
35
35
|
import"./index-76rn3g2c.js";
|
|
36
36
|
import {
|
|
37
37
|
LibraryScript
|
|
38
|
-
} from "./index-
|
|
38
|
+
} from "./index-a1e0j63x.js";
|
|
39
39
|
import {
|
|
40
40
|
Exec,
|
|
41
41
|
Workspace,
|
|
42
42
|
command,
|
|
43
43
|
runner,
|
|
44
44
|
script
|
|
45
|
-
} from "./index-
|
|
45
|
+
} from "./index-6rhabeev.js";
|
|
46
46
|
import"./index-fgc8r6dj.js";
|
|
47
47
|
import {
|
|
48
48
|
ThemeValidator,
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
collectScopeRecipeSources,
|
|
60
60
|
extractAgentBlock,
|
|
61
61
|
renderScopeAgentBlock
|
|
62
|
-
} from "./index-
|
|
62
|
+
} from "./index-vg0sj9nc.js";
|
|
63
63
|
import"./index-mxvakhsm.js";
|
|
64
64
|
import {
|
|
65
65
|
collectRecipeSources,
|