@owlmeans/create-app 0.1.18-rc.17 → 0.1.18-rc.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/README.md +3 -2
- package/package.json +2 -2
- package/template/README.bare.md +2 -2
- package/template/README.md +4 -67
- package/template/_agents/skills/getting-started/SKILL.md +26 -133
- package/template/_agents/skills/reuse-code/SKILL.md +1 -1
- package/template/sources/api/package.json +2 -2
- package/template/sources/api/src/entrypoints.bare.ts +3 -4
- package/template/sources/api/src/entrypoints.ts +11 -6
- package/template/sources/common/package.json +5 -5
- package/template/sources/common/src/entrypoints.bare.ts +13 -7
- package/template/sources/common/src/entrypoints.ts +8 -4
- package/template/sources/web/package.json +10 -10
- package/template/sources/web/src/entrypoints.bare.ts +10 -10
- package/template/sources/web/src/entrypoints.ts +10 -10
- package/template/sources/web/src/index.css +1 -1
package/README.md
CHANGED
|
@@ -65,8 +65,9 @@ is present even with `--no-install`.
|
|
|
65
65
|
`--bare` keeps the three workspaces, the config/context/entrypoint wiring, the layout, the nav
|
|
66
66
|
skeleton and one Home screen, and drops every piece of example code — the `SessionItem` types and
|
|
67
67
|
schemas, the api's `app/session/**` handlers and its static resource, the About and Session screens.
|
|
68
|
-
`sources/common/src/entrypoints.ts` exports an
|
|
69
|
-
|
|
68
|
+
`sources/common/src/entrypoints.ts` exports an immutable `appEntrypoints` tree with an empty `api`
|
|
69
|
+
branch and the web routes. The API and web bind those branches locally, so the first feature adds a
|
|
70
|
+
declaration to the tree, then a handler and a screen binding.
|
|
70
71
|
|
|
71
72
|
What bare removes and what it swaps in is declared in `template/_bare.json`, next to the
|
|
72
73
|
`.bare.`-infixed variants it points at — not in the scaffolder's code.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/create-app",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.19",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Scaffold a fullstack OwlMeans Common app — common + api + web workspaces, shadcn UI navigation/layout, no auth, and a session-scoped in-memory resource, or --bare for the demo-free shell. Also usable programmatically via scaffold(). Deploys agent skills via @owlmeans/agent-skills by default.",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"template"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@owlmeans/agent-skills": "^0.1.18-rc.
|
|
33
|
+
"@owlmeans/agent-skills": "^0.1.18-rc.15"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@owlmeans/dep-config": "workspace:*",
|
package/template/README.bare.md
CHANGED
|
@@ -34,10 +34,10 @@ bun run dev
|
|
|
34
34
|
1. **`sources/common/src/entrypoints.ts`** — declare the route as an OwlMeans *entrypoint* and
|
|
35
35
|
give it an AJV filter. Both sides import this one declaration; neither re-declares the route.
|
|
36
36
|
2. **`sources/api`** — register a resource in `src/context.ts` (widening `Context` in
|
|
37
|
-
`src/types.ts`), then `
|
|
37
|
+
`src/types.ts`), then `bind()` the entrypoint with a handler in `src/entrypoints.ts`.
|
|
38
38
|
3. **`sources/web`** — add a screen under `src/screens`, hang it off a frontend route in
|
|
39
39
|
`src/entrypoints.ts`, list it in `src/nav.ts`, and call the backend with
|
|
40
|
-
`context.entrypoint(
|
|
40
|
+
`context.entrypoint(protocol).call({ params, body })`.
|
|
41
41
|
|
|
42
42
|
See the [OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md)
|
|
43
43
|
for a worked example of all three steps.
|
package/template/README.md
CHANGED
|
@@ -2,71 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
__APP_DESCRIPTION__
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
An OwlMeans application has shared protocol declarations in `sources/common`, server bindings in
|
|
6
|
+
`sources/api`, and browser bindings/screens in `sources/web`. Contracts, request schemas, guards
|
|
7
|
+
and gates are declared once in common; runtime packages bind them without changing the declaration.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Workspaces
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
sources/
|
|
14
|
-
├── common/ # shared entrypoints (routes), schemas and types — used by api AND web
|
|
15
|
-
├── api/ # @owlmeans/server-app backend; session items in @owlmeans/static-resource
|
|
16
|
-
└── web/ # @owlmeans/web-panel + shadcn UI: navigation, layout and screens
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Develop
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
bun install
|
|
23
|
-
bun run dev
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
- API: http://localhost:3000
|
|
27
|
-
- Web: http://localhost:3001
|
|
28
|
-
|
|
29
|
-
Open the **Session** page and add/remove items — they are stored per browser session
|
|
30
|
-
(a `sid` kept in `localStorage`) in an in-memory resource on the API. Restarting the API
|
|
31
|
-
clears them; opening a different browser/incognito window gets an isolated session.
|
|
32
|
-
|
|
33
|
-
> **Note:** The API runs over plain HTTP in dev (`cfg.security = { unsecure: true }` in
|
|
34
|
-
> `sources/common/src/config.ts`). If you edit `sources/common`, restart `bun run dev` to
|
|
35
|
-
> rebuild it before the API and web pick up the changes.
|
|
36
|
-
|
|
37
|
-
## How it fits together
|
|
38
|
-
|
|
39
|
-
1. **`sources/common`** declares the API routes as OwlMeans *entrypoints* (`session.list`,
|
|
40
|
-
`session.add`, `session.remove`) plus their AJV schemas and shared types.
|
|
41
|
-
2. **`sources/api`** registers a `@owlmeans/static-resource` in its context and `elevate()`s
|
|
42
|
-
each entrypoint with a handler that does CRUD against it, keyed by the session id.
|
|
43
|
-
3. **`sources/web`** `elevate()`s the same entrypoints to screen components and calls them with
|
|
44
|
-
`context.entrypoint(alias).call({ params, body })`.
|
|
45
|
-
|
|
46
|
-
See [OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md)
|
|
47
|
-
for a full walkthrough and the manual (non-scaffolded) version of this project.
|
|
48
|
-
|
|
49
|
-
## Agent guidance
|
|
50
|
-
|
|
51
|
-
Always-on project context lives in `AGENTS.md`, which every agent reads; `CLAUDE.md` is a thin
|
|
52
|
-
bridge that imports it. It carries the four mandatory sections a real OwlMeans monorepo uses —
|
|
53
|
-
**Git Workflow**, **Reporting**, **Memory**, **Self-Education** — plus a project-purpose
|
|
54
|
-
placeholder the agent fills in on its first session.
|
|
55
|
-
|
|
56
|
-
Project memory is a single shared graph store at `.agents/memory/` (index `MEMORY.md`), used by
|
|
57
|
-
every agent — never write memory anywhere else.
|
|
58
|
-
|
|
59
|
-
Reusable guidance is one skill per topic at `.agents/skills/<name>/SKILL.md` — the
|
|
60
|
-
[Agent Skills](https://agentskills.io) standard location, read natively by Copilot and Codex.
|
|
61
|
-
Claude Code reads them through the generated per-skill symlinks under `.claude/skills/`, which
|
|
62
|
-
`sh .agents/scripts/link-skills.sh` (re)creates; the committed `SessionStart` hook runs it each
|
|
63
|
-
session. Never author a file under `.claude/skills/`.
|
|
64
|
-
|
|
65
|
-
Files carrying an `AUTO-GENERATED` banner are managed by
|
|
66
|
-
[`@owlmeans/agent-skills`](https://www.npmjs.com/package/@owlmeans/agent-skills) — don't hand-edit
|
|
67
|
-
them; write your own guidance as separate, un-bannered files. Refresh after adding or upgrading
|
|
68
|
-
`@owlmeans/*` packages:
|
|
69
|
-
|
|
70
|
-
```sh
|
|
71
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.12
|
|
72
|
-
```
|
|
9
|
+
Use `bun run build` from the project root to build every workspace.
|
|
@@ -1,152 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: getting-started
|
|
3
|
-
description:
|
|
4
|
-
user-invocable: true
|
|
3
|
+
description: Start a protocol-first OwlMeans application with shared contracts, server entrypoints and browser entrypoints.
|
|
5
4
|
metadata:
|
|
6
5
|
scope: general
|
|
7
6
|
---
|
|
8
7
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
9
8
|
|
|
10
|
-
#
|
|
9
|
+
# Protocol-first application shape
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
sources/
|
|
16
|
-
├── common/ # shared entrypoints (routes), AJV schemas, types, config — the single source of truth
|
|
17
|
-
│ # entrypoints.ts
|
|
18
|
-
├── api/ # @owlmeans/server-app backend; handlers attached to the shared entrypoints
|
|
19
|
-
│ # context.ts, entrypoints.ts, app/<area>/*, index.ts
|
|
20
|
-
└── web/ # @owlmeans/web-panel + shadcn UI; screens attached to the same entrypoints
|
|
21
|
-
# context.ts, entrypoints.ts, nav.ts, layout/, screens/, render.tsx, index.tsx
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Three workspaces is the whole shape — a backend that needs its own long-running worker or a second
|
|
25
|
-
API adds a workspace beside them and shares the same `common`.
|
|
26
|
-
|
|
27
|
-
The full, runnable walkthrough (scaffolded **and** manual) lives in the
|
|
28
|
-
[OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md).
|
|
29
|
-
To generate this exact project, use [[scaffolding]] (`npm create @owlmeans/app`). This skill is the
|
|
30
|
-
mental model.
|
|
31
|
-
|
|
32
|
-
## The core idea: one contract, two sides
|
|
33
|
-
|
|
34
|
-
Declare each route once in `common` as an **entrypoint**, then `elevate()` it on each side:
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
// common/entrypoints.ts — declaration + validation, no implementation
|
|
38
|
-
export const sessionEntrypoints = [
|
|
39
|
-
entrypoint(route(session.base, '/session')),
|
|
40
|
-
entrypoint(route(session.list, '/:sid/items', { parent: session.base, method: RouteMethod.GET }),
|
|
41
|
-
filter(params<SessionParams>(SessionParamsSchema))),
|
|
42
|
-
entrypoint(route(session.add, '/:sid/items', { parent: session.base, method: RouteMethod.POST }),
|
|
43
|
-
filter(params<SessionParams>(SessionParamsSchema, body<AddItemPayload>(AddItemSchema)))),
|
|
44
|
-
]
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```ts
|
|
48
|
-
// api/entrypoints.ts — attach handlers
|
|
49
|
-
elevate(sessionEntrypoints, session.list, handlers.list)
|
|
50
|
-
export const appEntrypoints = [...entrypoints, ...sessionEntrypoints] // `entrypoints` = framework defaults
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
// web/entrypoints.ts — attach screen components, plus call-only elevation for backend routes
|
|
55
|
-
const entrypoints = [...baseEntrypoints, ...sessionEntrypoints] // `baseEntrypoints` from web-panel
|
|
56
|
-
elevate(entrypoints, session.list) // callable from the client
|
|
57
|
-
entrypoints.push(entrypoint(route(web.session, '/session', frontend({ parent: BASE })), handler(SessionScreen)))
|
|
58
|
-
export const appEntrypoints = entrypoints
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
A route declaration is plain data: its `path` is the SEGMENT it contributes under its `parent`, and
|
|
62
|
-
nothing ever rewrites it. `session.list` reads `/:sid/items` under `session.base`'s `/session`,
|
|
63
|
-
under the api service's `base: 'api'` — so the address is `GET /api/session/:sid/items`, computed
|
|
64
|
-
on demand by whoever asks. `elevate` is idempotent, so re-elevating an alias is allowed and guards
|
|
65
|
-
given at elevation are added to the declared ones.
|
|
66
|
-
|
|
67
|
-
Change a route or schema in `common` and both sides stay in sync. See [[entrypoint]], [[route]],
|
|
68
|
-
[[server-app]], [[web-client]], [[web-panel]].
|
|
69
|
-
|
|
70
|
-
## Shared config (where services live)
|
|
71
|
-
|
|
72
|
-
`common/config.ts` registers both services so the web knows where the API is. `base: 'api'`
|
|
73
|
-
prefixes API routes with `/api`:
|
|
11
|
+
An OwlMeans application owns one shared protocol declaration and creates local entrypoints for each
|
|
12
|
+
runtime. The declaration is never modified by a server or browser.
|
|
74
13
|
|
|
75
14
|
```ts
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
15
|
+
// common/src/entrypoints.ts
|
|
16
|
+
export const sessionEntrypoints = {
|
|
17
|
+
list: protocol(
|
|
18
|
+
route(session.list, '/session', backend()),
|
|
19
|
+
contract.request({ query: typed<SessionQuery>(SessionQuerySchema) }, typed<Session[]>())
|
|
20
|
+
),
|
|
21
|
+
}
|
|
82
22
|
```
|
|
83
23
|
|
|
84
|
-
api: `config(APP_API, commonConfig)` (+ `cfg.port`). web: `config(APP_WEB, commonConfig)`. See [[config]].
|
|
85
|
-
|
|
86
|
-
## Backend bootstrap + in-memory data
|
|
87
|
-
|
|
88
24
|
```ts
|
|
89
|
-
// api/
|
|
90
|
-
const
|
|
91
|
-
|
|
25
|
+
// api/src/entrypoints.ts
|
|
26
|
+
const api = handlers<Context>()
|
|
27
|
+
export const appEntrypoints = [
|
|
28
|
+
...frameworkEntrypoints,
|
|
29
|
+
bind(sessionEntrypoints.list, api.request(sessionEntrypoints.list, listSessions)),
|
|
30
|
+
]
|
|
92
31
|
```
|
|
93
32
|
|
|
94
|
-
Handlers use `handleRequest` / `handleBody` / `handleParams` (validated payload, then context, then
|
|
95
|
-
req). Read/write `ctx.getStaticResource<T>(alias)` — the full resource contract
|
|
96
|
-
(`get/load/list/count/create/update/save/delete/take/purge`), so the resource answers the whole
|
|
97
|
-
question rather than the handler filtering afterwards:
|
|
98
|
-
|
|
99
33
|
```ts
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
`list` returns `{ items, total }`; the in-memory backends are unpaged unless a `size` is asked for.
|
|
107
|
-
`main(context, appEntrypoints)` starts the server. See [[static-resource]], [[server-app]],
|
|
108
|
-
[[resource]].
|
|
109
|
-
|
|
110
|
-
Swap `@owlmeans/static-resource` for [[mongo-resource]] / [[redis-resource]] when you need
|
|
111
|
-
persistence — the handler shape is identical.
|
|
112
|
-
|
|
113
|
-
## Web bootstrap (shadcn)
|
|
114
|
-
|
|
115
|
-
`@owlmeans/web-panel`'s `PanelApp` is shadcn/Tailwind v4 (no MUI). The **app provides** the shadcn
|
|
116
|
-
primitives at the `@` alias — `web-panel` references `@/lib/utils` and
|
|
117
|
-
`@/components/ui/{alert,button,card,input,label,navigation-menu,progress}`; copy those into `src/`.
|
|
118
|
-
Routing resolves itself from the active router plugin, so `PanelApp` takes no router prop —
|
|
119
|
-
`render.tsx` is one line and `index.tsx` calls it:
|
|
120
|
-
|
|
121
|
-
```tsx
|
|
122
|
-
// render.tsx — import { render as basicRender } from '@owlmeans/web-client'
|
|
123
|
-
basicRender(<PanelApp context={context} />)
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
`vite.config.ts` sets `@`→`src`, `@tailwindcss/vite`, and dedupes the owlmeans/react singletons.
|
|
127
|
-
`index.css` is `@import "tailwindcss";` + a shadcn `@theme` token block (replaces `@owlmeans/owl-theme`).
|
|
128
|
-
A parent `BASE` route renders the layout via `handler(MainLayout)`; `HOME` is its default child, declared `frontend({ default: true, parent: BASE })`.
|
|
129
|
-
`index.tsx` calls `context.registerEntrypoints(appEntrypoints)` and `context.serviceRoute(...)` for
|
|
130
|
-
each service, then renders.
|
|
131
|
-
|
|
132
|
-
Screens address the backend through three explicit verbs on the entrypoint:
|
|
34
|
+
// web/src/entrypoints.ts
|
|
35
|
+
export const appEntrypoints = [
|
|
36
|
+
...frameworkEntrypoints,
|
|
37
|
+
...bindAll(sessionEntrypoints),
|
|
38
|
+
]
|
|
133
39
|
|
|
134
|
-
|
|
135
|
-
const items = await ctx.entrypoint<ClientEntrypoint<Item[]>>(session.list).call({ params: { sid } })
|
|
136
|
-
const { value, outcome } = await ctx.entrypoint<ClientEntrypoint<Item>>(session.add).invoke({ body })
|
|
137
|
-
const href = await ctx.entrypoint<ClientEntrypoint<string>>(web.about).url()
|
|
40
|
+
const sessions = await context.entrypoint(sessionEntrypoints.list).call({ query: { sid } })
|
|
138
41
|
```
|
|
139
42
|
|
|
140
|
-
`
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
See [[web-panel]], [[web-client]], [[shadcn-web]], [[client-entrypoint]].
|
|
144
|
-
|
|
145
|
-
The screen keeps nothing in component state: `makeContext` registers a `@owlmeans/state` resource,
|
|
146
|
-
the fetch writes what came back into it with `store.replace(items)`, and `useStoreList` renders the
|
|
147
|
-
live subscription. See [[state]].
|
|
148
|
-
|
|
149
|
-
## Authentication
|
|
150
|
-
|
|
151
|
-
This shape is intentionally **auth-free**. To add it: `@owlmeans/server-auth` + `@owlmeans/client-auth`
|
|
152
|
-
and `guard(...)` on entrypoints. See [[auth-protocol]], [[server-auth]], [[client-auth]].
|
|
43
|
+
Use `schema<T>(...)` or `typed<T>(...)` at the contract boundary. Bind all route parents with their
|
|
44
|
+
children. Keep organization entity values on the wire as `entitySlug`; database relations use
|
|
45
|
+
`entityId` only.
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"typecheck": "tsc -b"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@owlmeans/server-app": "^0.1.18-rc.
|
|
15
|
-
"@owlmeans/static-resource": "^0.1.18-rc.
|
|
14
|
+
"@owlmeans/server-app": "^0.1.18-rc.21",
|
|
15
|
+
"@owlmeans/static-resource": "^0.1.18-rc.12",
|
|
16
16
|
"__APP_SLUG__-common": "workspace:^"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sharedEntrypoints } from '__APP_SLUG__-common'
|
|
1
|
+
import { entrypoints } from '@owlmeans/server-app'
|
|
3
2
|
|
|
4
|
-
//
|
|
5
|
-
export const appEntrypoints = [...entrypoints
|
|
3
|
+
// The bare shell has no API declarations yet. Bind new protocols here as they are added.
|
|
4
|
+
export const appEntrypoints = [...entrypoints]
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { entrypoints } from '@owlmeans/server-app'
|
|
2
|
+
import { bind } from '@owlmeans/server-entrypoint'
|
|
3
|
+
import { appEntrypoints as protocols } from '__APP_SLUG__-common'
|
|
3
4
|
import * as handlers from './app/session/index.js'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/** Local server bindings for the shared session protocol tree. */
|
|
7
|
+
export const appEntrypoints = [
|
|
8
|
+
...entrypoints,
|
|
9
|
+
bind(protocols.api.session.base),
|
|
10
|
+
bind(protocols.api.session.list, handlers.list),
|
|
11
|
+
bind(protocols.api.session.add, handlers.add),
|
|
12
|
+
bind(protocols.api.session.remove, handlers.remove),
|
|
13
|
+
]
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"typecheck": "tsc -b"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
23
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
24
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
25
|
-
"@owlmeans/resource": "^0.1.18-rc.
|
|
26
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
22
|
+
"@owlmeans/config": "^0.1.18-rc.15",
|
|
23
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.14",
|
|
24
|
+
"@owlmeans/error": "^0.1.18-rc.11",
|
|
25
|
+
"@owlmeans/resource": "^0.1.18-rc.12",
|
|
26
|
+
"@owlmeans/route": "^0.1.18-rc.12",
|
|
27
27
|
"ajv": "^8.17.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { openProtocol } from '@owlmeans/entrypoint'
|
|
2
|
+
import { BASE, HOME } from '@owlmeans/context'
|
|
3
|
+
import { frontend, route } from '@owlmeans/route'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const webBase = openProtocol(route(BASE, '/', frontend()))
|
|
6
|
+
|
|
7
|
+
/** The shared immutable protocol tree. Add API declarations below `api` as the shell grows. */
|
|
8
|
+
export const appEntrypoints = {
|
|
9
|
+
api: {},
|
|
10
|
+
web: {
|
|
11
|
+
base: webBase,
|
|
12
|
+
home: openProtocol(route(HOME, '/', frontend({ default: true, parent: webBase }))),
|
|
13
|
+
},
|
|
14
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { contract, openProtocol, protocol,
|
|
1
|
+
import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
|
|
2
2
|
import { route, RouteMethod, frontend } from '@owlmeans/route'
|
|
3
3
|
import { AddItemSchema, ItemParamsSchema, SessionParamsSchema } from './schemas.js'
|
|
4
4
|
import type { SessionItem } from './types.js'
|
|
@@ -22,8 +22,8 @@ const sessionBase = protocol(route(aliases.session.base, '/session'), contract()
|
|
|
22
22
|
const webBase = openProtocol(route(aliases.web.base, '/', frontend()))
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Shared entrypoint declarations. The api
|
|
26
|
-
*
|
|
25
|
+
* Shared entrypoint declarations. The api materializes these with handlers; the web
|
|
26
|
+
* materializes them with screen components and calls them. Routes resolve under the
|
|
27
27
|
* api service `base` (`/api`), so e.g. `session.list` → `GET /api/session/:sid/items`.
|
|
28
28
|
*/
|
|
29
29
|
export const session = {
|
|
@@ -53,4 +53,8 @@ export const web = {
|
|
|
53
53
|
about: openProtocol(route(aliases.web.about, '/about', frontend({ parent: webBase }))),
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
/** The shared immutable protocol tree. Runtime packages bind their own local handlers and screens. */
|
|
57
|
+
export const appEntrypoints = {
|
|
58
|
+
api: { session },
|
|
59
|
+
web,
|
|
60
|
+
}
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
"preview": "vite preview"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@owlmeans/client": "^0.1.18-rc.
|
|
15
|
-
"@owlmeans/client-config": "^0.1.18-rc.
|
|
16
|
-
"@owlmeans/client-context": "^0.1.18-rc.
|
|
17
|
-
"@owlmeans/client-entrypoint": "^0.1.18-rc.
|
|
18
|
-
"@owlmeans/client-i18n": "^0.1.18-rc.
|
|
19
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
20
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
21
|
-
"@owlmeans/state": "^0.1.18-rc.
|
|
22
|
-
"@owlmeans/web-client": "^0.1.18-rc.
|
|
23
|
-
"@owlmeans/web-panel": "^0.1.18-rc.
|
|
14
|
+
"@owlmeans/client": "^0.1.18-rc.19",
|
|
15
|
+
"@owlmeans/client-config": "^0.1.18-rc.15",
|
|
16
|
+
"@owlmeans/client-context": "^0.1.18-rc.16",
|
|
17
|
+
"@owlmeans/client-entrypoint": "^0.1.18-rc.16",
|
|
18
|
+
"@owlmeans/client-i18n": "^0.1.18-rc.18",
|
|
19
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.14",
|
|
20
|
+
"@owlmeans/route": "^0.1.18-rc.12",
|
|
21
|
+
"@owlmeans/state": "^0.1.18-rc.13",
|
|
22
|
+
"@owlmeans/web-client": "^0.1.18-rc.27",
|
|
23
|
+
"@owlmeans/web-panel": "^0.1.18-rc.35",
|
|
24
24
|
"@radix-ui/react-label": "^2.1.0",
|
|
25
25
|
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
26
26
|
"@radix-ui/react-progress": "^1.1.0",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { bindAll, bindScreen, entrypoints as baseEntrypoints, handler } from '@owlmeans/web-panel'
|
|
2
|
+
import { appEntrypoints as protocols } from '__APP_SLUG__-common'
|
|
3
3
|
import { MainLayout } from './layout/main.js'
|
|
4
4
|
import { HomeScreen } from './screens/home.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
/** Local browser bindings for shared API and screen protocols. */
|
|
7
|
+
export const appEntrypoints = [
|
|
8
|
+
...baseEntrypoints,
|
|
9
|
+
...bindAll(protocols.api),
|
|
10
|
+
// BASE renders the shared layout; HOME is its default child.
|
|
11
|
+
bindScreen(protocols.web.base, handler(MainLayout)),
|
|
12
|
+
bindScreen(protocols.web.home, handler(HomeScreen)),
|
|
13
|
+
]
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { bindAll, bindScreen, entrypoints as baseEntrypoints, handler } from '@owlmeans/web-panel'
|
|
2
|
-
import {
|
|
2
|
+
import { appEntrypoints as protocols } from '__APP_SLUG__-common'
|
|
3
3
|
import { MainLayout } from './layout/main.js'
|
|
4
4
|
import { AboutScreen } from './screens/about.js'
|
|
5
5
|
import { HomeScreen } from './screens/home.js'
|
|
6
6
|
import { SessionScreen } from './screens/session.js'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
/** Local browser bindings for shared API and screen protocols. */
|
|
9
|
+
export const appEntrypoints = [
|
|
10
|
+
...baseEntrypoints,
|
|
11
|
+
...bindAll(protocols.api),
|
|
12
|
+
bindScreen(protocols.web.base, handler(MainLayout)),
|
|
13
|
+
bindScreen(protocols.web.home, handler(HomeScreen)),
|
|
14
|
+
bindScreen(protocols.web.session, handler(SessionScreen)),
|
|
15
|
+
bindScreen(protocols.web.about, handler(AboutScreen)),
|
|
16
|
+
]
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* scan by default — so the classes that exist ONLY inside @owlmeans/web-panel components
|
|
6
6
|
* (the navigation shell, the footer) would never reach the stylesheet. This line adds them.
|
|
7
7
|
*/
|
|
8
|
-
@source "../../../node_modules/@owlmeans/web-panel/
|
|
8
|
+
@source "../../../node_modules/@owlmeans/web-panel/src";
|
|
9
9
|
|
|
10
10
|
/*
|
|
11
11
|
* shadcn / Tailwind v4 design tokens (new-york, neutral). The app owns these — they
|