@metaobjectsdev/runtime-ts 1.1.1 → 1.1.2

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.
Files changed (36) hide show
  1. package/dist/decimal-wire.d.ts +16 -6
  2. package/dist/decimal-wire.d.ts.map +1 -1
  3. package/dist/decimal-wire.js +25 -8
  4. package/dist/decimal-wire.js.map +1 -1
  5. package/dist/drizzle-fastify/index.d.ts +5 -9
  6. package/dist/drizzle-fastify/index.d.ts.map +1 -1
  7. package/dist/drizzle-fastify/index.js +5 -4
  8. package/dist/drizzle-fastify/index.js.map +1 -1
  9. package/dist/drizzle-fastify/mount-m2m.d.ts +2 -3
  10. package/dist/drizzle-fastify/mount-m2m.d.ts.map +1 -1
  11. package/dist/drizzle-fastify/mount-m2m.js +2 -2
  12. package/dist/drizzle-fastify/mount-m2m.js.map +1 -1
  13. package/dist/drizzle-fastify/mount-read-only.d.ts +2 -9
  14. package/dist/drizzle-fastify/mount-read-only.d.ts.map +1 -1
  15. package/dist/drizzle-fastify/mount-read-only.js +2 -2
  16. package/dist/drizzle-fastify/mount-read-only.js.map +1 -1
  17. package/dist/hono/index.d.ts +5 -9
  18. package/dist/hono/index.d.ts.map +1 -1
  19. package/dist/hono/index.js +5 -4
  20. package/dist/hono/index.js.map +1 -1
  21. package/dist/hono/mount-read-only.d.ts +2 -9
  22. package/dist/hono/mount-read-only.d.ts.map +1 -1
  23. package/dist/hono/mount-read-only.js +2 -2
  24. package/dist/hono/mount-read-only.js.map +1 -1
  25. package/dist/wire-format.d.ts +35 -0
  26. package/dist/wire-format.d.ts.map +1 -0
  27. package/dist/wire-format.js +77 -0
  28. package/dist/wire-format.js.map +1 -0
  29. package/package.json +3 -3
  30. package/src/decimal-wire.ts +26 -6
  31. package/src/drizzle-fastify/index.ts +7 -12
  32. package/src/drizzle-fastify/mount-m2m.ts +3 -5
  33. package/src/drizzle-fastify/mount-read-only.ts +3 -11
  34. package/src/hono/index.ts +7 -12
  35. package/src/hono/mount-read-only.ts +3 -11
  36. package/src/wire-format.ts +103 -0
@@ -1,9 +1,10 @@
1
1
  import { type SqlDialect } from "../sql-dialect.js";
2
2
  import type { Hono } from "hono";
3
3
  import type { FilterAllowlist, SortAllowlist } from "../drizzle-fastify/filter-allowlist.js";
4
+ import { type WireOptions } from "../wire-format.js";
4
5
  type AnyView = any;
5
6
  type AnyHono = Hono<any, any, any>;
6
- export interface MountReadOnlyOptions {
7
+ export interface MountReadOnlyOptions extends WireOptions {
7
8
  readonly app: AnyHono;
8
9
  readonly path: string;
9
10
  readonly db: any;
@@ -29,14 +30,6 @@ export interface MountReadOnlyOptions {
29
30
  readonly itemRoutes?: boolean;
30
31
  /** The noun in the 405 message, which is free prose. Default "projection". */
31
32
  readonly resource?: "projection" | "report";
32
- /**
33
- * The names of the view's `field.decimal` fields. A decimal is a canonical string on the wire
34
- * on every dialect (ADR-0019 Amendment 1): Postgres and MySQL return the column's scale
35
- * (`"100.5000"`), and SQLite hands back a number, a REAL for a computed one (a report's ratio,
36
- * average or sum). Each row is rewritten under these keys. The generated route passes them;
37
- * absent, rows are sent as read. Default none.
38
- */
39
- readonly decimalColumns?: readonly string[];
40
33
  }
41
34
  export declare function mountReadOnlyCrudRoutes(opts: MountReadOnlyOptions): void;
42
35
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"mount-read-only.d.ts","sourceRoot":"","sources":["../../src/hono/mount-read-only.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAIjC,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACd,MAAM,wCAAwC,CAAC;AAQhD,KAAK,OAAO,GAAG,GAAG,CAAC;AAEnB,KAAK,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAyED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAoIxE"}
1
+ {"version":3,"file":"mount-read-only.d.ts","sourceRoot":"","sources":["../../src/hono/mount-read-only.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAIjC,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACd,MAAM,wCAAwC,CAAC;AAGhD,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAK/D,KAAK,OAAO,GAAG,GAAG,CAAC;AAEnB,KAAK,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnC,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;CAC7C;AAyED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAoIxE"}
@@ -7,7 +7,7 @@ import qs from "qs";
7
7
  import { parseFilterParams, parsePageBound, RAW_VIEW_MAX_LIMIT, FilterParseError } from "../drizzle-fastify/filter-parser.js";
8
8
  import { isTruthyFlag, coerceIdForColumn, rawIdLiteral, contractErrorCode, viewBaseConfig } from "../drizzle-fastify/util.js";
9
9
  import { timestampWire } from "../timestamp-wire.js";
10
- import { withDecimals } from "../decimal-wire.js";
10
+ import { withWire } from "../wire-format.js";
11
11
  // An unexpected error on a mounted route answers `500 { error: "internal" }`.
12
12
  import { guardRoute } from "./route-guard.js";
13
13
  function resolveViewName(view) {
@@ -84,7 +84,7 @@ export function mountReadOnlyCrudRoutes(opts) {
84
84
  const useRawSql = isEmptyColumnView(view) && !!viewName;
85
85
  // The raw-SQL branch has no declared columns, so nothing names a timestamp there.
86
86
  const timestamps = timestampWire(view);
87
- const toWire = withDecimals(timestamps, opts.decimalColumns);
87
+ const toWire = withWire(timestamps, opts);
88
88
  // ── List ──────────────────────────────────────────────────────────────────
89
89
  app.get(path, guardRoute(async (c) => {
90
90
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"mount-read-only.js","sourceRoot":"","sources":["../../src/hono/mount-read-only.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mount-read-only.js","sourceRoot":"","sources":["../../src/hono/mount-read-only.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,8EAA8E;AAC9E,4EAA4E;AAE5E,OAAO,EAAE,UAAU,EAAmB,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAK9H,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC9H,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAoB,MAAM,mBAAmB,CAAC;AAC/D,8EAA8E;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAoC9C,SAAS,eAAe,CAAC,IAAa;IACpC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,MAAM,CAAW,CAAC;IACpE,CAAC;IACD,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,OAAO,CACL,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CACpE,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAa;IACtC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAwC,CAAC;QAC5E,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,WAAW,CAAC,GAA4B;IAC/C,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,iFAAiF;AACjF,KAAK,UAAU,OAAO,CAAC,EAAO,EAAE,OAA2B,EAAE,KAAc;IACzE,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAY,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,GAAgC,CAAC;QAChE,OAAQ,GAAmD,EAAE,IAAI,IAAI,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,mCAAmC;QACnC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAyC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAA8B,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAA0B;IAChE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC;IAE7C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;IACxD,kFAAkF;IAClF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAE1C,6EAA6E;IAC7E,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;gBACtB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC9B,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAA4B,CAAC;gBAChE,0EAA0E;gBAC1E,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,kBAAkB,CAAC,IAAI,kBAAkB,CAAC;gBAC3F,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACxD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;gBACpD,iEAAiE;gBACjE,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,iBAAiB,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,QAAQ,WAAW,SAAS,EAAE,CAAC,CAAC,CAAU,CAAC;gBACpJ,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3E,IAAI,CAAC,SAAS;oBAAE,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzC,iEAAiE;gBACjE,MAAM,SAAS,GAAG,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,6BAA6B,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAU,CAAC;gBAC/H,MAAM,KAAK,GAAW,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;gBACnD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;YACtB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAA4B,CAAC;YAChE,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,iBAAiB,CAAC;gBAC/B,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,IAAI;gBACX,SAAS,EAAE,eAAe;gBAC1B,aAAa;gBACb,OAAO;aACR,CAAC,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,WAAW;gBACtD,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC;gBACvC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,aAAa;gBAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC9C,IAAI,MAAM,CAAC,OAAO;gBAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;gBAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1D,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;gBAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7D,yEAAyE;YACzE,oEAAoE;YACpE,2EAA2E;YAC3E,0EAA0E;YAC1E,6DAA6D;YAC7D,MAAM,IAAI,GAAG,CAAC,MAAM,CAAe,CAAA,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAEhD,IAAI,CAAC,SAAS;gBAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEpC,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,aAAa;gBAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAA8B,CAAC;YAC5D,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;gBACpC,2EAA2E;gBAC3E,yCAAyC;gBACzC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC3G,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC,CAAC;IAEJ,uFAAuF;IACvF,mDAAmD;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,6EAA6E;QAC7E,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAC5C,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,SAAS,EAAE,CAAC;gBACd,iEAAiE;gBACjE,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,iBAAiB,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,YAAY,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAU,CAAC;gBAChL,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACvD,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;YACjE,CAAC;YACD,sEAAsE;YACtE,MAAM,MAAM,GAAI,IAAY,CAAC,KAAK,CAAC,CAAC;YACpC,sFAAsF;YACtF,+EAA+E;YAC/E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,qFAAqF;YACrF,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC9C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,CAAC;YACD,6EAA6E;YAC7E,0CAA0C;YAC1C,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,EAAE;iBACR,IAAI,CAAC,IAAI,CAAC;iBACV,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;iBAC1B,KAAK,CAAC,CAAC,CAAC,CAAC;YACZ,MAAM,GAAG,GAAI,IAAkB,CAAC,CAAC,CAAC,CAAC;YACnC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,CAAgF,EAAE,EAAE,CAClG,CAAC,CAAC,IAAI,CACJ,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,0BAA0B,QAAQ,eAAe,EAAE,EAC1G,GAAG,CACJ,CAAC;IACJ,wEAAwE;IACxE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,MAAa,CAAC,CAAC;IAC9B,IAAI,UAAU,EAAE,CAAC;QACf,wEAAwE;QACxE,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,EAAE,MAAa,CAAC,CAAC;QACxC,gFAAgF;QAChF,2EAA2E;QAC3E,wEAAwE;QACxE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,MAAM,EAAE,MAAa,CAAC,CAAC;QACtC,wEAAwE;QACxE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,EAAE,MAAa,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { type DecimalWireMode } from "./decimal-wire.js";
2
+ /** `wire.nullMembers`. */
3
+ export type NullMembersMode = "native" | "emit" | "omit";
4
+ /**
5
+ * The declared shape of a value object held by a jsonb column: its member names, and the shape
6
+ * of any member that is itself a value object. `map` marks a `field.map` of value objects (the
7
+ * column's value is an object keyed by arbitrary text, each value a value object). An array
8
+ * (`isArray`) needs no flag: the walk reads the value's own shape.
9
+ */
10
+ export interface ValueObjectShape {
11
+ readonly members: readonly string[];
12
+ readonly map?: boolean;
13
+ readonly nested?: Readonly<Record<string, ValueObjectShape>>;
14
+ }
15
+ /** The wire options every read-side mount takes beside its other options. */
16
+ export interface WireOptions {
17
+ /**
18
+ * The names of the entity's `field.decimal` fields. Each row sent is rewritten under these
19
+ * keys: `native` (default) leaves the string a driver returned and renders a SQLite number at
20
+ * 15 significant digits; `decimalWire: "string"` sends the canonical string (ADR-0019
21
+ * Amendment 1). The generated route passes them; absent, rows are sent as read.
22
+ */
23
+ readonly decimalColumns?: readonly string[];
24
+ /** `wire.decimals`. Default `native`. */
25
+ readonly decimalWire?: DecimalWireMode;
26
+ /** `wire.nullMembers` for the members of the value objects under `valueObjects`. Default `native`. */
27
+ readonly nullMembers?: NullMembersMode;
28
+ /** The jsonb columns that hold a value object (or an array / map of them), by column name. */
29
+ readonly valueObjects?: Readonly<Record<string, ValueObjectShape>>;
30
+ }
31
+ /** Rewrite the value-object columns of a row per `mode`. `undefined` when there is nothing to do. */
32
+ export declare function nullMembersWire(shapes: Readonly<Record<string, ValueObjectShape>> | undefined, mode: NullMembersMode | undefined): ((row: unknown) => unknown) | undefined;
33
+ /** A wire mapper: `base` (timestamps), then the decimal rewrite, then the null-member rewrite. */
34
+ export declare function withWire(base: (row: unknown) => unknown, opts: WireOptions): (row: unknown) => unknown;
35
+ //# sourceMappingURL=wire-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-format.d.ts","sourceRoot":"","sources":["../src/wire-format.ts"],"names":[],"mappings":"AAaA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEvE,0BAA0B;AAC1B,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAC9D;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,yCAAyC;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;IACvC,sGAAsG;IACtG,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;IACvC,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpE;AAkCD,qGAAqG;AACrG,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,GAAG,SAAS,EAC9D,IAAI,EAAE,eAAe,GAAG,SAAS,GAChC,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAYzC;AAED,kGAAkG;AAClG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAItG"}
@@ -0,0 +1,77 @@
1
+ // The OUTPUT form of a generated REST surface: the `wire` project setting (ADR-0019 Amendment 2).
2
+ // A generated route passes the options below to a mount helper; the helper rewrites each row it
3
+ // sends. Input rules do not follow the setting (decimal bodies are parsed by the generated write
4
+ // schemas, filter operands by the filter parser).
5
+ //
6
+ // decimals `native` (default): the string the TS type holds, not canonicalized
7
+ // (`decimalToNative`); `string`: the canonical W1 string (`decimalToWire`).
8
+ // nullMembers a value object's members. `native` (default): as stored. `omit`: a null member
9
+ // is dropped. `emit`: every DECLARED member is present, `null` when unset.
10
+ //
11
+ // Which columns are decimals and which hold value objects comes from the model, never from the
12
+ // shape of a value, so the generated route carries both as static data.
13
+ import { withDecimals } from "./decimal-wire.js";
14
+ function isPlainObject(v) {
15
+ return v !== null && typeof v === "object" && !Array.isArray(v);
16
+ }
17
+ function shapeMember(value, shape, mode) {
18
+ const out = {};
19
+ if (mode === "emit") {
20
+ // Every declared member, in declaration order, null when unset.
21
+ for (const m of shape.members)
22
+ out[m] = m in value && value[m] !== undefined ? value[m] : null;
23
+ for (const [k, v] of Object.entries(value))
24
+ if (!(k in out) && v !== undefined)
25
+ out[k] = v;
26
+ }
27
+ else {
28
+ for (const [k, v] of Object.entries(value))
29
+ if (v !== null && v !== undefined)
30
+ out[k] = v;
31
+ }
32
+ for (const [name, inner] of Object.entries(shape.nested ?? {})) {
33
+ if (name in out && out[name] !== null)
34
+ out[name] = shapeValue(out[name], inner, mode);
35
+ }
36
+ return out;
37
+ }
38
+ /** Apply `mode` to a stored value object, an array of them, or (for `shape.map`) a map of them. */
39
+ function shapeValue(value, shape, mode) {
40
+ if (Array.isArray(value))
41
+ return value.map((el) => shapeValue(el, shape, mode));
42
+ if (!isPlainObject(value))
43
+ return value;
44
+ if (shape.map === true) {
45
+ // Keys are arbitrary text, never compared with the value object's member names.
46
+ const out = {};
47
+ for (const [k, el] of Object.entries(value))
48
+ out[k] = isPlainObject(el) ? shapeMember(el, shape, mode) : el;
49
+ return out;
50
+ }
51
+ return shapeMember(value, shape, mode);
52
+ }
53
+ /** Rewrite the value-object columns of a row per `mode`. `undefined` when there is nothing to do. */
54
+ export function nullMembersWire(shapes, mode) {
55
+ if (shapes === undefined || mode === undefined || mode === "native")
56
+ return undefined;
57
+ const entries = Object.entries(shapes);
58
+ if (entries.length === 0)
59
+ return undefined;
60
+ return (row) => {
61
+ if (!isPlainObject(row))
62
+ return row;
63
+ const out = { ...row };
64
+ for (const [column, shape] of entries) {
65
+ if (column in out && out[column] !== null && out[column] !== undefined)
66
+ out[column] = shapeValue(out[column], shape, mode);
67
+ }
68
+ return out;
69
+ };
70
+ }
71
+ /** A wire mapper: `base` (timestamps), then the decimal rewrite, then the null-member rewrite. */
72
+ export function withWire(base, opts) {
73
+ const decimals = withDecimals(base, opts.decimalColumns, opts.decimalWire);
74
+ const members = nullMembersWire(opts.valueObjects, opts.nullMembers);
75
+ return members === undefined ? decimals : (row) => members(decimals(row));
76
+ }
77
+ //# sourceMappingURL=wire-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-format.js","sourceRoot":"","sources":["../src/wire-format.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaobjectsdev/runtime-ts",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Node-side runtime helpers for MetaObjects: Fastify route builders, Drizzle filter/sort integration, Kysely drivers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -64,8 +64,8 @@
64
64
  "access": "public"
65
65
  },
66
66
  "dependencies": {
67
- "@metaobjectsdev/metadata": "1.1.1",
68
- "@metaobjectsdev/render": "1.1.1",
67
+ "@metaobjectsdev/metadata": "1.1.2",
68
+ "@metaobjectsdev/render": "1.1.2",
69
69
  "qs": "^6.13.0"
70
70
  },
71
71
  "peerDependencies": {
@@ -125,20 +125,39 @@ export function decimalToWire(value: unknown): unknown {
125
125
  }
126
126
 
127
127
  /**
128
- * Rewrite the values under `columns` to their canonical string. Returns `undefined` when there is
129
- * nothing to do. Which keys are decimals comes from the caller (the generated route passes the
130
- * names of the entity's `field.decimal` fields), never from the shape of a value: an integer
131
- * column is not a decimal because it is a number.
128
+ * The `native` output form (`wire.decimals: native`, ADR-0019 Amendment 2): the string the
129
+ * in-process type holds, NOT canonicalized. A string a driver handed back (Postgres `numeric`,
130
+ * MySQL `DECIMAL`, SQLite text) passes through as it is (`"12.50"` stays `"12.50"`), a number
131
+ * (a SQLite or D1 REAL or INTEGER) is rendered at 15 significant digits (W4, because the TS type
132
+ * is `string`), a bigint is its digits, and an array is rewritten element by element.
133
+ */
134
+ export function decimalToNative(value: unknown): unknown {
135
+ if (Array.isArray(value)) return value.map(decimalToNative);
136
+ if (typeof value === "number") return decimalFromDouble15(value) ?? value;
137
+ if (typeof value === "bigint") return value.toString();
138
+ return value;
139
+ }
140
+
141
+ /** How a decimal is written: `native` (default) or the canonical `string` (`wire.decimals`). */
142
+ export type DecimalWireMode = "native" | "string";
143
+
144
+ /**
145
+ * Rewrite the values under `columns` to their wire form (`mode`, default `native`). Returns
146
+ * `undefined` when there is nothing to do. Which keys are decimals comes from the caller (the
147
+ * generated route passes the names of the entity's `field.decimal` fields), never from the shape
148
+ * of a value: an integer column is not a decimal because it is a number.
132
149
  */
133
150
  export function decimalWire(
134
151
  columns: readonly string[] | undefined,
152
+ mode: DecimalWireMode = "native",
135
153
  ): ((row: unknown) => unknown) | undefined {
136
154
  if (columns === undefined || columns.length === 0) return undefined;
155
+ const convert = mode === "string" ? decimalToWire : decimalToNative;
137
156
  return (row) => {
138
157
  if (row === null || typeof row !== "object") return row;
139
158
  const out = { ...(row as Record<string, unknown>) };
140
159
  for (const c of columns) {
141
- if (c in out) out[c] = decimalToWire(out[c]);
160
+ if (c in out) out[c] = convert(out[c]);
142
161
  }
143
162
  return out;
144
163
  };
@@ -148,7 +167,8 @@ export function decimalWire(
148
167
  export function withDecimals(
149
168
  base: (row: unknown) => unknown,
150
169
  columns: readonly string[] | undefined,
170
+ mode: DecimalWireMode = "native",
151
171
  ): (row: unknown) => unknown {
152
- const decimals = decimalWire(columns);
172
+ const decimals = decimalWire(columns, mode);
153
173
  return decimals === undefined ? base : (row) => decimals(base(row));
154
174
  }
@@ -29,13 +29,15 @@ export type { FilterAllowlist, SortAllowlist } from "./filter-allowlist.js";
29
29
  import { parseFilterParams, parsePageBound, FilterParseError } from "./filter-parser.js";
30
30
  import { isTruthyFlag, contractErrorCode, coerceIdForColumn, firstRow, extractRowCount } from "./util.js";
31
31
  import { timestampWire } from "../timestamp-wire.js";
32
- import { withDecimals } from "../decimal-wire.js";
32
+ import { withWire, type WireOptions } from "../wire-format.js";
33
33
  import { supportsReturning, type SqlDialect } from "../sql-dialect.js";
34
34
  import { withContractErrorHandler } from "./route-error-handler.js";
35
35
  import { validationErrorBody } from "../route-errors.js";
36
36
  export { isTruthyFlag, contractErrorCode, parseId, coerceIdForColumn } from "./util.js";
37
37
  export { timestampWire, canonicalTimestamp } from "../timestamp-wire.js";
38
- export { decimalWire, withDecimals, canonicalDecimal, parseDecimalInput, parseDecimalOperand } from "../decimal-wire.js";
38
+ export { decimalWire, withDecimals, decimalToNative, canonicalDecimal, parseDecimalInput, parseDecimalOperand } from "../decimal-wire.js";
39
+ export { withWire, nullMembersWire } from "../wire-format.js";
40
+ export type { WireOptions, ValueObjectShape, NullMembersMode } from "../wire-format.js";
39
41
 
40
42
  // ---------------------------------------------------------------------------
41
43
  // Loose types — we don't bind to a specific Drizzle backend so the helper
@@ -49,7 +51,7 @@ type AnyTable = any;
49
51
 
50
52
  export type CrudVerb = "list" | "get" | "create" | "update" | "delete";
51
53
 
52
- export interface CrudRoutesOptions {
54
+ export interface CrudRoutesOptions extends WireOptions {
53
55
  fastify: FastifyInstance;
54
56
  /** REST resource path, e.g. "/subscribers". */
55
57
  path: string;
@@ -86,13 +88,6 @@ export interface CrudRoutesOptions {
86
88
  updateMethod?: "patch" | "put";
87
89
  filterAllowlist?: FilterAllowlist;
88
90
  sortAllowlist?: SortAllowlist;
89
- /**
90
- * The names of the entity's `field.decimal` fields. A decimal is a canonical string on the
91
- * wire on every dialect (ADR-0019 Amendment 1): Postgres and MySQL return the column's scale
92
- * (`"100.5000"`) and SQLite hands back a number, so each row the routes send is rewritten
93
- * under these keys. The generated route passes them; absent, rows are sent as read.
94
- */
95
- decimalColumns?: readonly string[];
96
91
  /** Dialect — required if filterAllowlist or sortAllowlist is set (for dialect-specific `like` lowering: SQLite lowers to GLOB to stay case-sensitive; ADR-0049). */
97
92
  dialect?: SqlDialect;
98
93
  /**
@@ -131,7 +126,7 @@ function readSource(opts: VerbOptions): AnyTable {
131
126
  * non-timestamp of the same name.
132
127
  */
133
128
  function readWire(opts: VerbOptions): (row: unknown) => unknown {
134
- return withDecimals(timestampWire(readSource(opts)), opts.decimalColumns);
129
+ return withWire(timestampWire(readSource(opts)), opts);
135
130
  }
136
131
 
137
132
  /**
@@ -140,7 +135,7 @@ function readWire(opts: VerbOptions): (row: unknown) => unknown {
140
135
  * against the union of both sources.
141
136
  */
142
137
  function echoWire(opts: VerbOptions): (row: unknown) => unknown {
143
- return withDecimals(timestampWire(opts.table, opts.readView), opts.decimalColumns);
138
+ return withWire(timestampWire(opts.table, opts.readView), opts);
144
139
  }
145
140
 
146
141
  /** #214 — after a write to the base table, re-read the row THROUGH the replica
@@ -34,7 +34,7 @@ import type { FastifyInstance, RouteShorthandOptions } from "fastify";
34
34
  import { and, eq, or, inArray } from "drizzle-orm";
35
35
  import { coerceIdForColumn } from "./util.js";
36
36
  import { timestampWire } from "../timestamp-wire.js";
37
- import { withDecimals } from "../decimal-wire.js";
37
+ import { withWire, type WireOptions } from "../wire-format.js";
38
38
  import { withContractErrorHandler } from "./route-error-handler.js";
39
39
 
40
40
  // Loose Drizzle types — the helper works across libsql / better-sqlite3 / pg.
@@ -43,7 +43,7 @@ type AnyDrizzle = any;
43
43
  // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over user's Drizzle table
44
44
  type AnyTable = any;
45
45
 
46
- export interface M2mRouteOptions {
46
+ export interface M2mRouteOptions extends WireOptions {
47
47
  fastify: FastifyInstance;
48
48
  /** Source resource path, e.g. "/posts". The route mounts at `{path}/:id/{relationName}`. */
49
49
  path: string;
@@ -61,8 +61,6 @@ export interface M2mRouteOptions {
61
61
  targetColumn: string;
62
62
  /** Target entity PK column (physical column name, e.g. "id"). Defaults to "id". */
63
63
  targetPkColumn?: string;
64
- /** The names of the TARGET entity's `field.decimal` fields, sent as canonical strings (ADR-0019 Amendment 1). */
65
- decimalColumns?: readonly string[];
66
64
  /** Undirected self-join: union both junction FK columns on read. */
67
65
  symmetric: boolean;
68
66
  /**
@@ -90,7 +88,7 @@ export function mountM2mRoute(opts: M2mRouteOptions): void {
90
88
  const route = `${opts.path}/:id/${opts.relationName}`;
91
89
  // Route-scoped contract error handler — see route-error-handler.ts.
92
90
  const ro = withContractErrorHandler(opts.routeOptions);
93
- const toWire = withDecimals(timestampWire(opts.targetTable), opts.decimalColumns);
91
+ const toWire = withWire(timestampWire(opts.targetTable), opts);
94
92
 
95
93
  opts.fastify.get(route, ro, async (req, reply) => {
96
94
  const { id } = req.params as { id: string };
@@ -6,13 +6,13 @@ import { parseFilterParams, parsePageBound, RAW_VIEW_MAX_LIMIT, FilterParseError
6
6
  import type { FilterAllowlist, SortAllowlist } from "./filter-allowlist.js";
7
7
  import { isTruthyFlag, contractErrorCode, coerceIdForColumn, rawIdLiteral, viewBaseConfig } from "./util.js";
8
8
  import { timestampWire } from "../timestamp-wire.js";
9
- import { withDecimals } from "../decimal-wire.js";
9
+ import { withWire, type WireOptions } from "../wire-format.js";
10
10
  import { withContractErrorHandler } from "./route-error-handler.js";
11
11
 
12
12
  // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over user-supplied views
13
13
  type AnyView = any;
14
14
 
15
- export interface MountReadOnlyOptions {
15
+ export interface MountReadOnlyOptions extends WireOptions {
16
16
  readonly fastify: FastifyInstance;
17
17
  readonly path: string;
18
18
  // biome-ignore lint/suspicious/noExplicitAny: dynamic Drizzle client
@@ -50,14 +50,6 @@ export interface MountReadOnlyOptions {
50
50
  readonly itemRoutes?: boolean;
51
51
  /** The noun in the 405 message, which is free prose. Default "projection". */
52
52
  readonly resource?: "projection" | "report";
53
- /**
54
- * The names of the view's `field.decimal` fields. A decimal is a canonical string on the wire
55
- * on every dialect (ADR-0019 Amendment 1): Postgres and MySQL return the column's scale
56
- * (`"100.5000"`), and SQLite hands back a number, a REAL for a computed one (a report's ratio,
57
- * average or sum). Each row is rewritten under these keys. The generated route passes them;
58
- * absent, rows are sent as read. Default none.
59
- */
60
- readonly decimalColumns?: readonly string[];
61
53
  }
62
54
 
63
55
  const rejectMutation = (resource: string) => async (
@@ -160,7 +152,7 @@ export function mountReadOnlyCrudRoutes(opts: MountReadOnlyOptions): void {
160
152
  const useRawSql = isEmptyColumnView(view) && !!viewName;
161
153
  // The raw-SQL branch has no declared columns, so nothing names a timestamp there.
162
154
  const timestamps = timestampWire(view);
163
- const toWire = withDecimals(timestamps, opts.decimalColumns);
155
+ const toWire = withWire(timestamps, opts);
164
156
 
165
157
  // ── List ──────────────────────────────────────────────────────────────────
166
158
  fastify.get(path, ro, async (req, reply) => {
package/src/hono/index.ts CHANGED
@@ -45,7 +45,7 @@ export type {
45
45
  import { isTruthyFlag, coerceIdForColumn, firstRow, extractRowCount } from "../drizzle-fastify/util.js";
46
46
  import { supportsReturning, type SqlDialect } from "../sql-dialect.js";
47
47
  import { timestampWire } from "../timestamp-wire.js";
48
- import { withDecimals } from "../decimal-wire.js";
48
+ import { withWire, type WireOptions } from "../wire-format.js";
49
49
  // Every handler below is wrapped in guardRoute (an unexpected error answers
50
50
  // `500 { error: "internal" }`, logged server-side) and reads its body through
51
51
  // readJsonBody (a malformed body answers `400 { error: "invalid_json" }`).
@@ -54,7 +54,9 @@ import { guardRoute, readJsonBody } from "./route-guard.js";
54
54
  // shared (deprecated) helper so the three adapters can't silently diverge.
55
55
  export { parseId } from "../drizzle-fastify/util.js";
56
56
  export { timestampWire, canonicalTimestamp } from "../timestamp-wire.js";
57
- export { decimalWire, withDecimals, canonicalDecimal, parseDecimalInput, parseDecimalOperand } from "../decimal-wire.js";
57
+ export { decimalWire, withDecimals, decimalToNative, canonicalDecimal, parseDecimalInput, parseDecimalOperand } from "../decimal-wire.js";
58
+ export { withWire, nullMembersWire } from "../wire-format.js";
59
+ export type { WireOptions, ValueObjectShape, NullMembersMode } from "../wire-format.js";
58
60
 
59
61
  // ---------------------------------------------------------------------------
60
62
  // Loose types — we don't bind to a specific Drizzle backend so the helper
@@ -70,7 +72,7 @@ type AnyHono = Hono<any, any, any>;
70
72
 
71
73
  export type CrudVerb = "list" | "get" | "create" | "update" | "delete";
72
74
 
73
- export interface CrudRoutesOptions {
75
+ export interface CrudRoutesOptions extends WireOptions {
74
76
  /** Hono app instance. Bindings type is the consumer's — kept generic here. */
75
77
  app: AnyHono;
76
78
  /** REST resource path, e.g. "/subscribers". */
@@ -106,13 +108,6 @@ export interface CrudRoutesOptions {
106
108
  updateMethod?: "patch" | "put";
107
109
  filterAllowlist?: FilterAllowlist;
108
110
  sortAllowlist?: SortAllowlist;
109
- /**
110
- * The names of the entity's `field.decimal` fields. A decimal is a canonical string on the
111
- * wire on every dialect (ADR-0019 Amendment 1): Postgres and MySQL return the column's scale
112
- * (`"100.5000"`) and SQLite hands back a number, so each row the routes send is rewritten
113
- * under these keys. The generated route passes them; absent, rows are sent as read.
114
- */
115
- decimalColumns?: readonly string[];
116
111
  /** Dialect — required if filterAllowlist or sortAllowlist is set (for dialect-specific `like` lowering: SQLite lowers to GLOB to stay case-sensitive; ADR-0049). */
117
112
  dialect?: SqlDialect;
118
113
  }
@@ -159,7 +154,7 @@ function readSource(opts: VerbOptions): AnyTable {
159
154
  * non-timestamp of the same name.
160
155
  */
161
156
  function readWire(opts: VerbOptions): (row: unknown) => unknown {
162
- return withDecimals(timestampWire(readSource(opts)), opts.decimalColumns);
157
+ return withWire(timestampWire(readSource(opts)), opts);
163
158
  }
164
159
 
165
160
  /**
@@ -168,7 +163,7 @@ function readWire(opts: VerbOptions): (row: unknown) => unknown {
168
163
  * against the union of both sources.
169
164
  */
170
165
  function echoWire(opts: VerbOptions): (row: unknown) => unknown {
171
- return withDecimals(timestampWire(opts.table, opts.readView), opts.decimalColumns);
166
+ return withWire(timestampWire(opts.table, opts.readView), opts);
172
167
  }
173
168
 
174
169
  /** Re-read a just-written row through the replica view so the response carries the
@@ -13,7 +13,7 @@ import type {
13
13
  } from "../drizzle-fastify/filter-allowlist.js";
14
14
  import { isTruthyFlag, coerceIdForColumn, rawIdLiteral, contractErrorCode, viewBaseConfig } from "../drizzle-fastify/util.js";
15
15
  import { timestampWire } from "../timestamp-wire.js";
16
- import { withDecimals } from "../decimal-wire.js";
16
+ import { withWire, type WireOptions } from "../wire-format.js";
17
17
  // An unexpected error on a mounted route answers `500 { error: "internal" }`.
18
18
  import { guardRoute } from "./route-guard.js";
19
19
 
@@ -22,7 +22,7 @@ type AnyView = any;
22
22
  // biome-ignore lint/suspicious/noExplicitAny: generic Hono app
23
23
  type AnyHono = Hono<any, any, any>;
24
24
 
25
- export interface MountReadOnlyOptions {
25
+ export interface MountReadOnlyOptions extends WireOptions {
26
26
  readonly app: AnyHono;
27
27
  readonly path: string;
28
28
  // biome-ignore lint/suspicious/noExplicitAny: dynamic Drizzle client
@@ -49,14 +49,6 @@ export interface MountReadOnlyOptions {
49
49
  readonly itemRoutes?: boolean;
50
50
  /** The noun in the 405 message, which is free prose. Default "projection". */
51
51
  readonly resource?: "projection" | "report";
52
- /**
53
- * The names of the view's `field.decimal` fields. A decimal is a canonical string on the wire
54
- * on every dialect (ADR-0019 Amendment 1): Postgres and MySQL return the column's scale
55
- * (`"100.5000"`), and SQLite hands back a number, a REAL for a computed one (a report's ratio,
56
- * average or sum). Each row is rewritten under these keys. The generated route passes them;
57
- * absent, rows are sent as read. Default none.
58
- */
59
- readonly decimalColumns?: readonly string[];
60
52
  }
61
53
 
62
54
  function resolveViewName(view: AnyView): string | undefined {
@@ -139,7 +131,7 @@ export function mountReadOnlyCrudRoutes(opts: MountReadOnlyOptions): void {
139
131
  const useRawSql = isEmptyColumnView(view) && !!viewName;
140
132
  // The raw-SQL branch has no declared columns, so nothing names a timestamp there.
141
133
  const timestamps = timestampWire(view);
142
- const toWire = withDecimals(timestamps, opts.decimalColumns);
134
+ const toWire = withWire(timestamps, opts);
143
135
 
144
136
  // ── List ──────────────────────────────────────────────────────────────────
145
137
  app.get(path, guardRoute(async (c) => {
@@ -0,0 +1,103 @@
1
+ // The OUTPUT form of a generated REST surface: the `wire` project setting (ADR-0019 Amendment 2).
2
+ // A generated route passes the options below to a mount helper; the helper rewrites each row it
3
+ // sends. Input rules do not follow the setting (decimal bodies are parsed by the generated write
4
+ // schemas, filter operands by the filter parser).
5
+ //
6
+ // decimals `native` (default): the string the TS type holds, not canonicalized
7
+ // (`decimalToNative`); `string`: the canonical W1 string (`decimalToWire`).
8
+ // nullMembers a value object's members. `native` (default): as stored. `omit`: a null member
9
+ // is dropped. `emit`: every DECLARED member is present, `null` when unset.
10
+ //
11
+ // Which columns are decimals and which hold value objects comes from the model, never from the
12
+ // shape of a value, so the generated route carries both as static data.
13
+
14
+ import { withDecimals, type DecimalWireMode } from "./decimal-wire.js";
15
+
16
+ /** `wire.nullMembers`. */
17
+ export type NullMembersMode = "native" | "emit" | "omit";
18
+
19
+ /**
20
+ * The declared shape of a value object held by a jsonb column: its member names, and the shape
21
+ * of any member that is itself a value object. `map` marks a `field.map` of value objects (the
22
+ * column's value is an object keyed by arbitrary text, each value a value object). An array
23
+ * (`isArray`) needs no flag: the walk reads the value's own shape.
24
+ */
25
+ export interface ValueObjectShape {
26
+ readonly members: readonly string[];
27
+ readonly map?: boolean;
28
+ readonly nested?: Readonly<Record<string, ValueObjectShape>>;
29
+ }
30
+
31
+ /** The wire options every read-side mount takes beside its other options. */
32
+ export interface WireOptions {
33
+ /**
34
+ * The names of the entity's `field.decimal` fields. Each row sent is rewritten under these
35
+ * keys: `native` (default) leaves the string a driver returned and renders a SQLite number at
36
+ * 15 significant digits; `decimalWire: "string"` sends the canonical string (ADR-0019
37
+ * Amendment 1). The generated route passes them; absent, rows are sent as read.
38
+ */
39
+ readonly decimalColumns?: readonly string[];
40
+ /** `wire.decimals`. Default `native`. */
41
+ readonly decimalWire?: DecimalWireMode;
42
+ /** `wire.nullMembers` for the members of the value objects under `valueObjects`. Default `native`. */
43
+ readonly nullMembers?: NullMembersMode;
44
+ /** The jsonb columns that hold a value object (or an array / map of them), by column name. */
45
+ readonly valueObjects?: Readonly<Record<string, ValueObjectShape>>;
46
+ }
47
+
48
+ function isPlainObject(v: unknown): v is Record<string, unknown> {
49
+ return v !== null && typeof v === "object" && !Array.isArray(v);
50
+ }
51
+
52
+ function shapeMember(value: Record<string, unknown>, shape: ValueObjectShape, mode: NullMembersMode): Record<string, unknown> {
53
+ const out: Record<string, unknown> = {};
54
+ if (mode === "emit") {
55
+ // Every declared member, in declaration order, null when unset.
56
+ for (const m of shape.members) out[m] = m in value && value[m] !== undefined ? value[m] : null;
57
+ for (const [k, v] of Object.entries(value)) if (!(k in out) && v !== undefined) out[k] = v;
58
+ } else {
59
+ for (const [k, v] of Object.entries(value)) if (v !== null && v !== undefined) out[k] = v;
60
+ }
61
+ for (const [name, inner] of Object.entries(shape.nested ?? {})) {
62
+ if (name in out && out[name] !== null) out[name] = shapeValue(out[name], inner, mode);
63
+ }
64
+ return out;
65
+ }
66
+
67
+ /** Apply `mode` to a stored value object, an array of them, or (for `shape.map`) a map of them. */
68
+ function shapeValue(value: unknown, shape: ValueObjectShape, mode: NullMembersMode): unknown {
69
+ if (Array.isArray(value)) return value.map((el) => shapeValue(el, shape, mode));
70
+ if (!isPlainObject(value)) return value;
71
+ if (shape.map === true) {
72
+ // Keys are arbitrary text, never compared with the value object's member names.
73
+ const out: Record<string, unknown> = {};
74
+ for (const [k, el] of Object.entries(value)) out[k] = isPlainObject(el) ? shapeMember(el, shape, mode) : el;
75
+ return out;
76
+ }
77
+ return shapeMember(value, shape, mode);
78
+ }
79
+
80
+ /** Rewrite the value-object columns of a row per `mode`. `undefined` when there is nothing to do. */
81
+ export function nullMembersWire(
82
+ shapes: Readonly<Record<string, ValueObjectShape>> | undefined,
83
+ mode: NullMembersMode | undefined,
84
+ ): ((row: unknown) => unknown) | undefined {
85
+ if (shapes === undefined || mode === undefined || mode === "native") return undefined;
86
+ const entries = Object.entries(shapes);
87
+ if (entries.length === 0) return undefined;
88
+ return (row) => {
89
+ if (!isPlainObject(row)) return row;
90
+ const out = { ...row };
91
+ for (const [column, shape] of entries) {
92
+ if (column in out && out[column] !== null && out[column] !== undefined) out[column] = shapeValue(out[column], shape, mode);
93
+ }
94
+ return out;
95
+ };
96
+ }
97
+
98
+ /** A wire mapper: `base` (timestamps), then the decimal rewrite, then the null-member rewrite. */
99
+ export function withWire(base: (row: unknown) => unknown, opts: WireOptions): (row: unknown) => unknown {
100
+ const decimals = withDecimals(base, opts.decimalColumns, opts.decimalWire);
101
+ const members = nullMembersWire(opts.valueObjects, opts.nullMembers);
102
+ return members === undefined ? decimals : (row) => members(decimals(row));
103
+ }