@metaobjectsdev/sdk 0.12.2 → 0.12.3-rc.1

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.2",
3
+ "version": "0.12.3-rc.1",
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.2",
59
+ "@metaobjectsdev/metadata": "0.12.3-rc.1",
60
60
  "zod": "^3.23.0"
61
61
  },
62
62
  "devDependencies": {