@beignet/core 0.0.20 → 0.0.21
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 +6 -0
- package/README.md +7 -0
- package/package.json +4 -2
- package/skills/app-architecture/SKILL.md +159 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -30,6 +30,13 @@ npm install arktype
|
|
|
30
30
|
|
|
31
31
|
This package requires TypeScript 5.0 or higher for proper type inference.
|
|
32
32
|
|
|
33
|
+
## Agent skills
|
|
34
|
+
|
|
35
|
+
This package ships a TanStack Intent skill for coding agents:
|
|
36
|
+
`@beignet/core#app-architecture`. Load it when adding or fixing Beignet
|
|
37
|
+
schemas, contracts, use cases, app errors, ports, policies, app context,
|
|
38
|
+
providers, workflow primitives, or core subpath imports.
|
|
39
|
+
|
|
33
40
|
## Subpaths
|
|
34
41
|
|
|
35
42
|
Install `@beignet/core` once, then import the framework area you need. The
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beignet/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core framework primitives for Beignet",
|
|
6
6
|
"exports": {
|
|
@@ -150,6 +150,7 @@
|
|
|
150
150
|
"!src/**/*.test.ts",
|
|
151
151
|
"!src/**/*.test.tsx",
|
|
152
152
|
"!src/**/*.test-d.ts",
|
|
153
|
+
"skills",
|
|
153
154
|
"README.md",
|
|
154
155
|
"CHANGELOG.md"
|
|
155
156
|
],
|
|
@@ -167,7 +168,8 @@
|
|
|
167
168
|
"api",
|
|
168
169
|
"typescript",
|
|
169
170
|
"standard-schema",
|
|
170
|
-
"validation"
|
|
171
|
+
"validation",
|
|
172
|
+
"tanstack-intent"
|
|
171
173
|
],
|
|
172
174
|
"license": "MIT",
|
|
173
175
|
"repository": {
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: app-architecture
|
|
3
|
+
description: "Build Beignet app feature slices with @beignet/core primitives: schemas, contracts, use cases, app errors, ports, policies, context, providers, jobs, schedules, tasks, outbox, mail, uploads, and tests. Use when adding or fixing Beignet application behavior, dependency boundaries, app-facing ports, authorization, workflow primitives, or core subpath imports."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Beignet App Architecture
|
|
7
|
+
|
|
8
|
+
Use this skill when working in an app that depends on `@beignet/core`.
|
|
9
|
+
Read the app's `AGENTS.md`, `beignet.config.*`, and closest existing feature
|
|
10
|
+
slice before changing code.
|
|
11
|
+
|
|
12
|
+
## Source Order
|
|
13
|
+
|
|
14
|
+
1. Follow local app instructions and configured paths.
|
|
15
|
+
2. Reuse the nearest feature slice's naming and helper exports.
|
|
16
|
+
3. Inspect installed `@beignet/core/*` exports and types when an API is unclear.
|
|
17
|
+
4. Read narrow Beignet docs only for the concept being changed.
|
|
18
|
+
|
|
19
|
+
## Feature Slice
|
|
20
|
+
|
|
21
|
+
Normal feature code belongs here:
|
|
22
|
+
|
|
23
|
+
```txt
|
|
24
|
+
features/<feature>/
|
|
25
|
+
contracts.ts
|
|
26
|
+
schemas.ts
|
|
27
|
+
routes.ts
|
|
28
|
+
use-cases/
|
|
29
|
+
ports.ts
|
|
30
|
+
policy.ts
|
|
31
|
+
client/
|
|
32
|
+
components/
|
|
33
|
+
tests/
|
|
34
|
+
factories/
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Small features do not need every file. Add folders when the concern exists.
|
|
38
|
+
|
|
39
|
+
## Core Boundaries
|
|
40
|
+
|
|
41
|
+
- Contracts and schemas must be import-safe for clients and OpenAPI.
|
|
42
|
+
- Use cases own business workflows and depend on `ctx.ports`, not infra.
|
|
43
|
+
- Domain and use-case code must not import React, routes, providers, server
|
|
44
|
+
runtime, or concrete adapters.
|
|
45
|
+
- Infra implements ports and may import provider packages, SDKs, and database
|
|
46
|
+
clients.
|
|
47
|
+
- UI and feature client modules call server behavior through contracts and a
|
|
48
|
+
typed client, not by importing use cases.
|
|
49
|
+
|
|
50
|
+
## Contracts And Schemas
|
|
51
|
+
|
|
52
|
+
Use `@beignet/core/contracts` and keep shared DTOs in `schemas.ts`.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { defineContractGroup } from "@beignet/core/contracts";
|
|
56
|
+
import { z } from "zod";
|
|
57
|
+
import { errors } from "@/features/shared/errors";
|
|
58
|
+
|
|
59
|
+
export const projectSchema = z.object({
|
|
60
|
+
id: z.string().uuid(),
|
|
61
|
+
name: z.string().min(1),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const projects = defineContractGroup()
|
|
65
|
+
.namespace("projects")
|
|
66
|
+
.prefix("/api/projects");
|
|
67
|
+
|
|
68
|
+
export const getProject = projects
|
|
69
|
+
.get("/:id")
|
|
70
|
+
.pathParams(z.object({ id: z.string().uuid() }))
|
|
71
|
+
.errors({ ProjectNotFound: errors.ProjectNotFound })
|
|
72
|
+
.responses({ 200: projectSchema });
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If a route-backed use case throws `appError("ProjectNotFound")`, the matching
|
|
76
|
+
contract should declare `ProjectNotFound` with `.errors(...)`.
|
|
77
|
+
|
|
78
|
+
## Use Cases
|
|
79
|
+
|
|
80
|
+
Use the app-bound `useCase` builder from `lib/use-case.ts`.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { requireUserId } from "@beignet/core/ports";
|
|
84
|
+
import { appError } from "@/features/shared/errors";
|
|
85
|
+
import { projectIdInputSchema, projectSchema } from "@/features/projects/schemas";
|
|
86
|
+
import { useCase } from "@/lib/use-case";
|
|
87
|
+
|
|
88
|
+
export const getProjectUseCase = useCase
|
|
89
|
+
.query("projects.get")
|
|
90
|
+
.input(projectIdInputSchema)
|
|
91
|
+
.output(projectSchema)
|
|
92
|
+
.run(async ({ ctx, input }) => {
|
|
93
|
+
const userId = requireUserId(ctx);
|
|
94
|
+
const project = await ctx.ports.projects.findById(input.id);
|
|
95
|
+
if (!project) throw appError("ProjectNotFound", { details: input });
|
|
96
|
+
|
|
97
|
+
await ctx.gate.authorize("projects.read", project);
|
|
98
|
+
return project;
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Use `ctx.ports.uow.transaction(...)` when writes, audit entries, events, jobs,
|
|
103
|
+
or outbox records must commit together.
|
|
104
|
+
|
|
105
|
+
## Errors And Policies
|
|
106
|
+
|
|
107
|
+
- Generated apps usually place the error catalog in `features/shared/errors.ts`.
|
|
108
|
+
Some apps centralize it elsewhere; reuse the existing catalog.
|
|
109
|
+
- Business authorization belongs in use cases or feature policies, not only
|
|
110
|
+
route metadata.
|
|
111
|
+
- Put a policy in the feature that owns the authorized resource. Cross-feature
|
|
112
|
+
abilities may still live there when they inspect that resource.
|
|
113
|
+
|
|
114
|
+
## Ports And Providers
|
|
115
|
+
|
|
116
|
+
- Feature-specific ports usually live in `features/<feature>/ports.ts`.
|
|
117
|
+
- App-wide ports live in `ports/`.
|
|
118
|
+
- Default wiring belongs in `infra/app-ports.ts`.
|
|
119
|
+
- `bound` ports are app-owned at boot, such as gates, config, clocks, IDs, or
|
|
120
|
+
no-op reporters.
|
|
121
|
+
- `deferred` ports are supplied by providers at startup, such as auth,
|
|
122
|
+
database, mail, logger, jobs, repositories, idempotency, and rate limits.
|
|
123
|
+
|
|
124
|
+
Do not import provider packages from contracts, use cases, routes, UI, or
|
|
125
|
+
feature client modules.
|
|
126
|
+
|
|
127
|
+
## Workflows
|
|
128
|
+
|
|
129
|
+
Feature-owned workflow definitions belong under the feature:
|
|
130
|
+
|
|
131
|
+
```txt
|
|
132
|
+
features/<feature>/jobs/
|
|
133
|
+
features/<feature>/schedules/
|
|
134
|
+
features/<feature>/notifications/
|
|
135
|
+
features/<feature>/tasks/
|
|
136
|
+
features/<feature>/uploads/
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Small existing apps may use feature-root `jobs.ts` or `schedules.ts`; follow
|
|
140
|
+
local style unless migrating deliberately. Central registries and service
|
|
141
|
+
contexts live under `server/`.
|
|
142
|
+
|
|
143
|
+
Providers should not start unbounded background loops on server boot. Expose
|
|
144
|
+
cron routes, worker entrypoints, task runners, schedule runners, or outbox
|
|
145
|
+
drains instead.
|
|
146
|
+
|
|
147
|
+
## Validation
|
|
148
|
+
|
|
149
|
+
After core app-architecture changes, run from the app root:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
beignet lint
|
|
153
|
+
beignet doctor --strict
|
|
154
|
+
bun run test
|
|
155
|
+
bun run typecheck
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Use the app's package manager and scripts. If package-manager shims are not on
|
|
159
|
+
PATH, use local binaries such as `./node_modules/.bin/beignet lint`.
|