@metaobjectsdev/runtime-ts 0.8.1 → 0.9.0
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/dist/drizzle-fastify/index.d.ts +1 -1
- package/dist/drizzle-fastify/index.d.ts.map +1 -1
- package/dist/drizzle-fastify/index.js +36 -10
- package/dist/drizzle-fastify/index.js.map +1 -1
- package/dist/drizzle-fastify/mount-read-only.d.ts.map +1 -1
- package/dist/drizzle-fastify/mount-read-only.js +11 -5
- package/dist/drizzle-fastify/mount-read-only.js.map +1 -1
- package/dist/drizzle-fastify/util.d.ts +1 -0
- package/dist/drizzle-fastify/util.d.ts.map +1 -1
- package/dist/drizzle-fastify/util.js +23 -0
- package/dist/drizzle-fastify/util.js.map +1 -1
- package/dist/extract-object.d.ts +44 -0
- package/dist/extract-object.d.ts.map +1 -0
- package/dist/extract-object.js +284 -0
- package/dist/extract-object.js.map +1 -0
- package/dist/fastify/index.d.ts +9 -0
- package/dist/fastify/index.d.ts.map +1 -1
- package/dist/fastify/index.js +43 -3
- package/dist/fastify/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/validator-runner.js +2 -2
- package/dist/validator-runner.js.map +1 -1
- package/package.json +3 -2
- package/src/drizzle-fastify/index.ts +33 -10
- package/src/drizzle-fastify/mount-read-only.ts +12 -6
- package/src/drizzle-fastify/util.ts +24 -0
- package/src/extract-object.ts +367 -0
- package/src/fastify/index.ts +55 -3
- package/src/index.ts +10 -0
- package/src/validator-runner.ts +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-object.js","sourceRoot":"","sources":["../src/extract-object.ts"],"names":[],"mappings":"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"}
|
package/dist/fastify/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { FastifyInstance } from "fastify";
|
|
|
2
2
|
import type { ZodTypeAny } from "zod";
|
|
3
3
|
import type { ObjectManager } from "../object-manager.js";
|
|
4
4
|
import type { RouteShorthandOptions } from "fastify";
|
|
5
|
+
import type { SortAllowlist } from "../drizzle-fastify/filter-allowlist.js";
|
|
5
6
|
export type CrudVerb = "list" | "get" | "create" | "update" | "delete";
|
|
6
7
|
export interface CrudRoutesOptions {
|
|
7
8
|
fastify: FastifyInstance;
|
|
@@ -39,6 +40,14 @@ export interface CrudRoutesOptions {
|
|
|
39
40
|
* uses PUT for updates.
|
|
40
41
|
*/
|
|
41
42
|
updateMethod?: "patch" | "put";
|
|
43
|
+
/**
|
|
44
|
+
* Per-entity sort allowlist (`<Entity>SortAllowlist` from codegen). When set,
|
|
45
|
+
* a `?sort=field:dir` referencing a field NOT in the allowlist (or an invalid
|
|
46
|
+
* order) is rejected with HTTP 400 `{ error: "invalid_sort" }` — matching the
|
|
47
|
+
* cross-port REST contract and the drizzle-fastify mount. When absent, `?sort`
|
|
48
|
+
* is ignored (legacy back-compat: limit/offset only).
|
|
49
|
+
*/
|
|
50
|
+
sortAllowlist?: SortAllowlist;
|
|
42
51
|
}
|
|
43
52
|
/**
|
|
44
53
|
* Mount the 5 standard REST endpoints for an entity:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAO5E,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,YAAY,EAAE,UAAU,CAAC;IACzB,yEAAyE;IACzE,YAAY,EAAE,UAAU,CAAC;IACzB;;;OAGG;IACH,EAAE,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC7B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC/B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAO7D;AAOD,KAAK,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAW3D,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAgC5D;AAmBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAM3D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAY9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA4B9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAM9D;AAMD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGpD"}
|
package/dist/fastify/index.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
// Type-only Fastify imports keep the optional-peer story clean: the .d.ts
|
|
11
11
|
// reference is needed for the public API, but at runtime there's no
|
|
12
12
|
// `require("fastify")`.
|
|
13
|
+
import qs from "qs";
|
|
14
|
+
import { isTruthyFlag, contractErrorCode } from "../drizzle-fastify/util.js";
|
|
13
15
|
const ALL_VERBS = ["list", "get", "create", "update", "delete"];
|
|
14
16
|
/**
|
|
15
17
|
* Mount the 5 standard REST endpoints for an entity:
|
|
@@ -42,16 +44,54 @@ function routeOpts(opts) {
|
|
|
42
44
|
return opts.routeOptions ?? {};
|
|
43
45
|
}
|
|
44
46
|
export function mountListRoute(opts) {
|
|
45
|
-
opts.fastify.get(opts.path, routeOpts(opts), async (req) => {
|
|
46
|
-
|
|
47
|
+
opts.fastify.get(opts.path, routeOpts(opts), async (req, reply) => {
|
|
48
|
+
// Re-parse the raw URL with qs so the top-level withCount flag and the
|
|
49
|
+
// sort=field:dir param are available regardless of Fastify's query parser.
|
|
50
|
+
const rawSearch = req.raw.url?.includes("?")
|
|
51
|
+
? req.raw.url.slice(req.raw.url.indexOf("?") + 1)
|
|
52
|
+
: "";
|
|
53
|
+
const parsed = qs.parse(rawSearch);
|
|
54
|
+
const withCount = isTruthyFlag(parsed["withCount"]);
|
|
47
55
|
const readOpts = {};
|
|
56
|
+
const { limit, offset } = req.query;
|
|
48
57
|
if (limit !== undefined)
|
|
49
58
|
readOpts.limit = Number(limit);
|
|
50
59
|
if (offset !== undefined)
|
|
51
60
|
readOpts.offset = Number(offset);
|
|
52
|
-
|
|
61
|
+
// Sort allowlist gate (cross-port REST contract). Only enforced when a
|
|
62
|
+
// sortAllowlist is configured; absent → ?sort is ignored (back-compat).
|
|
63
|
+
if (opts.sortAllowlist && typeof parsed["sort"] === "string") {
|
|
64
|
+
const sortParse = parseSort(parsed["sort"], opts.sortAllowlist);
|
|
65
|
+
if (sortParse.error) {
|
|
66
|
+
return reply.code(400).send({ error: contractErrorCode(sortParse.error) });
|
|
67
|
+
}
|
|
68
|
+
if (sortParse.orderBy)
|
|
69
|
+
readOpts.orderBy = sortParse.orderBy;
|
|
70
|
+
}
|
|
71
|
+
const om = await opts.om();
|
|
72
|
+
const rows = await om.findMany(opts.entity, undefined, readOpts);
|
|
73
|
+
if (!withCount)
|
|
74
|
+
return rows;
|
|
75
|
+
// total is the UNPAGINATED count (no limit/offset).
|
|
76
|
+
const total = await om.count(opts.entity);
|
|
77
|
+
return { rows, total };
|
|
53
78
|
});
|
|
54
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Validate a `sort=field:dir` spec against the allowlist. Mirrors the
|
|
82
|
+
* drizzle-fastify filter-parser's sort semantics + internal error codes
|
|
83
|
+
* (`sort.unknown_field` / `sort.invalid_order`) so both mounts emit the same
|
|
84
|
+
* `invalid_sort` envelope at the HTTP boundary.
|
|
85
|
+
*/
|
|
86
|
+
function parseSort(spec, sortAllowlist) {
|
|
87
|
+
const [field, orderRaw] = spec.split(":");
|
|
88
|
+
if (!field || !sortAllowlist[field])
|
|
89
|
+
return { error: "sort.unknown_field" };
|
|
90
|
+
const order = (orderRaw ?? "asc").toLowerCase();
|
|
91
|
+
if (order !== "asc" && order !== "desc")
|
|
92
|
+
return { error: "sort.invalid_order" };
|
|
93
|
+
return { orderBy: [field, order] };
|
|
94
|
+
}
|
|
55
95
|
export function mountGetRoute(opts) {
|
|
56
96
|
opts.fastify.get(`${opts.path}/:id`, routeOpts(opts), async (req, reply) => {
|
|
57
97
|
const { id } = req.params;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,4DAA4D;AAC5D,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,0EAA0E;AAC1E,oEAAoE;AACpE,wBAAwB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,5 @@ export type { FieldViewSpec, EntityViewSpec } from "./view.js";
|
|
|
6
6
|
export type { ValidationResult } from "./validator-runner.js";
|
|
7
7
|
export type { ValidationFailure } from "./errors.js";
|
|
8
8
|
export { RuntimeError, ValidationError, NotFoundError, ConstraintViolationError, MetadataError, UnsafeNameError, } from "./errors.js";
|
|
9
|
+
export { extractObject, extractSchemaFor, assemble, MAX_NEST_DEPTH, } from "./extract-object.js";
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErF,YAAY,EACV,iBAAiB,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAC/C,WAAW,EAAE,OAAO,EACpB,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EACjD,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,GACvD,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEzE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,aAAa,EACb,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErF,YAAY,EACV,iBAAiB,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAC/C,WAAW,EAAE,OAAO,EACpB,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EACjD,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,GACvD,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEzE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,aAAa,EACb,eAAe,GAChB,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,cAAc,GACf,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export { ObjectManager } from "./object-manager.js";
|
|
2
2
|
export { RuntimeError, ValidationError, NotFoundError, ConstraintViolationError, MetadataError, UnsafeNameError, } from "./errors.js";
|
|
3
|
+
// FR-010 Phase B — metadata-driven runtime extract. The descriptor-driven extract ENGINE lives in
|
|
4
|
+
// the metadata-free @metaobjectsdev/render package; this bridge wires it to the Phase A runtime
|
|
5
|
+
// object model (MetaObject.newInstance() + the MetaField SPI), mirroring the JVM `om` siting.
|
|
6
|
+
export { extractObject, extractSchemaFor, assemble, MAX_NEST_DEPTH, } from "./extract-object.js";
|
|
3
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAgBpD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,aAAa,EACb,eAAe,GAChB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAgBpD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,aAAa,EACb,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,kGAAkG;AAClG,gGAAgG;AAChG,8FAA8F;AAC9F,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,cAAc,GACf,MAAM,qBAAqB,CAAC"}
|
package/dist/validator-runner.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Pure function: NEVER throws. ObjectManager wraps a non-ok result in a ValidationError on writes;
|
|
2
2
|
// om.validate() returns the result directly.
|
|
3
|
-
import { TYPE_FIELD, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, VALIDATOR_SUBTYPE_LENGTH, VALIDATOR_SUBTYPE_REGEX, FIELD_SUBTYPE_STRING, FIELD_SUBTYPE_INT, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE, FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT, FIELD_SUBTYPE_BOOLEAN, FIELD_ATTR_REQUIRED, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_DEFAULT, VALIDATOR_ATTR_MIN, VALIDATOR_ATTR_MAX, VALIDATOR_ATTR_PATTERN, } from "@metaobjectsdev/metadata";
|
|
3
|
+
import { TYPE_FIELD, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, VALIDATOR_SUBTYPE_LENGTH, VALIDATOR_SUBTYPE_REGEX, FIELD_SUBTYPE_STRING, FIELD_SUBTYPE_INT, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE, FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT, FIELD_SUBTYPE_BOOLEAN, FIELD_SUBTYPE_UUID, FIELD_ATTR_REQUIRED, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_DEFAULT, VALIDATOR_ATTR_MIN, VALIDATOR_ATTR_MAX, VALIDATOR_ATTR_PATTERN, } from "@metaobjectsdev/metadata";
|
|
4
4
|
const NUMERIC_FIELD_SUBTYPES = new Set([
|
|
5
5
|
FIELD_SUBTYPE_INT, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE,
|
|
6
6
|
FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT,
|
|
@@ -138,7 +138,7 @@ function resolveMinLength(field) {
|
|
|
138
138
|
return undefined;
|
|
139
139
|
}
|
|
140
140
|
function checkType(subType, value) {
|
|
141
|
-
if (subType === FIELD_SUBTYPE_STRING) {
|
|
141
|
+
if (subType === FIELD_SUBTYPE_STRING || subType === FIELD_SUBTYPE_UUID) {
|
|
142
142
|
if (typeof value !== "string")
|
|
143
143
|
return `expected string`;
|
|
144
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator-runner.js","sourceRoot":"","sources":["../src/validator-runner.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,6CAA6C;AAG7C,OAAO,EACL,UAAU,EAAE,cAAc,EAC1B,0BAA0B,EAAE,wBAAwB,EAAE,uBAAuB,EAC7E,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAC3D,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,mBAAmB,EAClF,qBAAqB,
|
|
1
|
+
{"version":3,"file":"validator-runner.js","sourceRoot":"","sources":["../src/validator-runner.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": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
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",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@metaobjectsdev/metadata": "0.
|
|
56
|
+
"@metaobjectsdev/metadata": "0.9.0",
|
|
57
|
+
"@metaobjectsdev/render": "0.9.0",
|
|
57
58
|
"qs": "^6.13.0"
|
|
58
59
|
},
|
|
59
60
|
"peerDependencies": {
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
|
|
17
17
|
import type { FastifyInstance, RouteShorthandOptions } from "fastify";
|
|
18
18
|
import type { ZodTypeAny } from "zod";
|
|
19
|
-
import { eq, count, and } from "drizzle-orm";
|
|
19
|
+
import { eq, count, and, asc } from "drizzle-orm";
|
|
20
20
|
import qs from "qs";
|
|
21
21
|
import type { FilterAllowlist, SortAllowlist } from "./filter-allowlist.js";
|
|
22
22
|
export type { FilterAllowlist, SortAllowlist } from "./filter-allowlist.js";
|
|
23
23
|
import { parseFilterParams, FilterParseError } from "./filter-parser.js";
|
|
24
|
-
import { isTruthyFlag } from "./util.js";
|
|
25
|
-
export { isTruthyFlag } from "./util.js";
|
|
24
|
+
import { isTruthyFlag, contractErrorCode } from "./util.js";
|
|
25
|
+
export { isTruthyFlag, contractErrorCode } from "./util.js";
|
|
26
26
|
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
28
|
// Loose types — we don't bind to a specific Drizzle backend so the helper
|
|
@@ -109,29 +109,39 @@ export function mountListRoute(opts: VerbOptions): void {
|
|
|
109
109
|
? and(parsed.where, parsed.searchWhere)
|
|
110
110
|
: (parsed.where ?? parsed.searchWhere);
|
|
111
111
|
if (combinedWhere) { q = q.where(combinedWhere); where = combinedWhere; }
|
|
112
|
+
// Default to stable id-ascending order when the caller specifies no
|
|
113
|
+
// sort — the cross-port contract asserts deterministic ordering for
|
|
114
|
+
// pagination + filter scenarios (Postgres otherwise returns rows in an
|
|
115
|
+
// unspecified order).
|
|
112
116
|
if (parsed.orderBy) q = q.orderBy(...parsed.orderBy);
|
|
117
|
+
else if (opts.table.id !== undefined) q = q.orderBy(asc(opts.table.id));
|
|
113
118
|
if (parsed.limit !== undefined) q = q.limit(parsed.limit);
|
|
114
119
|
if (parsed.offset !== undefined) q = q.offset(parsed.offset);
|
|
115
120
|
} else {
|
|
116
121
|
// Legacy path — no allowlists configured. Only limit/offset.
|
|
117
122
|
const { limit, offset } = req.query as { limit?: string; offset?: string };
|
|
123
|
+
if (opts.table.id !== undefined) q = q.orderBy(asc(opts.table.id));
|
|
118
124
|
if (limit !== undefined) q = q.limit(Number(limit));
|
|
119
125
|
if (offset !== undefined) q = q.offset(Number(offset));
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
|
|
128
|
+
// Await the query directly rather than calling `.all()`: the
|
|
129
|
+
// drizzle-orm node-postgres query builder is thenable but has no `.all()`
|
|
130
|
+
// method (that is a libsql/better-sqlite3-only API). Awaiting works on
|
|
131
|
+
// both dialects and is what makes this helper genuinely Postgres-capable.
|
|
132
|
+
const rows = await q;
|
|
123
133
|
|
|
124
134
|
if (!withCount) return rows;
|
|
125
135
|
|
|
126
136
|
// Count query: same WHERE, no limit/offset/orderBy.
|
|
127
137
|
let cq = opts.db.select({ c: count() }).from(opts.table).$dynamic();
|
|
128
138
|
if (where) cq = cq.where(where);
|
|
129
|
-
const countRow = (await cq
|
|
139
|
+
const countRow = (await cq)[0] as { c: number } | undefined;
|
|
130
140
|
const total = countRow?.c ?? 0;
|
|
131
141
|
return { rows, total };
|
|
132
142
|
} catch (err) {
|
|
133
143
|
if (err instanceof FilterParseError) {
|
|
134
|
-
return reply.code(400).send({ error: err.code, ...(err.details ?? {}) });
|
|
144
|
+
return reply.code(400).send({ error: contractErrorCode(err.code), ...(err.details ?? {}) });
|
|
135
145
|
}
|
|
136
146
|
throw err;
|
|
137
147
|
}
|
|
@@ -141,11 +151,15 @@ export function mountListRoute(opts: VerbOptions): void {
|
|
|
141
151
|
export function mountGetRoute(opts: VerbOptions): void {
|
|
142
152
|
opts.fastify.get(`${opts.path}/:id`, routeOpts(opts), async (req, reply) => {
|
|
143
153
|
const { id } = req.params as { id: string };
|
|
144
|
-
|
|
154
|
+
// Await + take the first row rather than `.get()` — `.get()` is a
|
|
155
|
+
// libsql/better-sqlite3-only method; the node-postgres builder is thenable
|
|
156
|
+
// but has no `.get()`. Awaiting works on both dialects.
|
|
157
|
+
const rows = await opts.db
|
|
145
158
|
.select()
|
|
146
159
|
.from(opts.table)
|
|
147
160
|
.where(eq(opts.table.id, parseId(id)))
|
|
148
|
-
.
|
|
161
|
+
.limit(1);
|
|
162
|
+
const row = (rows as unknown[])[0];
|
|
149
163
|
return row ?? reply.code(404).send({ error: "not_found" });
|
|
150
164
|
});
|
|
151
165
|
}
|
|
@@ -182,11 +196,20 @@ export function mountUpdateRoute(opts: VerbOptions): void {
|
|
|
182
196
|
};
|
|
183
197
|
const path = `${opts.path}/:id`;
|
|
184
198
|
const ro = routeOpts(opts);
|
|
199
|
+
// Cross-port REST contract (FR-008): the update verb is reachable via BOTH
|
|
200
|
+
// PATCH and PUT, each routed to the same handler (the Java/Kotlin/C#/Python
|
|
201
|
+
// controllers map both methods to the update path). Mount both by default so
|
|
202
|
+
// the generated TS routes match. `updateMethod` remains an explicit
|
|
203
|
+
// single-verb override for a consumer that wants to restrict the surface.
|
|
185
204
|
// biome-ignore lint/suspicious/noExplicitAny: handler signature is generic
|
|
205
|
+
const h = handler as any;
|
|
186
206
|
if (opts.updateMethod === "put") {
|
|
187
|
-
opts.fastify.put(path, ro,
|
|
207
|
+
opts.fastify.put(path, ro, h);
|
|
208
|
+
} else if (opts.updateMethod === "patch") {
|
|
209
|
+
opts.fastify.patch(path, ro, h);
|
|
188
210
|
} else {
|
|
189
|
-
opts.fastify.patch(path, ro,
|
|
211
|
+
opts.fastify.patch(path, ro, h);
|
|
212
|
+
opts.fastify.put(path, ro, h);
|
|
190
213
|
}
|
|
191
214
|
}
|
|
192
215
|
|
|
@@ -3,7 +3,7 @@ import { sql, eq, and, count } from "drizzle-orm";
|
|
|
3
3
|
import qs from "qs";
|
|
4
4
|
import { parseFilterParams, FilterParseError } from "./filter-parser.js";
|
|
5
5
|
import type { FilterAllowlist, SortAllowlist } from "./filter-allowlist.js";
|
|
6
|
-
import { isTruthyFlag } from "./util.js";
|
|
6
|
+
import { isTruthyFlag, contractErrorCode } from "./util.js";
|
|
7
7
|
|
|
8
8
|
// biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over user-supplied views
|
|
9
9
|
type AnyView = any;
|
|
@@ -140,19 +140,23 @@ export function mountReadOnlyCrudRoutes(opts: MountReadOnlyOptions): void {
|
|
|
140
140
|
if (result.orderBy) q = q.orderBy(...result.orderBy);
|
|
141
141
|
if (result.limit !== undefined) q = q.limit(result.limit);
|
|
142
142
|
if (result.offset !== undefined) q = q.offset(result.offset);
|
|
143
|
-
|
|
143
|
+
// Await directly — `.all()` is libsql/better-sqlite3-only; the
|
|
144
|
+
// node-postgres builder is thenable. (The useRawSql branch above keeps
|
|
145
|
+
// db.all(sql.raw(...)) because that is the libsql raw-exec API, only
|
|
146
|
+
// reachable for `.existing()` empty-column views which are sqlite-only.)
|
|
147
|
+
const rows = await q;
|
|
144
148
|
|
|
145
149
|
if (!withCount) return rows;
|
|
146
150
|
|
|
147
151
|
// Count query: same WHERE, no limit/offset/orderBy.
|
|
148
152
|
let cq = db.select({ c: count() }).from(view);
|
|
149
153
|
if (combinedWhere) cq = cq.where(combinedWhere);
|
|
150
|
-
const countRow = (await cq
|
|
154
|
+
const countRow = (await cq)[0] as { c: number } | undefined;
|
|
151
155
|
const total = countRow?.c ?? 0;
|
|
152
156
|
return { rows, total };
|
|
153
157
|
} catch (err) {
|
|
154
158
|
if (err instanceof FilterParseError) {
|
|
155
|
-
reply.code(400).send({ error: err.code, message: err.message });
|
|
159
|
+
reply.code(400).send({ error: contractErrorCode(err.code), message: err.message });
|
|
156
160
|
return;
|
|
157
161
|
}
|
|
158
162
|
throw err;
|
|
@@ -174,9 +178,11 @@ export function mountReadOnlyCrudRoutes(opts: MountReadOnlyOptions): void {
|
|
|
174
178
|
}
|
|
175
179
|
// biome-ignore lint/suspicious/noExplicitAny: Drizzle table/view column ref
|
|
176
180
|
const colRef = (view as any)[idCol];
|
|
177
|
-
|
|
181
|
+
// Await + first row rather than `.get()` (libsql/better-sqlite3-only).
|
|
182
|
+
const rows = await db.select().from(view).where(
|
|
178
183
|
colRef !== undefined ? eq(colRef, Number(id)) : undefined
|
|
179
|
-
).
|
|
184
|
+
).limit(1);
|
|
185
|
+
const row = (rows as unknown[])[0];
|
|
180
186
|
return row ?? reply.code(404).send({ error: "not_found" });
|
|
181
187
|
});
|
|
182
188
|
|
|
@@ -8,3 +8,27 @@ export function isTruthyFlag(v: unknown): boolean {
|
|
|
8
8
|
if (typeof v === "boolean") return v;
|
|
9
9
|
return String(v) === "1";
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
// Cross-port REST contract error envelope (FR-008/009). The internal
|
|
13
|
+
// FilterParseError carries fine-grained dotted codes (filter.unknown_field,
|
|
14
|
+
// sort.unknown_field, ...); the HTTP wire contract that every port's generated
|
|
15
|
+
// API must emit uses the coarser invalid_filter_field / invalid_filter_op /
|
|
16
|
+
// invalid_filter_value / invalid_sort envelope. Map at the HTTP boundary so the
|
|
17
|
+
// internal codes stay stable while the response conforms cross-port.
|
|
18
|
+
export function contractErrorCode(internal: string): string {
|
|
19
|
+
switch (internal) {
|
|
20
|
+
case "filter.unknown_field":
|
|
21
|
+
return "invalid_filter_field";
|
|
22
|
+
case "filter.unsupported_op":
|
|
23
|
+
return "invalid_filter_op";
|
|
24
|
+
case "filter.invalid_value":
|
|
25
|
+
return "invalid_filter_value";
|
|
26
|
+
case "sort.unknown_field":
|
|
27
|
+
case "sort.invalid_order":
|
|
28
|
+
return "invalid_sort";
|
|
29
|
+
default:
|
|
30
|
+
// Implementation-specific guards (nesting depth, in-list size, leading
|
|
31
|
+
// wildcard) are not part of the cross-port contract surface; pass through.
|
|
32
|
+
return internal;
|
|
33
|
+
}
|
|
34
|
+
}
|