@metaobjectsdev/sdk 0.12.2 → 0.12.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.
|
@@ -351,7 +351,10 @@ child traversal, package only on the root segment) and/or carry `origin.*`
|
|
|
351
351
|
children (`passthrough` / `aggregate` / `collection`) declaring assembly; its
|
|
352
352
|
identity passes through via `extends` (`identity.primary: { name: id, extends:
|
|
353
353
|
"Author.id" }`); it is read-only by construction and the declared field set IS
|
|
354
|
-
the exposure (fail-closed).
|
|
354
|
+
the exposure (fail-closed). Give it a read-only `source.rdb` `@kind: view`
|
|
355
|
+
child (`source.rdb: { kind: view, table: v_author }`) — codegen keys projection
|
|
356
|
+
detection + view DDL off that read-only source, so without it `meta gen` emits
|
|
357
|
+
nothing for the projection.
|
|
355
358
|
|
|
356
359
|
## Abstracts + `extends` (deferred resolution) + `overlay`
|
|
357
360
|
|
|
@@ -61,6 +61,40 @@ entity never emits instance/write artifacts regardless.
|
|
|
61
61
|
Per-entity opt-outs exist (e.g. skipping client-side artifacts for a given
|
|
62
62
|
entity) and are set as attributes on the entity in metadata, not in code.
|
|
63
63
|
|
|
64
|
+
## You don't have to generate everything — pick your layers
|
|
65
|
+
|
|
66
|
+
Codegen is **granular and à la carte, not all-or-nothing.** The most powerful
|
|
67
|
+
pattern when an app's API doesn't match generated CRUD: **generate the data layer,
|
|
68
|
+
hand-write only the API layer** — never abandon codegen wholesale and hand-write
|
|
69
|
+
the data access too.
|
|
70
|
+
|
|
71
|
+
- **Generate the data layer, skip the routes.** Omit `routesFile()` from the
|
|
72
|
+
`generators` array (keep `entityFile()` + `queriesFile()` + `barrel()`): you get
|
|
73
|
+
the typed entity/table, schemas, and query/finder helpers, then write your own
|
|
74
|
+
routes by hand — *calling the generated queries*. Do this whenever the API shape
|
|
75
|
+
(custom paths, HTML responses, nested payloads) doesn't fit generated REST CRUD.
|
|
76
|
+
- **Mix generated and hand-written routes.** Even with custom paths, mount the
|
|
77
|
+
standard verbs with the runtime helpers and hand-write only the custom ones (see
|
|
78
|
+
the runtime skill's `mountCrudRoutes` / `mount<Verb>Route` / `expose`). You are
|
|
79
|
+
never forced into all-generated or all-hand-written.
|
|
80
|
+
- **Derived/aggregate data → declare a projection, then USE its generated query.**
|
|
81
|
+
Don't hand-write a join or an `AVG()`/`COUNT()`. Declare an `object.projection`
|
|
82
|
+
with `origin.aggregate` / `origin.passthrough` / `origin.collection` children
|
|
83
|
+
**and a read-only `source.rdb` `@kind: view` child** (codegen detects a
|
|
84
|
+
projection by that read-only source, not by the subtype alone — omit it and
|
|
85
|
+
nothing is generated). `meta gen` emits a read-only query for it (and
|
|
86
|
+
`meta migrate` its DB view), and you **call that generated query from your
|
|
87
|
+
route**. Declaring the projection is only half the win — *consuming* its
|
|
88
|
+
generated query is the other half.
|
|
89
|
+
- **Codegen is yours to extend.** A generated file carries the `@generated` header
|
|
90
|
+
and is a normal source file: copy it and customize the copy (three-way merge
|
|
91
|
+
preserves your edits on regen), or write your own `Generator` (the plugin
|
|
92
|
+
interface) and add it to the `generators` array for an artifact the built-ins
|
|
93
|
+
don't cover.
|
|
94
|
+
|
|
95
|
+
`meta gen --list` prints every generator by stable name; the `generators` array in
|
|
96
|
+
`metaobjects.config.ts` is where you opt each one in or out.
|
|
97
|
+
|
|
64
98
|
## Dialects
|
|
65
99
|
|
|
66
100
|
Generated DB schema/DDL targets a SQL **dialect**:
|
|
@@ -90,3 +90,33 @@ The routes call `parseFilterParams` (from `@metaobjectsdev/runtime-ts/drizzle-fa
|
|
|
90
90
|
to validate `?filter[..][..]=..&sort=..&limit=&offset=` against the generated
|
|
91
91
|
`<Entity>FilterAllowlist` / `<Entity>SortAllowlist`, returning HTTP 400 on an
|
|
92
92
|
unknown field or disallowed operator.
|
|
93
|
+
|
|
94
|
+
### Granular routes — mount some, hand-write the rest (don't read `node_modules`)
|
|
95
|
+
|
|
96
|
+
When the API doesn't match generated CRUD, you don't have to choose all-generated
|
|
97
|
+
or all-hand-written, and you never need to reverse-engineer the runtime package.
|
|
98
|
+
`@metaobjectsdev/runtime-ts/drizzle-fastify` exports the mount helpers the generated
|
|
99
|
+
routes are built from — call them directly:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import {
|
|
103
|
+
mountCrudRoutes, mountGetRoute, mountListRoute, mountReadOnlyCrudRoutes,
|
|
104
|
+
} from "@metaobjectsdev/runtime-ts/drizzle-fastify";
|
|
105
|
+
import { RecipeInsertSchema, RecipeUpdateSchema } from "./generated/Recipe.js";
|
|
106
|
+
|
|
107
|
+
// all five verbs:
|
|
108
|
+
mountCrudRoutes({ fastify: app, path: "/recipes", db, table: recipes,
|
|
109
|
+
insertSchema: RecipeInsertSchema, updateSchema: RecipeUpdateSchema });
|
|
110
|
+
|
|
111
|
+
mountCrudRoutes({ ...opts, expose: ["list", "get"] }); // only some verbs
|
|
112
|
+
mountReadOnlyCrudRoutes({ ...opts }); // list + get only
|
|
113
|
+
mountGetRoute({ ...opts }); // a single verb
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`CrudRoutesOptions` = `{ fastify, path, db, table, insertSchema, updateSchema }`
|
|
117
|
+
plus `expose?` (limit verbs), `routeOptions?` (Fastify hooks — e.g.
|
|
118
|
+
`{ preHandler: requireAuthHook }` for auth), and `updateMethod?` (`"patch"` default
|
|
119
|
+
/ `"put"`). So **mount the standard verbs with these helpers and hand-write only the
|
|
120
|
+
custom routes** (HTML pages, nested resources, computed fields) — calling the
|
|
121
|
+
generated query helpers, and a projection's generated query for derived/aggregate
|
|
122
|
+
data. Generate the data layer; hand-write only what's genuinely custom.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/sdk",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Workspace helpers and agent-docs utilities for MetaObjects projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@metaobjectsdev/metadata": "0.12.
|
|
59
|
+
"@metaobjectsdev/metadata": "0.12.3",
|
|
60
60
|
"zod": "^3.23.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|