@stonyx/orm 0.3.2-alpha.74 → 0.3.2-alpha.76
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/README.md +59 -20
- package/dist/orm-request.js +37 -18
- package/package.json +1 -1
- package/src/orm-request.ts +37 -18
package/README.md
CHANGED
|
@@ -951,7 +951,18 @@ per-record filter. An input you cannot identify must **deny**.
|
|
|
951
951
|
`methodAccessMap[request.method]`: it would ask a different question on a
|
|
952
952
|
write route than on a read route, which is the two-vocabularies failure
|
|
953
953
|
`createLinkageFilter` exists to prevent. An unresolvable class
|
|
954
|
-
(`getAccess()` → `undefined`) and a predicate that throws both **deny**.
|
|
954
|
+
(`getAccess()` → `undefined`) and a predicate that throws both **deny**.
|
|
955
|
+
|
|
956
|
+
**What the two write surfaces cost before #235, measured rather than
|
|
957
|
+
described:** one HTTP verb defeated the filter on the same record. On
|
|
958
|
+
`dev @ 8dda5d6`, seconds apart, with no query string and no relationship
|
|
959
|
+
route, `GET /animals/1` returned `owner.data: null` while `PATCH /animals/1`
|
|
960
|
+
returned **200 naming angela**. Any caller who could read a record could also
|
|
961
|
+
write it and be handed the id the read withheld. That consequence is kept here
|
|
962
|
+
after the fix, and stated as a measurement, because **naming the two handlers
|
|
963
|
+
is not a substitute for it** — a reader who is told only that `POST` and
|
|
964
|
+
`PATCH` are now covered cannot tell what was wrong, and a reviewer cannot tell
|
|
965
|
+
whether the fix addressed it. A
|
|
955
966
|
filtered-out relationship is **indistinguishable from a genuinely empty one** —
|
|
956
967
|
an emptied `hasMany` is `data: []` and an emptied `belongsTo` is `data: null`,
|
|
957
968
|
both **keeping their `links`**, which are built from the serialized record's
|
|
@@ -983,20 +994,30 @@ per-record filter. An input you cannot identify must **deny**.
|
|
|
983
994
|
*permitted* related record, which is recorded in the release notes as a
|
|
984
995
|
breaking change.
|
|
985
996
|
|
|
986
|
-
**Not yet covered
|
|
987
|
-
withhold
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
[#
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
`{
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
997
|
+
**Not yet covered by #235. Each still publishes ids the surfaces above
|
|
998
|
+
withhold, except where its own owning issue has since closed it — the first
|
|
999
|
+
entry names an issue that is in flight as this is written:**
|
|
1000
|
+
|
|
1001
|
+
- **`GET /:models/:id/relationships/{relationship}`, and its state is #232's
|
|
1002
|
+
to report rather than this entry's.**
|
|
1003
|
+
[#232](https://github.com/abofs/stonyx-orm/issues/232) owns the
|
|
1004
|
+
relationships-linkage route. Its *primary data* is linkage,
|
|
1005
|
+
so filtering it is a **membership** decision — which is why it is the filed
|
|
1006
|
+
child of [#196](https://github.com/abofs/stonyx-orm/issues/196) and not of
|
|
1007
|
+
#234. The route builds its `{type, id}` objects by hand and never calls
|
|
1008
|
+
`toJSON`, so the `linkage` **option** never reaches it; whatever that route
|
|
1009
|
+
filters, it filters itself. Measured **on `dev @ 8dda5d6`**, the commit
|
|
1010
|
+
#235 branched from: `GET /animals/1/relationships/owner` answered
|
|
1011
|
+
`{"type":"owner","id":"angela"}` while `GET /owners/angela` was `404`. That
|
|
1012
|
+
measurement is pinned to a commit on purpose, so that it does not quietly
|
|
1013
|
+
become a false claim about `dev`. **PR
|
|
1014
|
+
[#247](https://github.com/abofs/stonyx-orm/pull/247) is in flight against
|
|
1015
|
+
this entry**; if it has landed, this route is covered and the bullet #247
|
|
1016
|
+
adds above supersedes this one.
|
|
1017
|
+
- **Whether a related resource appears in `included` at all.**
|
|
1018
|
+
[#233](https://github.com/abofs/stonyx-orm/issues/233) owns whether a
|
|
1019
|
+
related resource appears in `included`. #235 filters what a record
|
|
1020
|
+
*already in* `included` may **name**; a hidden record is still a
|
|
1000
1021
|
**member** of that array. The two are different questions and neither closes
|
|
1001
1022
|
the other: after #235, `GET /animals/1?include=owner,owner.pets` returns
|
|
1002
1023
|
`owner.data: null` on every permitted animal it sideloads **and still
|
|
@@ -1105,11 +1126,29 @@ read all of these.
|
|
|
1105
1126
|
|
|
1106
1127
|
#### `Record.toJSON()` does not filter relationship linkage unless you pass a verdict
|
|
1107
1128
|
|
|
1108
|
-
**The framework
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1129
|
+
**The framework resolves a verdict for you on every request-bound surface that
|
|
1130
|
+
serializes a record through `toJSON()`. You own it everywhere else.**
|
|
1131
|
+
|
|
1132
|
+
Those surfaces are `GET /:models`, `GET /:models/:id`, both shapes of
|
|
1133
|
+
`GET /:models/:id/{relationship}`, the `POST /:models` and `PATCH /:models/:id`
|
|
1134
|
+
**response documents**, and every record inside an `?include=` **`included`**
|
|
1135
|
+
array ([#234](https://github.com/abofs/stonyx-orm/issues/234) for the four
|
|
1136
|
+
reads, [#235](https://github.com/abofs/stonyx-orm/issues/235) for the two
|
|
1137
|
+
writes and `included`). Each resolves a linkage verdict and passes it to
|
|
1138
|
+
`toJSON()` for you.
|
|
1139
|
+
|
|
1140
|
+
**`GET /:models/:id/relationships/{relationship}` is not on that list, and its
|
|
1141
|
+
state is not this section's to report.** It builds its `{ type, id }` objects by
|
|
1142
|
+
hand instead of calling `toJSON()`, so the `linkage` **option** never reaches it
|
|
1143
|
+
— whatever that route filters, it filters itself. And because its linkage *is*
|
|
1144
|
+
its primary data, filtering it is a **membership** decision rather than a
|
|
1145
|
+
linkage one. Membership on both relationship route families is owned by
|
|
1146
|
+
[#232](https://github.com/abofs/stonyx-orm/issues/232) (PR
|
|
1147
|
+
[#247](https://github.com/abofs/stonyx-orm/pull/247), in flight as this is
|
|
1148
|
+
written); read that issue for its state rather than inferring it here, because
|
|
1149
|
+
this section describes only what `toJSON()` filters.
|
|
1150
|
+
|
|
1151
|
+
Any other path to a document — `JSON.stringify(record)`, `res.json(record)`,
|
|
1113
1152
|
`console.log(record)`, a custom route, a queue payload, a websocket frame —
|
|
1114
1153
|
calls `toJSON()` with no verdict, and **the no-verdict document names every
|
|
1115
1154
|
related id, including records hidden on every one of their own surfaces**
|
package/dist/orm-request.js
CHANGED
|
@@ -1333,27 +1333,46 @@ export default class OrmRequest extends Request {
|
|
|
1333
1333
|
};
|
|
1334
1334
|
// Relationship linkage route: GET /:id/relationships/{relationship}
|
|
1335
1335
|
//
|
|
1336
|
-
// NO `linkage` FILTER
|
|
1337
|
-
// abofs/stonyx-orm#232 OWNS THIS
|
|
1338
|
-
//
|
|
1339
|
-
//
|
|
1340
|
-
//
|
|
1341
|
-
// `{ type, id }` objects BY HAND and never calls `toJSON` at all, so it
|
|
1342
|
-
// cannot see a filter no matter who passes one.
|
|
1336
|
+
// NO `linkage` FILTER FROM abofs/stonyx-orm#235, AND THAT IS A SCOPE
|
|
1337
|
+
// BOUNDARY RATHER THAN AN OVERSIGHT -- abofs/stonyx-orm#232 OWNS THIS
|
|
1338
|
+
// ROUTE, and PR #247 is IN FLIGHT against it in this same sprint. If you
|
|
1339
|
+
// are reading this after #247 landed, the filtering below is #232's and
|
|
1340
|
+
// this note records why it was never #235's to add.
|
|
1343
1341
|
//
|
|
1344
|
-
//
|
|
1345
|
-
//
|
|
1346
|
-
//
|
|
1347
|
-
//
|
|
1348
|
-
//
|
|
1342
|
+
// The three sites #235 does own (`buildResponse`'s `included`, the
|
|
1343
|
+
// related-resource branch above, and the two write handlers) all reach
|
|
1344
|
+
// the filter through `record.toJSON()`, which is where the `linkage`
|
|
1345
|
+
// OPTION is applied. This branch builds its `{ type, id }` objects BY
|
|
1346
|
+
// HAND and never calls `toJSON` at all, so the `linkage` option cannot
|
|
1347
|
+
// reach it -- whatever this route filters, it has to filter itself, which
|
|
1348
|
+
// is precisely why doing so is a separate change with a separate owner.
|
|
1349
1349
|
//
|
|
1350
|
-
//
|
|
1351
|
-
//
|
|
1352
|
-
//
|
|
1353
|
-
//
|
|
1350
|
+
// It is also a DIFFERENT QUESTION. Everywhere #235 touches, linkage is
|
|
1351
|
+
// metadata ABOUT a document. Here the linkage IS the primary data, so
|
|
1352
|
+
// dropping an entry is a MEMBERSHIP decision about what this route
|
|
1353
|
+
// serves -- the same class as abofs/stonyx-orm#233 and #196, not the
|
|
1354
|
+
// class #234/#235 close. That is why it is absent from #224 §2a's
|
|
1355
|
+
// seven-site inventory.
|
|
1356
|
+
//
|
|
1357
|
+
// MEASURED, so the next person does not re-derive it. Against this
|
|
1358
|
+
// branch's baseline of 1011/0, wiring `createLinkageFilter` into the
|
|
1359
|
+
// belongsTo branch below takes the suite to 1009/2, reddening
|
|
1360
|
+
// `[GUARD] #235 X2` and the
|
|
1354
1361
|
// `GET /animals/:id/relationships/owner returns relationship linkage`
|
|
1355
|
-
// test
|
|
1356
|
-
//
|
|
1362
|
+
// test -- the latter is #232's own reproduction, not a regression.
|
|
1363
|
+
//
|
|
1364
|
+
// THE BASELINE IS QUOTED WITH THE RESULT BECAUSE AN EARLIER REVISION OF
|
|
1365
|
+
// THIS COMMENT SAID 993/2 AND SHIPPED IT. This file lands in consumers'
|
|
1366
|
+
// `node_modules`, so a wrong number here is a wrong number in the
|
|
1367
|
+
// published package. 993+2 = 995 is the DEV baseline, carried over from
|
|
1368
|
+
// a branch on which `[GUARD] #235 X2` does not exist. A pass/fail pair
|
|
1369
|
+
// with no baseline beside it cannot be checked by reading, which is how
|
|
1370
|
+
// it survived three artifacts and a review; the qualitative claim was
|
|
1371
|
+
// right the whole time and only the count was wrong.
|
|
1372
|
+
//
|
|
1373
|
+
// `[GUARD] #235 X2` in test/integration/orm-test.ts pins the OWNERSHIP
|
|
1374
|
+
// BOUNDARY here rather than this route's current answer, so that it
|
|
1375
|
+
// survives #247 landing. Read its comment before changing it.
|
|
1357
1376
|
routes[`/:id/relationships/${dasherizedName}`] = async (request, { filter } = {}) => {
|
|
1358
1377
|
const record = await store.find(model, getId(request.params));
|
|
1359
1378
|
if (!record)
|
package/package.json
CHANGED
package/src/orm-request.ts
CHANGED
|
@@ -1454,27 +1454,46 @@ export default class OrmRequest extends Request {
|
|
|
1454
1454
|
|
|
1455
1455
|
// Relationship linkage route: GET /:id/relationships/{relationship}
|
|
1456
1456
|
//
|
|
1457
|
-
// NO `linkage` FILTER
|
|
1458
|
-
// abofs/stonyx-orm#232 OWNS THIS
|
|
1459
|
-
//
|
|
1460
|
-
//
|
|
1461
|
-
//
|
|
1462
|
-
// `{ type, id }` objects BY HAND and never calls `toJSON` at all, so it
|
|
1463
|
-
// cannot see a filter no matter who passes one.
|
|
1457
|
+
// NO `linkage` FILTER FROM abofs/stonyx-orm#235, AND THAT IS A SCOPE
|
|
1458
|
+
// BOUNDARY RATHER THAN AN OVERSIGHT -- abofs/stonyx-orm#232 OWNS THIS
|
|
1459
|
+
// ROUTE, and PR #247 is IN FLIGHT against it in this same sprint. If you
|
|
1460
|
+
// are reading this after #247 landed, the filtering below is #232's and
|
|
1461
|
+
// this note records why it was never #235's to add.
|
|
1464
1462
|
//
|
|
1465
|
-
//
|
|
1466
|
-
//
|
|
1467
|
-
//
|
|
1468
|
-
//
|
|
1469
|
-
//
|
|
1463
|
+
// The three sites #235 does own (`buildResponse`'s `included`, the
|
|
1464
|
+
// related-resource branch above, and the two write handlers) all reach
|
|
1465
|
+
// the filter through `record.toJSON()`, which is where the `linkage`
|
|
1466
|
+
// OPTION is applied. This branch builds its `{ type, id }` objects BY
|
|
1467
|
+
// HAND and never calls `toJSON` at all, so the `linkage` option cannot
|
|
1468
|
+
// reach it -- whatever this route filters, it has to filter itself, which
|
|
1469
|
+
// is precisely why doing so is a separate change with a separate owner.
|
|
1470
1470
|
//
|
|
1471
|
-
//
|
|
1472
|
-
//
|
|
1473
|
-
//
|
|
1474
|
-
//
|
|
1471
|
+
// It is also a DIFFERENT QUESTION. Everywhere #235 touches, linkage is
|
|
1472
|
+
// metadata ABOUT a document. Here the linkage IS the primary data, so
|
|
1473
|
+
// dropping an entry is a MEMBERSHIP decision about what this route
|
|
1474
|
+
// serves -- the same class as abofs/stonyx-orm#233 and #196, not the
|
|
1475
|
+
// class #234/#235 close. That is why it is absent from #224 §2a's
|
|
1476
|
+
// seven-site inventory.
|
|
1477
|
+
//
|
|
1478
|
+
// MEASURED, so the next person does not re-derive it. Against this
|
|
1479
|
+
// branch's baseline of 1011/0, wiring `createLinkageFilter` into the
|
|
1480
|
+
// belongsTo branch below takes the suite to 1009/2, reddening
|
|
1481
|
+
// `[GUARD] #235 X2` and the
|
|
1475
1482
|
// `GET /animals/:id/relationships/owner returns relationship linkage`
|
|
1476
|
-
// test
|
|
1477
|
-
//
|
|
1483
|
+
// test -- the latter is #232's own reproduction, not a regression.
|
|
1484
|
+
//
|
|
1485
|
+
// THE BASELINE IS QUOTED WITH THE RESULT BECAUSE AN EARLIER REVISION OF
|
|
1486
|
+
// THIS COMMENT SAID 993/2 AND SHIPPED IT. This file lands in consumers'
|
|
1487
|
+
// `node_modules`, so a wrong number here is a wrong number in the
|
|
1488
|
+
// published package. 993+2 = 995 is the DEV baseline, carried over from
|
|
1489
|
+
// a branch on which `[GUARD] #235 X2` does not exist. A pass/fail pair
|
|
1490
|
+
// with no baseline beside it cannot be checked by reading, which is how
|
|
1491
|
+
// it survived three artifacts and a review; the qualitative claim was
|
|
1492
|
+
// right the whole time and only the count was wrong.
|
|
1493
|
+
//
|
|
1494
|
+
// `[GUARD] #235 X2` in test/integration/orm-test.ts pins the OWNERSHIP
|
|
1495
|
+
// BOUNDARY here rather than this route's current answer, so that it
|
|
1496
|
+
// survives #247 landing. Read its comment before changing it.
|
|
1478
1497
|
routes[`/:id/relationships/${dasherizedName}`] = async (request: OrmRequest$, { filter }: { [key: string]: unknown } = {}) => {
|
|
1479
1498
|
const record = await store.find(model, getId(request.params)) as OrmRecord | undefined;
|
|
1480
1499
|
if (!record) return 404;
|