@ai0x0/utils 0.1.2 → 0.1.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/SKILL.md CHANGED
@@ -68,7 +68,7 @@ export const getListOperation = createGetListOperation({ db, getSession });
68
68
 
69
69
  | Export | Purpose | Required options | Notable optional options |
70
70
  | ------------------- | -------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
71
- | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
71
+ | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `serverColumns`, `refineSchema`, `extraConfig` |
72
72
  | `getOperation` | GET one by filters | `schemas.query`, `schemas.response` | `table`, `setParams`, `relations`, `jsonArrayFields`, `access.byCreator`, `handler`, `catch`, `openApiOperation` |
73
73
  | `getListOperation` | GET paginated list | `schemas.query`, `schemas.response` | `table`, `setParams`, `relations`, `jsonArrayFields`, `handler`, `catch`, `openApiOperation` |
74
74
  | `postOperation` | POST create | `schemas.body` | `table`, `contentType`, `parseBody`, `schemas.response`, `setBody`, `handler`, `catch`, `openApiOperation` |
@@ -308,7 +308,8 @@ export const { GET } = route({
308
308
 
309
309
  ## Built-in Conventions
310
310
 
311
- - **Base fields** auto-added by `createTableSchema`: `id` (uuid, pk, default random) / `creatorId` / `editorId` / `accessedAt` / `createdAt` / `updatedAt`.
311
+ - **Base fields** auto-added by `createTableSchema`: `id` (uuid, pk, default random) / `creatorId` / `editorId` / `accessedAt` / `createdAt` / `updatedAt`. They never appear in the insert/update schemas — the server writes them.
312
+ - **Server-owned business columns** (`serverColumns: { ownerId: uuid("owner_id").notNull() }`): a second column bucket, alongside `columns`. Everything in it goes on the table and into `selectSchema` (you can read it), but **not** into `insertSchema` / `updateSchema` — exactly how the base fields already behave, just opened up to columns you declare yourself. Use it for anything carrying ownership (`ownerId`, `tenantId`): letting a client send that column is letting it choose whose row this is. Pair it with `access.scope.column` — that decides _which rows you see_, this decides _that you cannot write the column_. Which bucket a column sits in is the whole rule, so there is nothing to remember and nothing to forget; `insertSchema.omit(...)` per table would work too, but missing one table is not a compile error, it is a silent privilege escalation.
312
313
  - **Row-level scope** (`access`, on by default for every verb): the request may only see / touch rows whose scope column matches. Three knobs:
313
314
  - `byCreator?: boolean` — the old spelling, equivalent to `scope: { column: "creatorId", value: (s) => s.userId }`. Default `true`.
314
315
  - `scope?: { column?, value }` — pick the column (default `creatorId`) and derive the value from the session. Return an array for `IN (...)`. Use this when a row can belong to something other than one user (a team, a workspace).