@metreeca/keep 0.10.0 → 0.11.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.
@@ -16,45 +16,45 @@
16
16
  /**
17
17
  * Validating store wrapper.
18
18
  *
19
- * Wraps a plain {@link StoreClient} with shape-driven validation of entries, models, and states
20
- * before delegating, and optional re-validation of retrieval responses.
19
+ * Guards a {@link StoreClient} against malformed requests, checking entries, models and states against the request
20
+ * shape before they reach the backend. Retrieval responses from untrusted sources can be re-validated as well.
21
21
  *
22
22
  * @module
23
23
  */
24
24
  import { validate } from "@metreeca/blue";
25
- import { immutable } from "@metreeca/core/structures";
25
+ import { blueprint } from "@metreeca/blue/value";
26
+ import { error } from "@metreeca/core";
27
+ import { isNestedIRI } from "@metreeca/core/resource";
26
28
  import { TraceError } from "@metreeca/core/trace";
27
- import { isReference } from "@metreeca/qest/resource";
29
+ import { immutable } from "@metreeca/core/values";
30
+ import { isReference } from "@metreeca/qest/state";
28
31
  /**
29
32
  * Creates a validating store backed by a delegate.
30
33
  *
31
- * Each method validates the relevant inputs against the supplied shape before delegating to `store`:
34
+ * Each method validates its inputs against the supplied shape before forwarding the request to `store`:
32
35
  *
33
- * - `entry` is checked for absolute-IRI form (no query string, no fragment) — failures rejected as `RangeError`
34
- * - `state.id`, when present, is checked for equality with `entry` — mismatches rejected as `RangeError`, since
35
- * the entry identifies the target and a contradicting payload identity is a caller error
36
- * - `model` is validated as a {@link @metreeca/blue!validate | template} for
37
- * {@link StoreClient.lookup lookup}, with the `lookup` `plain`/`depth`/`limit` opts forwarded as
38
- * query-complexity caps
39
- * - `state` is validated as a resource for {@link StoreClient.create create}/
40
- * {@link StoreClient.update update}/{@link StoreClient.insert insert}; `create` and
41
- * `update` always cap captive expansion at depth `0` (inline captive batches rejected), while `insert` honours its
42
- * `depth` opt
43
- * (omitted leaves expansion unbounded)
36
+ * - `entry` must be an absolute IRI with no query string and no fragment; otherwise the request is rejected with a
37
+ * {@link !RangeError RangeError}
38
+ * - `model` is validated as a {@link @metreeca/blue!validate | template} for {@link StoreClient.lookup lookup},
39
+ * within the query-complexity bounds (`plain`, `depth`, `limit`) of the caller's
40
+ * {@link StoreScope | retrieval scope}, and as a collection slice for {@link StoreClient.create create}
41
+ * - `state.id`, if present, must be nested under `entry` for {@link StoreClient.create create}, and equal to `entry`
42
+ * for {@link StoreClient.update update} and {@link StoreClient.insert insert}; otherwise the request is rejected
43
+ * with a {@link !RangeError RangeError}
44
+ * - `state` is validated as a resource with captive expansion capped at depth `0`, so inline captive batches are
45
+ * rejected; {@link StoreClient.create create} validates it against the shape of the collected resources, and
46
+ * {@link StoreClient.update update} and {@link StoreClient.insert insert} against the supplied shape
44
47
  *
45
- * The `trusted` opt controls whether {@link StoreClient.lookup lookup} responses are re-validated
46
- * against the shape narrowed by the caller's `model` template before surfacing. Defaults to `false`
47
- * — connectors whose backing source isn't trusted to deliver shape-conforming data (for example, a
48
- * remote REST endpoint) get the safe default. Local stores that compute results themselves should
49
- * pass `trusted: true` to skip the redundant pass.
48
+ * The `trusted` option controls whether {@link StoreClient.lookup lookup} responses are re-validated against the
49
+ * shape, as narrowed by the caller's `model`. It defaults to `false`, the safe choice for connectors whose source may
50
+ * deliver non-conforming data, such as a remote REST endpoint. Local stores that compute results themselves can pass
51
+ * `trusted: true` to skip the redundant check.
50
52
  *
51
- * Validation failures surface as {@link @metreeca/core!TraceError | TraceError} or `RangeError` rejections per the
52
- * unified {@link Store} error channel.
53
+ * Validation failures surface as {@link @metreeca/core!TraceError | TraceError} or {@link !RangeError RangeError}
54
+ * rejections, in line with the unified {@link Store} error channel.
53
55
  *
54
- * @param store - Inner StoreClient to delegate to after validation
56
+ * @param store - Inner StoreClient receiving the validated requests
55
57
  * @param options - Optional validation options
56
- * @param options.trusted - When `true`, skips re-validation of the {@link StoreClient.lookup lookup}
57
- * response against the shape narrowed by the caller's `model`; defaults to `false`
58
58
  *
59
59
  * @returns An immutable {@link StoreClient} wrapping `store` with input validation
60
60
  */
@@ -64,33 +64,43 @@ export function createValidatingStore(store, { trusted = false } = {}) {
64
64
  return store.lookup({
65
65
  entry: assertEntry(entry),
66
66
  shape,
67
- model: validate(model, { ...opts, shape, model: true })({
68
- value: value => value,
69
- trace: trace => { throw new TraceError("invalid model", trace ?? []); }
70
- })
67
+ model: assertModel(model, shape, opts)
71
68
  }, opts).then(result => {
72
- return trusted || result === undefined ? immutable(result) : validate(result, { shape, model })({
69
+ // ;(cast) blue types the validated copy by its own `Delivery` inference rather than by the `Match`
70
+ // the store states; the copy is returned, rather than the raw response, as it carries the verdict
71
+ return (trusted || result === undefined ? immutable(result) : validate(result, { shape, model })({
73
72
  value: value => value,
74
73
  trace: trace => { throw new TraceError("invalid response", trace ?? []); }
75
- });
74
+ }));
76
75
  });
77
76
  },
78
- async create({ entry, shape, state }) {
79
- return store.create({
80
- entry: assertEntry(entry),
81
- shape,
82
- state: validate(state, { shape, depth: 0 })({
83
- value: value => value,
84
- trace: trace => { throw new TraceError("invalid state", trace ?? []); }
85
- })
77
+ async create({ entry, shape, model, state }) {
78
+ const $entry = assertEntry(entry);
79
+ const $model = validate(model, { shape, model: true })({
80
+ value: value => value,
81
+ trace: trace => { throw new TraceError("invalid model", trace ?? []); }
82
+ });
83
+ // the new resource is validated against the shape the collecting property ranges over, and a stated
84
+ // identifier is held to the collection it is created through
85
+ const plan = blueprint(shape, $model);
86
+ const { id } = state;
87
+ const $state = id === undefined || isReference(id) && isNestedIRI($entry, id) ? state
88
+ : error(new RangeError(`state id <${String(id)}> not nested under entry <${entry}>`));
89
+ // the validator hands back the state itself where it passes, so the typed input is relayed as it
90
+ // stands once the check has run, the blueprint being resolved at runtime rather than typed
91
+ validate($state, { shape: plan, depth: 0 })({
92
+ value: () => undefined,
93
+ trace: trace => { throw new TraceError("invalid state", trace ?? []); }
86
94
  });
95
+ return store.create({ entry: $entry, shape, model: $model, state: $state });
87
96
  },
88
97
  async update({ entry, shape, state }) {
98
+ const $entry = assertEntry(entry);
89
99
  return store.update({
90
- entry: assertEntry(entry),
100
+ entry: $entry,
91
101
  shape,
92
- state: validate(state, { shape, depth: 0 })({
93
- value: value => value,
102
+ state: validate(assertIdentity($entry, state), { shape, depth: 0 })({
103
+ value: () => state,
94
104
  trace: trace => { throw new TraceError("invalid state", trace ?? []); }
95
105
  })
96
106
  });
@@ -98,15 +108,16 @@ export function createValidatingStore(store, { trusted = false } = {}) {
98
108
  async delete({ entry, shape }) {
99
109
  return store.delete({ entry: assertEntry(entry), shape });
100
110
  },
101
- async insert({ entry, shape, state }, opts) {
111
+ async insert({ entry, shape, state }) {
112
+ const $entry = assertEntry(entry);
102
113
  return store.insert({
103
- entry: assertEntry(entry),
114
+ entry: $entry,
104
115
  shape,
105
- state: validate(state, { ...opts, shape })({
106
- value: value => value,
116
+ state: validate(assertIdentity($entry, state), { shape, depth: 0 })({
117
+ value: () => state,
107
118
  trace: trace => { throw new TraceError("invalid state", trace ?? []); }
108
119
  })
109
- }, opts);
120
+ });
110
121
  },
111
122
  async remove({ entry, shape }) {
112
123
  return store.remove({
@@ -124,5 +135,16 @@ export function createValidatingStore(store, { trusted = false } = {}) {
124
135
  }
125
136
  return entry;
126
137
  }
138
+ function assertIdentity(entry, state) {
139
+ const { id } = state;
140
+ return id === undefined || id === entry ? state
141
+ : error(new RangeError(`mismatched state id <${String(id)}> for entry <${entry}>`));
142
+ }
143
+ function assertModel(model, shape, opts = {}) {
144
+ return validate(model, { ...opts, shape, model: true })({
145
+ value: value => value,
146
+ trace: trace => { throw new TraceError("invalid model", trace ?? []); }
147
+ });
148
+ }
127
149
  }
128
150
  //# sourceMappingURL=validating.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validating.js","sourceRoot":"","sources":["../../src/clients/validating.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validating.js","sourceRoot":"","sources":["../../src/clients/validating.ts"],"names":[],"mappings":"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"}