@zerotal/arch 1.7.0 → 1.7.3
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/CHANGELOG.md +57 -0
- package/docs/about.md +4 -4
- package/docs/broadcasting/channels.md +1 -1
- package/docs/broadcasting/client.md +17 -4
- package/docs/broadcasting/events.md +2 -2
- package/docs/broadcasting/index.md +1 -1
- package/docs/changelog.md +106 -4
- package/docs/commands.md +21 -12
- package/docs/contributing.md +2 -2
- package/docs/errors.md +22 -0
- package/docs/flow/components.md +27 -8
- package/docs/flow/decorators.md +32 -16
- package/docs/flow/events.md +53 -19
- package/docs/flow/index.md +18 -7
- package/docs/flow/layouts.md +16 -0
- package/docs/flow/lifecycle.md +31 -16
- package/docs/flow/models.md +284 -0
- package/docs/flow/performance.md +27 -1
- package/docs/flow/references.md +16 -1
- package/docs/flow/routing.md +14 -2
- package/docs/flow/testing.md +32 -0
- package/docs/getting-started.md +26 -1
- package/docs/i18n.md +247 -144
- package/docs/notifications.md +1 -1
- package/docs/queue.md +11 -3
- package/docs/routing.md +89 -7
- package/docs/seeding.md +7 -0
- package/docs/support-policy.md +13 -5
- package/docs/upgrade.md +2 -0
- package/package.json +3 -3
- package/src/install/guidelines.ts +5 -1
- package/src/install/markers.ts +11 -2
- package/src/install/mcpConfig.ts +14 -2
- package/src/probe/topics.ts +19 -4
- package/src/tools/apiSurface.ts +115 -20
- package/src/tools/baselines.ts +33 -4
- package/src/tools/logs.ts +77 -7
- package/src/tools/searchDocs.ts +196 -29
package/docs/flow/references.md
CHANGED
|
@@ -87,6 +87,7 @@ Visual loading indicators (`showOnLoading`, `hideOnLoading`, `loadingClass`) wai
|
|
|
87
87
|
| ----------------- | --------------------------------------------------------- | ----------------------------------- |
|
|
88
88
|
| `navigate` | SPA navigation to `href`, layout stays mounted | `flow:navigate` |
|
|
89
89
|
| `navigate hover` | Prefetch page on hover (~60ms debounce) | `flow:navigate flow:navigate.hover` |
|
|
90
|
+
| `navigate down` | Prefetch page on pointer-down (no dwell; dense lists) | `flow:navigate flow:navigate.down` |
|
|
90
91
|
| `current={false}` | Disable automatic `data-current` attribute | — |
|
|
91
92
|
| `exact` | `data-current` only on an exact URL match (not sub-pages) | `flow:current.exact` |
|
|
92
93
|
|
|
@@ -177,12 +178,26 @@ override async render() {
|
|
|
177
178
|
|
|
178
179
|
> A dynamic `sortItem={String(it.id)}` inside a `.map()` renders through the standard runtime (not the AOT fast path) — the drag behaviour is identical either way.
|
|
179
180
|
|
|
181
|
+
> **The payload does not say which container took the drop.** The client reads `flow:sort` off the
|
|
182
|
+
> container a child was dropped **into** and calls it `(key, index)` — so the destination is
|
|
183
|
+
> encoded in _which method runs_, and nowhere else. For a single sortable list that is invisible.
|
|
184
|
+
> For dragging **between** containers under one `sortGroup` it means one action per container:
|
|
185
|
+
>
|
|
186
|
+
> ```tsx
|
|
187
|
+
> <ul onSort={this.dropInTodo} sortGroup="tasks">…</ul>
|
|
188
|
+
> <ul onSort={this.dropInDone} sortGroup="tasks">…</ul>
|
|
189
|
+
> ```
|
|
190
|
+
>
|
|
191
|
+
> An arrow (`onSort={(k, i) => this.move("todo", k, i)}`) cannot stand in, because the attribute's
|
|
192
|
+
> value is used as a method _name_ rather than evaluated. `onSort` accepts the name as a string,
|
|
193
|
+
> so the handlers can come from a lookup table keyed by column, but they must be declared members.
|
|
194
|
+
|
|
180
195
|
### DOM utilities
|
|
181
196
|
|
|
182
197
|
| You write | Behaviour | Compiles to |
|
|
183
198
|
| ----------------- | ------------------------------------------------------------ | --------------- |
|
|
184
199
|
| `teleport="body"` | Move the element to a CSS selector target (modals, tooltips) | `flow:teleport` |
|
|
185
|
-
| `ref="name"` | Name this element as `$refs.name` for
|
|
200
|
+
| `ref="name"` | Name this element as `$refs.name` for ``this.$`…` `` scripts | `x-ref` |
|
|
186
201
|
|
|
187
202
|
### Alpine plugins
|
|
188
203
|
|
package/docs/flow/routing.md
CHANGED
|
@@ -426,15 +426,27 @@ export class DashboardPage extends Component {
|
|
|
426
426
|
}
|
|
427
427
|
```
|
|
428
428
|
|
|
429
|
-
|
|
429
|
+
### The page title
|
|
430
|
+
|
|
431
|
+
`static title` takes a string, or a function of the component:
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
static title = "Posts";
|
|
435
|
+
static title = (c: PostPage) => `${c.post?.title ?? "Loading"} — My App`;
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
The function form is resolved on the server for every render and every patch, so a title
|
|
439
|
+
that depends on state follows it without an action doing anything:
|
|
430
440
|
|
|
431
441
|
```typescript
|
|
432
442
|
@expose async loadPost(slug: string): Promise<void> {
|
|
433
443
|
this.post = await Post.where("slug", slug).firstOrFail();
|
|
434
|
-
|
|
444
|
+
// the title updates with it — nothing else to call
|
|
435
445
|
}
|
|
436
446
|
```
|
|
437
447
|
|
|
448
|
+
Only the resolved string is sent to the browser; the function stays on the server.
|
|
449
|
+
|
|
438
450
|
For per-render `<head>` content (meta tags, OG tags), use `<Head>` inside `render()`:
|
|
439
451
|
|
|
440
452
|
```tsx
|
package/docs/flow/testing.md
CHANGED
|
@@ -177,6 +177,38 @@ expect(page.user?.email).toBe("alice@example.com");
|
|
|
177
177
|
expect(page.totalRevenue).toBe(450.0);
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
+
## No request scope
|
|
181
|
+
|
|
182
|
+
`FlowTest` drives the server-side pipeline but does **not** open a request context. There is no
|
|
183
|
+
`RequestContext.run` inside it, so anything reaching for the request throws rather than
|
|
184
|
+
returning empty:
|
|
185
|
+
|
|
186
|
+
- `Auth.user()` → `E_UNAUTHORIZED`
|
|
187
|
+
- `Auth.attempt()` / `Auth.login()` → `E_CONTEXT_OUTSIDE_REQUEST`
|
|
188
|
+
- request-scoped pagination, and any facade that reads `RequestContext`
|
|
189
|
+
|
|
190
|
+
That covers most actions on any page behind a sign-in, so open the scope yourself. `HttpContext.fake()`
|
|
191
|
+
rather than an object literal cast to the type — it carries a real `Request`, which matters as soon
|
|
192
|
+
as anything downstream reads a header (an audited model records the actor's IP, for one):
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { RequestContext, HttpContext } from "@zerotal/core";
|
|
196
|
+
|
|
197
|
+
function asUser<T>(user: User | null, fn: () => Promise<T>): Promise<T> {
|
|
198
|
+
const ctx = HttpContext.fake("http://localhost/");
|
|
199
|
+
if (user) ctx.user = user;
|
|
200
|
+
return RequestContext.run(ctx, fn);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
await asUser(alice, async () => {
|
|
204
|
+
const t = await FlowTest.mount(IssuePage, { issue });
|
|
205
|
+
await t.call("postComment");
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`app.actingAs()` does not help here: it encodes a session cookie for `app.get()`, and `FlowTest`
|
|
210
|
+
never makes a request to send it on.
|
|
211
|
+
|
|
180
212
|
## Testing with a database
|
|
181
213
|
|
|
182
214
|
`FlowTest` does not set up or tear down a database — use your test suite's standard database helpers. With Bun, wrap tests in a transaction that rolls back after each test for full isolation:
|
package/docs/getting-started.md
CHANGED
|
@@ -11,7 +11,7 @@ provider.
|
|
|
11
11
|
|
|
12
12
|
## Requirements
|
|
13
13
|
|
|
14
|
-
- **Bun** ≥ 1.
|
|
14
|
+
- **Bun** ≥ 1.3.14 — [install](https://bun.sh/docs/installation)
|
|
15
15
|
- A PostgreSQL, MySQL, or SQLite database (SQLite requires nothing extra)
|
|
16
16
|
|
|
17
17
|
## Create a new project
|
|
@@ -36,6 +36,31 @@ It writes a fresh `APP_KEY` into the generated `.env.example` for you (no manual
|
|
|
36
36
|
generation needed). For Postgres/MySQL it reminds you to set `DATABASE_URL`
|
|
37
37
|
before migrating.
|
|
38
38
|
|
|
39
|
+
### Without a terminal — CI, scripts, agents
|
|
40
|
+
|
|
41
|
+
Every prompt has a flag, and the scaffolder never asks a question when there is
|
|
42
|
+
no TTY to answer it:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bunx create-zerotal my-app --template=api --db=postgres --no-install
|
|
46
|
+
bunx create-zerotal my-app --yes # take the defaults for anything unset
|
|
47
|
+
bunx create-zerotal --help
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| Flag | |
|
|
51
|
+
| ------------------------- | -------------------------------------------------- |
|
|
52
|
+
| `-t`, `--template <name>` | `api`, `admin`, `flow`, `react`, `vue`, `minimal` |
|
|
53
|
+
| `--db <name>` | `sqlite`, `postgres`, `mysql` — API template only |
|
|
54
|
+
| `-y`, `--yes` | Take defaults for anything not given; never prompt |
|
|
55
|
+
| `--no-install` | Skip `bun install` |
|
|
56
|
+
| `-h`, `--help` | Usage |
|
|
57
|
+
| `-v`, `--version` | The scaffolder's own version |
|
|
58
|
+
|
|
59
|
+
An answer that is missing and cannot be asked for is an error naming the flag
|
|
60
|
+
that would supply it, and the exit code is non-zero — so a pipeline fails where
|
|
61
|
+
it used to wait. A failed `bun install` also exits non-zero when there is no
|
|
62
|
+
terminal: a half-built project that reports success is worse than one that stops.
|
|
63
|
+
|
|
39
64
|
### Which template should I use?
|
|
40
65
|
|
|
41
66
|
- **API** — JSON REST API with core, [ORM](/docs/orm), [auth](/docs/authentication),
|