@haverstack/core 0.40.0 → 0.42.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.
Files changed (287) hide show
  1. package/README.md +121 -59
  2. package/dist/access.d.ts +34 -36
  3. package/dist/access.d.ts.map +1 -1
  4. package/dist/access.js +65 -42
  5. package/dist/access.js.map +1 -1
  6. package/dist/{combine.d.ts → adapter/combine.d.ts} +8 -1
  7. package/dist/adapter/combine.d.ts.map +1 -0
  8. package/dist/{combine.js → adapter/combine.js} +7 -0
  9. package/dist/adapter/combine.js.map +1 -0
  10. package/dist/{adapter-entry.d.ts → adapter/index.d.ts} +6 -5
  11. package/dist/adapter/index.d.ts.map +1 -0
  12. package/dist/{adapter-entry.js → adapter/index.js} +5 -4
  13. package/dist/adapter/index.js.map +1 -0
  14. package/dist/{sort.d.ts → adapter/sort.d.ts} +20 -20
  15. package/dist/adapter/sort.d.ts.map +1 -0
  16. package/dist/{sort.js → adapter/sort.js} +37 -27
  17. package/dist/adapter/sort.js.map +1 -0
  18. package/dist/associations/identity.d.ts +93 -0
  19. package/dist/associations/identity.d.ts.map +1 -0
  20. package/dist/associations/identity.js +198 -0
  21. package/dist/associations/identity.js.map +1 -0
  22. package/dist/associations/validation.d.ts +90 -0
  23. package/dist/associations/validation.d.ts.map +1 -0
  24. package/dist/associations/validation.js +339 -0
  25. package/dist/associations/validation.js.map +1 -0
  26. package/dist/attachment-records.d.ts +48 -0
  27. package/dist/attachment-records.d.ts.map +1 -0
  28. package/dist/attachment-records.js +52 -0
  29. package/dist/attachment-records.js.map +1 -0
  30. package/dist/collection.d.ts +182 -0
  31. package/dist/collection.d.ts.map +1 -0
  32. package/dist/collection.js +407 -0
  33. package/dist/collection.js.map +1 -0
  34. package/dist/content-match.d.ts +25 -0
  35. package/dist/content-match.d.ts.map +1 -0
  36. package/dist/content-match.js +51 -0
  37. package/dist/content-match.js.map +1 -0
  38. package/dist/content-translation.d.ts +42 -0
  39. package/dist/content-translation.d.ts.map +1 -0
  40. package/dist/content-translation.js +108 -0
  41. package/dist/content-translation.js.map +1 -0
  42. package/dist/did/did.d.ts.map +1 -0
  43. package/dist/{did.js → did/did.js} +3 -4
  44. package/dist/did/did.js.map +1 -0
  45. package/dist/{did-entry.d.ts → did/index.d.ts} +1 -1
  46. package/dist/did/index.d.ts.map +1 -0
  47. package/dist/{did-entry.js → did/index.js} +3 -3
  48. package/dist/did/index.js.map +1 -0
  49. package/dist/errors.d.ts +36 -63
  50. package/dist/errors.d.ts.map +1 -1
  51. package/dist/errors.js +35 -58
  52. package/dist/errors.js.map +1 -1
  53. package/dist/grants.d.ts +20 -43
  54. package/dist/grants.d.ts.map +1 -1
  55. package/dist/grants.js +71 -134
  56. package/dist/grants.js.map +1 -1
  57. package/dist/id.d.ts +13 -31
  58. package/dist/id.d.ts.map +1 -1
  59. package/dist/id.js +13 -31
  60. package/dist/id.js.map +1 -1
  61. package/dist/index.d.ts +14 -8
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +9 -5
  64. package/dist/index.js.map +1 -1
  65. package/dist/install.d.ts +141 -0
  66. package/dist/install.d.ts.map +1 -0
  67. package/dist/install.js +219 -0
  68. package/dist/install.js.map +1 -0
  69. package/dist/merge.d.ts.map +1 -1
  70. package/dist/merge.js +5 -11
  71. package/dist/merge.js.map +1 -1
  72. package/dist/migration-steps.d.ts +102 -0
  73. package/dist/migration-steps.d.ts.map +1 -0
  74. package/dist/migration-steps.js +293 -0
  75. package/dist/migration-steps.js.map +1 -0
  76. package/dist/query-validation.d.ts +28 -94
  77. package/dist/query-validation.d.ts.map +1 -1
  78. package/dist/query-validation.js +156 -336
  79. package/dist/query-validation.js.map +1 -1
  80. package/dist/record-changes.d.ts +2 -117
  81. package/dist/record-changes.d.ts.map +1 -1
  82. package/dist/record-changes.js +10 -212
  83. package/dist/record-changes.js.map +1 -1
  84. package/dist/schema.d.ts +18 -7
  85. package/dist/schema.d.ts.map +1 -1
  86. package/dist/schema.js +59 -30
  87. package/dist/schema.js.map +1 -1
  88. package/dist/scoped-stack/authority.d.ts +156 -0
  89. package/dist/scoped-stack/authority.d.ts.map +1 -0
  90. package/dist/scoped-stack/authority.js +384 -0
  91. package/dist/scoped-stack/authority.js.map +1 -0
  92. package/dist/scoped-stack/scoped-stack.d.ts +338 -0
  93. package/dist/scoped-stack/scoped-stack.d.ts.map +1 -0
  94. package/dist/scoped-stack/scoped-stack.js +776 -0
  95. package/dist/scoped-stack/scoped-stack.js.map +1 -0
  96. package/dist/scoped-stack/subscription.d.ts +55 -0
  97. package/dist/scoped-stack/subscription.d.ts.map +1 -0
  98. package/dist/scoped-stack/subscription.js +110 -0
  99. package/dist/scoped-stack/subscription.js.map +1 -0
  100. package/dist/stack/attachments.d.ts +24 -0
  101. package/dist/stack/attachments.d.ts.map +1 -0
  102. package/dist/stack/attachments.js +113 -0
  103. package/dist/stack/attachments.js.map +1 -0
  104. package/dist/{changes.d.ts → stack/changes.d.ts} +29 -65
  105. package/dist/stack/changes.d.ts.map +1 -0
  106. package/dist/{changes.js → stack/changes.js} +32 -66
  107. package/dist/stack/changes.js.map +1 -0
  108. package/dist/stack/client.d.ts +271 -0
  109. package/dist/stack/client.d.ts.map +1 -0
  110. package/dist/stack/client.js +9 -0
  111. package/dist/stack/client.js.map +1 -0
  112. package/dist/stack/identity-bindings.d.ts.map +1 -0
  113. package/dist/{identity-bindings.js → stack/identity-bindings.js} +8 -14
  114. package/dist/stack/identity-bindings.js.map +1 -0
  115. package/dist/stack/install-app.d.ts +22 -0
  116. package/dist/stack/install-app.d.ts.map +1 -0
  117. package/dist/stack/install-app.js +260 -0
  118. package/dist/stack/install-app.js.map +1 -0
  119. package/dist/stack/integrity.d.ts +94 -0
  120. package/dist/stack/integrity.d.ts.map +1 -0
  121. package/dist/stack/integrity.js +268 -0
  122. package/dist/stack/integrity.js.map +1 -0
  123. package/dist/{limits.d.ts → stack/limits.d.ts} +2 -5
  124. package/dist/stack/limits.d.ts.map +1 -0
  125. package/dist/{limits.js → stack/limits.js} +3 -6
  126. package/dist/stack/limits.js.map +1 -0
  127. package/dist/stack/migrations.d.ts +59 -0
  128. package/dist/stack/migrations.d.ts.map +1 -0
  129. package/dist/stack/migrations.js +141 -0
  130. package/dist/stack/migrations.js.map +1 -0
  131. package/dist/{stack-reads.d.ts → stack/reads.d.ts} +33 -6
  132. package/dist/stack/reads.d.ts.map +1 -0
  133. package/dist/{stack-reads.js → stack/reads.js} +49 -7
  134. package/dist/stack/reads.js.map +1 -0
  135. package/dist/stack/record-id.d.ts +35 -0
  136. package/dist/stack/record-id.d.ts.map +1 -0
  137. package/dist/stack/record-id.js +82 -0
  138. package/dist/stack/record-id.js.map +1 -0
  139. package/dist/stack/stack.d.ts +438 -0
  140. package/dist/stack/stack.d.ts.map +1 -0
  141. package/dist/stack/stack.js +1366 -0
  142. package/dist/stack/stack.js.map +1 -0
  143. package/dist/stack/system-types.d.ts +16 -0
  144. package/dist/stack/system-types.d.ts.map +1 -0
  145. package/dist/stack/system-types.js +111 -0
  146. package/dist/stack/system-types.js.map +1 -0
  147. package/dist/stack/type-grants.d.ts +20 -0
  148. package/dist/stack/type-grants.d.ts.map +1 -0
  149. package/dist/stack/type-grants.js +69 -0
  150. package/dist/stack/type-grants.js.map +1 -0
  151. package/dist/stack/write-expectation.d.ts +78 -0
  152. package/dist/stack/write-expectation.d.ts.map +1 -0
  153. package/dist/stack/write-expectation.js +71 -0
  154. package/dist/stack/write-expectation.js.map +1 -0
  155. package/dist/testing.d.ts +21 -26
  156. package/dist/testing.d.ts.map +1 -1
  157. package/dist/testing.js +50 -70
  158. package/dist/testing.js.map +1 -1
  159. package/dist/type-handle.d.ts +67 -78
  160. package/dist/type-handle.d.ts.map +1 -1
  161. package/dist/type-handle.js +44 -111
  162. package/dist/type-handle.js.map +1 -1
  163. package/dist/types/adapter.d.ts +223 -0
  164. package/dist/types/adapter.d.ts.map +1 -0
  165. package/dist/types/adapter.js +5 -0
  166. package/dist/types/adapter.js.map +1 -0
  167. package/dist/types/associations.d.ts +156 -0
  168. package/dist/types/associations.d.ts.map +1 -0
  169. package/dist/types/associations.js +13 -0
  170. package/dist/types/associations.js.map +1 -0
  171. package/dist/types/capabilities.d.ts +89 -0
  172. package/dist/types/capabilities.d.ts.map +1 -0
  173. package/dist/types/capabilities.js +5 -0
  174. package/dist/types/capabilities.js.map +1 -0
  175. package/dist/types/events.d.ts +155 -0
  176. package/dist/types/events.d.ts.map +1 -0
  177. package/dist/types/events.js +5 -0
  178. package/dist/types/events.js.map +1 -0
  179. package/dist/types/ids.d.ts +43 -0
  180. package/dist/types/ids.d.ts.map +1 -0
  181. package/dist/types/ids.js +5 -0
  182. package/dist/types/ids.js.map +1 -0
  183. package/dist/types/index.d.ts +19 -0
  184. package/dist/types/index.d.ts.map +1 -0
  185. package/dist/types/index.js +19 -0
  186. package/dist/types/index.js.map +1 -0
  187. package/dist/types/journal.d.ts +47 -0
  188. package/dist/types/journal.d.ts.map +1 -0
  189. package/dist/types/journal.js +5 -0
  190. package/dist/types/journal.js.map +1 -0
  191. package/dist/types/query.d.ts +185 -0
  192. package/dist/types/query.d.ts.map +1 -0
  193. package/dist/types/query.js +10 -0
  194. package/dist/types/query.js.map +1 -0
  195. package/dist/types/records.d.ts +76 -0
  196. package/dist/types/records.d.ts.map +1 -0
  197. package/dist/types/records.js +5 -0
  198. package/dist/types/records.js.map +1 -0
  199. package/dist/types/schema.d.ts +74 -0
  200. package/dist/types/schema.d.ts.map +1 -0
  201. package/dist/types/schema.js +5 -0
  202. package/dist/types/schema.js.map +1 -0
  203. package/dist/types/system.d.ts +161 -0
  204. package/dist/types/system.d.ts.map +1 -0
  205. package/dist/types/system.js +32 -0
  206. package/dist/types/system.js.map +1 -0
  207. package/dist/types/tokens.d.ts +39 -0
  208. package/dist/types/tokens.d.ts.map +1 -0
  209. package/dist/types/tokens.js +5 -0
  210. package/dist/types/tokens.js.map +1 -0
  211. package/dist/validate.d.ts +29 -70
  212. package/dist/validate.d.ts.map +1 -1
  213. package/dist/validate.js +65 -97
  214. package/dist/validate.js.map +1 -1
  215. package/dist/{attachment-download.d.ts → wire/attachment-download.d.ts} +0 -57
  216. package/dist/wire/attachment-download.d.ts.map +1 -0
  217. package/dist/{attachment-download.js → wire/attachment-download.js} +0 -61
  218. package/dist/wire/attachment-download.js.map +1 -0
  219. package/dist/{auth.d.ts → wire/auth.d.ts} +5 -8
  220. package/dist/wire/auth.d.ts.map +1 -0
  221. package/dist/{auth.js → wire/auth.js} +5 -8
  222. package/dist/wire/auth.js.map +1 -0
  223. package/dist/{wire-body.d.ts → wire/body.d.ts} +13 -5
  224. package/dist/wire/body.d.ts.map +1 -0
  225. package/dist/{wire-body.js → wire/body.js} +65 -7
  226. package/dist/wire/body.js.map +1 -0
  227. package/dist/{wire-entry.d.ts → wire/index.d.ts} +12 -12
  228. package/dist/wire/index.d.ts.map +1 -0
  229. package/dist/{wire-entry.js → wire/index.js} +13 -17
  230. package/dist/wire/index.js.map +1 -0
  231. package/dist/{wire-record.d.ts → wire/record.d.ts} +10 -22
  232. package/dist/wire/record.d.ts.map +1 -0
  233. package/dist/{wire-record.js → wire/record.js} +12 -24
  234. package/dist/wire/record.js.map +1 -0
  235. package/dist/{wire-request.d.ts → wire/request.d.ts} +20 -37
  236. package/dist/wire/request.d.ts.map +1 -0
  237. package/dist/{wire-request.js → wire/request.js} +79 -54
  238. package/dist/wire/request.js.map +1 -0
  239. package/package.json +7 -7
  240. package/dist/adapter-entry.d.ts.map +0 -1
  241. package/dist/adapter-entry.js.map +0 -1
  242. package/dist/attachment-download.d.ts.map +0 -1
  243. package/dist/attachment-download.js.map +0 -1
  244. package/dist/auth.d.ts.map +0 -1
  245. package/dist/auth.js.map +0 -1
  246. package/dist/changes.d.ts.map +0 -1
  247. package/dist/changes.js.map +0 -1
  248. package/dist/combine.d.ts.map +0 -1
  249. package/dist/combine.js.map +0 -1
  250. package/dist/did-entry.d.ts.map +0 -1
  251. package/dist/did-entry.js.map +0 -1
  252. package/dist/did.d.ts.map +0 -1
  253. package/dist/did.js.map +0 -1
  254. package/dist/identity-bindings.d.ts.map +0 -1
  255. package/dist/identity-bindings.js.map +0 -1
  256. package/dist/limits.d.ts.map +0 -1
  257. package/dist/limits.js.map +0 -1
  258. package/dist/record-id.d.ts +0 -70
  259. package/dist/record-id.d.ts.map +0 -1
  260. package/dist/record-id.js +0 -127
  261. package/dist/record-id.js.map +0 -1
  262. package/dist/scoped-stack.d.ts +0 -532
  263. package/dist/scoped-stack.d.ts.map +0 -1
  264. package/dist/scoped-stack.js +0 -1219
  265. package/dist/scoped-stack.js.map +0 -1
  266. package/dist/sort.d.ts.map +0 -1
  267. package/dist/sort.js.map +0 -1
  268. package/dist/stack-reads.d.ts.map +0 -1
  269. package/dist/stack-reads.js.map +0 -1
  270. package/dist/stack.d.ts +0 -971
  271. package/dist/stack.d.ts.map +0 -1
  272. package/dist/stack.js +0 -2012
  273. package/dist/stack.js.map +0 -1
  274. package/dist/types.d.ts +0 -1250
  275. package/dist/types.d.ts.map +0 -1
  276. package/dist/types.js +0 -49
  277. package/dist/types.js.map +0 -1
  278. package/dist/wire-body.d.ts.map +0 -1
  279. package/dist/wire-body.js.map +0 -1
  280. package/dist/wire-entry.d.ts.map +0 -1
  281. package/dist/wire-entry.js.map +0 -1
  282. package/dist/wire-record.d.ts.map +0 -1
  283. package/dist/wire-record.js.map +0 -1
  284. package/dist/wire-request.d.ts.map +0 -1
  285. package/dist/wire-request.js.map +0 -1
  286. /package/dist/{did.d.ts → did/did.d.ts} +0 -0
  287. /package/dist/{identity-bindings.d.ts → stack/identity-bindings.d.ts} +0 -0
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Migration steps
3
+ * -------------------------------------------------------
4
+ * A migration is a list of declared steps — rename, map, add, drop and
5
+ * derive — rather than a function, so that core can read what became of
6
+ * each field. Two things are built from one list: the in-memory `migrate`
7
+ * that `Stack.open()`, a collection's reads and `migrateAll()` run, and the
8
+ * field origins a collection translates a content filter or sort through.
9
+ *
10
+ * `fieldOrigins()` also checks the list against both schemas, so a step
11
+ * the target Type would refuse fails when `migration()` runs rather than
12
+ * on the first record `migrateAll()` writes. See docs/spec/data-model.md
13
+ * § Migration steps.
14
+ */
15
+ import { validateContent } from './validate.js';
16
+ /** Move a field's value to a new name. */
17
+ export const rename = (from, to) => Object.freeze({ op: 'rename', from, to });
18
+ /**
19
+ * Replace each value `values` lists with its mapping, keeping any other,
20
+ * element-wise through an array. A stored enum may hold a value no handle
21
+ * lists, and it is carried through rather than lost.
22
+ */
23
+ export const map = (field, values) => Object.freeze({ op: 'map', field, values: Object.freeze({ ...values }) });
24
+ /** Set a field to a constant. */
25
+ export const add = (field, value) => Object.freeze({ op: 'add', field, value });
26
+ /** Remove a field. */
27
+ export const drop = (field) => Object.freeze({ op: 'drop', field });
28
+ /**
29
+ * Set a field to what `fn` computes from the record as stored at the
30
+ * migration's `from`; `undefined` leaves it absent. The one opaque step: a
31
+ * field it produces does not translate across versions.
32
+ */
33
+ export const derive = (field, fn) => Object.freeze({ op: 'derive', field, derive: fn });
34
+ const describe = (step) => {
35
+ switch (step.op) {
36
+ case 'rename':
37
+ return `rename("${step.from}", "${step.to}")`;
38
+ case 'add':
39
+ return `add("${step.field}", …)`;
40
+ default:
41
+ return `${step.op}("${step.field}"${step.op === 'drop' ? '' : ', …'})`;
42
+ }
43
+ };
44
+ // -------------------------------------------------------
45
+ // Applying steps
46
+ // -------------------------------------------------------
47
+ const remap = (value, values) => {
48
+ if (Array.isArray(value))
49
+ return value.map((v) => remap(v, values));
50
+ return typeof value === 'string' && Object.hasOwn(values, value) ? values[value] : value;
51
+ };
52
+ /** The content `steps` produce from `content`, which is left untouched. */
53
+ export const applySteps = (steps, content) => {
54
+ const out = { ...content };
55
+ for (const step of steps) {
56
+ switch (step.op) {
57
+ case 'rename':
58
+ if (Object.hasOwn(out, step.from))
59
+ out[step.to] = out[step.from];
60
+ delete out[step.from];
61
+ break;
62
+ case 'map':
63
+ if (out[step.field] !== undefined)
64
+ out[step.field] = remap(out[step.field], step.values);
65
+ break;
66
+ case 'add':
67
+ out[step.field] = step.value;
68
+ break;
69
+ case 'drop':
70
+ delete out[step.field];
71
+ break;
72
+ case 'derive': {
73
+ const value = step.derive(content);
74
+ if (value === undefined)
75
+ delete out[step.field];
76
+ else
77
+ out[step.field] = value;
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ return out;
83
+ };
84
+ /** `outer` after `inner`, as one table over both domains. */
85
+ const composeValues = (inner, outer) => {
86
+ if (!inner)
87
+ return outer;
88
+ if (!outer)
89
+ return inner;
90
+ const composed = {};
91
+ for (const [from, to] of Object.entries(inner))
92
+ composed[from] = remap(to, outer);
93
+ for (const [from, to] of Object.entries(outer)) {
94
+ if (!Object.hasOwn(inner, from))
95
+ composed[from] = to;
96
+ }
97
+ return composed;
98
+ };
99
+ /**
100
+ * The origins across two migrations end to end: `lower` takes A to B and
101
+ * `upper` takes B to C, so the result says what each of C's fields is in
102
+ * terms of A's.
103
+ */
104
+ export const composeOrigins = (lower, upper) => {
105
+ const composed = new Map();
106
+ for (const [field, origin] of upper) {
107
+ if (origin.kind !== 'field') {
108
+ composed.set(field, origin);
109
+ continue;
110
+ }
111
+ // A name the lower step neither declares nor removed passes through it.
112
+ const inner = lower.get(origin.field) ?? { kind: 'field', field: origin.field };
113
+ composed.set(field, inner.kind === 'field'
114
+ ? { kind: 'field', field: inner.field, values: composeValues(inner.values, origin.values) }
115
+ : inner.kind === 'constant'
116
+ ? {
117
+ kind: 'constant',
118
+ value: origin.values ? remap(inner.value, origin.values) : inner.value,
119
+ }
120
+ : inner);
121
+ }
122
+ return composed;
123
+ };
124
+ const isStringKind = (def) => def?.kind === 'enum' || def?.kind === 'string' || def?.kind === 'text';
125
+ /** What `map` may remap: a string-shaped scalar, or a declared array of one. */
126
+ const isMappable = (def) => isStringKind(def) || (def?.kind === 'array' && !def.open && isStringKind(def.items));
127
+ const MAX_CARRY_DEPTH = 32;
128
+ /**
129
+ * Why a value stored under `source` could fail `target` once `values`
130
+ * remaps it, or null when it cannot. A carried field is written as it
131
+ * stands, so this is write validity, not the read compatibility
132
+ * isCompatible() answers.
133
+ */
134
+ const carryProblem = (path, source, target, values, depth) => {
135
+ if (depth > MAX_CARRY_DEPTH)
136
+ return `"${path}" nests too deeply to check`;
137
+ if (target.required && !source.required) {
138
+ return `"${path}" is optional at the source and required at the target`;
139
+ }
140
+ if (target.kind === 'array') {
141
+ if (source.kind !== 'array')
142
+ return `"${path}" changes kind from ${source.kind} to array`;
143
+ if (target.open)
144
+ return null;
145
+ if (source.open)
146
+ return `"${path}" is an open array at the source and declared at the target`;
147
+ return carryProblem(`${path}[]`, source.items, target.items, values, depth + 1);
148
+ }
149
+ if (target.kind === 'object') {
150
+ if (source.kind !== 'object')
151
+ return `"${path}" changes kind from ${source.kind} to object`;
152
+ if (target.open)
153
+ return null;
154
+ if (source.open)
155
+ return `"${path}" is an open object at the source and declared at the target`;
156
+ for (const [key, def] of Object.entries(target.properties)) {
157
+ const from = source.properties[key];
158
+ if (!from) {
159
+ if (def.required)
160
+ return `"${path}.${key}" is required at the target and not at the source`;
161
+ continue;
162
+ }
163
+ const problem = carryProblem(`${path}.${key}`, from, def, undefined, depth + 1);
164
+ if (problem)
165
+ return problem;
166
+ }
167
+ for (const key of Object.keys(source.properties)) {
168
+ if (!Object.hasOwn(target.properties, key)) {
169
+ return `"${path}.${key}" is not declared at the target`;
170
+ }
171
+ }
172
+ return null;
173
+ }
174
+ if (target.kind === 'enum') {
175
+ if (source.kind !== 'enum')
176
+ return `"${path}" changes kind from ${source.kind} to enum`;
177
+ const allowed = new Set(target.values);
178
+ const missing = source.values.find((v) => !allowed.has(remap(v, values ?? {})));
179
+ return missing === undefined
180
+ ? null
181
+ : `"${path}" holds "${missing}"${values && Object.hasOwn(values, missing) ? ` (mapped to "${values[missing]}")` : ''}, which the target's enum does not list`;
182
+ }
183
+ if (target.kind === 'string' || target.kind === 'text') {
184
+ return isStringKind(source)
185
+ ? null
186
+ : `"${path}" changes kind from ${source.kind} to ${target.kind}`;
187
+ }
188
+ return source.kind === target.kind
189
+ ? null
190
+ : `"${path}" changes kind from ${source.kind} to ${target.kind}`;
191
+ };
192
+ /**
193
+ * What each of `to`'s top-level fields is in terms of `from`'s, after
194
+ * `steps`. Returns the problem that makes the list unusable as a string
195
+ * instead: a step naming a field that is not there, a field `to` would
196
+ * refuse, or one it requires that nothing produces. See
197
+ * docs/spec/data-model.md § Migration steps.
198
+ */
199
+ export const fieldOrigins = (steps, from, to) => {
200
+ const current = new Map(Object.keys(from).map((field) => [field, { kind: 'field', field }]));
201
+ const removed = new Set();
202
+ for (const step of steps) {
203
+ const at = describe(step);
204
+ const named = step.op === 'rename' ? step.from : step.field;
205
+ if (step.op !== 'add' && step.op !== 'derive' && !current.has(named)) {
206
+ return `${at}: "${named}" is not a field at this point`;
207
+ }
208
+ switch (step.op) {
209
+ case 'rename':
210
+ if (current.has(step.to))
211
+ return `${at}: "${step.to}" is already a field at this point`;
212
+ current.set(step.to, current.get(step.from));
213
+ current.delete(step.from);
214
+ removed.add(step.from);
215
+ break;
216
+ case 'map': {
217
+ const origin = current.get(step.field);
218
+ if (origin.kind === 'field') {
219
+ if (!isMappable(from[origin.field])) {
220
+ return `${at}: only an enum, string or text field, or an array of one, can be mapped`;
221
+ }
222
+ current.set(step.field, {
223
+ ...origin,
224
+ values: composeValues(origin.values, step.values),
225
+ });
226
+ }
227
+ else if (origin.kind === 'constant') {
228
+ current.set(step.field, { kind: 'constant', value: remap(origin.value, step.values) });
229
+ }
230
+ break;
231
+ }
232
+ case 'add':
233
+ if (current.has(step.field))
234
+ return `${at}: "${step.field}" is already a field at this point`;
235
+ if (step.value === undefined)
236
+ return `${at}: an added field needs a value`;
237
+ current.set(step.field, { kind: 'constant', value: step.value });
238
+ break;
239
+ case 'drop':
240
+ current.delete(step.field);
241
+ removed.add(step.field);
242
+ break;
243
+ case 'derive':
244
+ current.set(step.field, { kind: 'derived' });
245
+ break;
246
+ }
247
+ }
248
+ for (const field of current.keys()) {
249
+ if (!Object.hasOwn(to, field)) {
250
+ return `"${field}" is carried to a Type that does not declare it; drop or rename it`;
251
+ }
252
+ }
253
+ for (const [field, def] of Object.entries(to)) {
254
+ const origin = current.get(field);
255
+ if (!origin) {
256
+ if (def.required)
257
+ return `"${field}" is required at the target, and no step produces it`;
258
+ // migrate() carries every field no step names, so one an older
259
+ // version gained in place arrives under its own name.
260
+ current.set(field, removed.has(field) ? { kind: 'constant', value: undefined } : { kind: 'field', field });
261
+ continue;
262
+ }
263
+ if (origin.kind === 'field') {
264
+ const problem = carryProblem(field, from[origin.field], def, origin.values, 0);
265
+ if (problem)
266
+ return problem;
267
+ }
268
+ else if (origin.kind === 'constant') {
269
+ const errors = validateContent({ [field]: origin.value }, { [field]: def });
270
+ if (errors.length > 0)
271
+ return `"${field}" is set to a value the target refuses: ${errors[0].message}`;
272
+ }
273
+ }
274
+ for (const field of removed) {
275
+ if (!current.has(field))
276
+ current.set(field, { kind: 'constant', value: undefined });
277
+ }
278
+ return current;
279
+ };
280
+ // -------------------------------------------------------
281
+ // Registry of origins
282
+ // -------------------------------------------------------
283
+ /**
284
+ * The origins `migration()` computed for each migration it built. A
285
+ * migration assembled by hand has none, and a collection reads every field
286
+ * across it as derived.
287
+ */
288
+ const ORIGINS = new WeakMap();
289
+ export const recordOrigins = (migration, origins) => {
290
+ ORIGINS.set(migration, origins);
291
+ };
292
+ export const originsOf = (migration) => ORIGINS.get(migration);
293
+ //# sourceMappingURL=migration-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-steps.js","sourceRoot":"","sources":["../src/migration-steps.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,10 @@
1
1
  /**
2
- * Query and association validation
2
+ * Query validation
3
3
  * -------------------------------------------------------
4
- * The sanitizers a query passes through before any adapter sees it, plus
5
- * the relationship-target rules an association is held to. Both sides of
6
- * the same job: a discriminated union and a `QuerySort` field are compile-
7
- * time promises, and a server mapping a request body onto either supplies
8
- * raw JSON that no compiler has seen.
4
+ * The sanitizers a query passes through before any adapter sees it. A
5
+ * `QuerySort` field or a filter's discriminated union is a compile-time
6
+ * promise, and a server mapping a request onto either supplies raw JSON
7
+ * that no compiler has seen.
9
8
  *
10
9
  * These live in the invariant layer for the reason validation and
11
10
  * `_config` protection do — so no adapter can forget one. `assertQueryCapabilities`
@@ -16,8 +15,7 @@
16
15
  * the query — one rule, one answer.
17
16
  * See docs/spec/data-model.md § Capability-gated filters.
18
17
  */
19
- import type { ValidationError } from './validate.js';
20
- import type { Association, AssociationEdit, AuthorityAssociation, DataAssociation, GrantGrantee, JournalQuery, VersionsQuery, QuerySort, RecordFilter, RelationshipTarget, StackCapabilities } from './types.js';
18
+ import type { JournalQuery, QuerySort, RecordFilter, StackCapabilities, VersionsQuery } from './types/index.js';
21
19
  /**
22
20
  * Fail loud rather than silently widen: a filter the adapter can't honor
23
21
  * would otherwise be dropped, returning an unfiltered superset presented
@@ -26,6 +24,14 @@ import type { Association, AssociationEdit, AuthorityAssociation, DataAssociatio
26
24
  * § Capability-gated filters.
27
25
  */
28
26
  export declare function assertQueryCapabilities(filter: RecordFilter | undefined, capabilities: Pick<StackCapabilities, 'filter'>): void;
27
+ /**
28
+ * Hold `filter.contentByType` to a split along Types: at least one arm,
29
+ * each pinned to a TypeId and flat, and never beside a top-level content
30
+ * predicate, whose relation to the arms would be ambiguous. A map that
31
+ * could arrive empty would match everything once it crossed the wire. See
32
+ * docs/spec/data-model.md § Content by type.
33
+ */
34
+ export declare function assertValidContentByType(filter: RecordFilter | undefined): void;
29
35
  /**
30
36
  * Whether a single-segment content filter can be pushed down to the
31
37
  * adapter. Callers that read a content field pair this with an in-memory
@@ -42,15 +48,10 @@ export declare function filtersContent(features: Pick<StackCapabilities, 'filter
42
48
  */
43
49
  export declare function parseContentFilterKey(key: string): string[];
44
50
  /**
45
- * Reject a sort whose field or direction is outside the closed set the
46
- * types promise. `QuerySort` is typed `'asc' | 'desc'`, but a type is not a
47
- * runtime guard: a server mapping `?direction=` onto a query, or a
48
- * delegated app calling query(), supplies a raw string. A SQLite record
49
- * adapter interpolates the direction straight into `ORDER BY`, so an
50
- * unvalidated value there is a SQL-injection sink reachable from every
51
- * untrusted caller. Validating in the invariant layer — the same reason
52
- * emission and _config protection live here — means no adapter can forget
53
- * it. See docs/spec/data-model.md § Sorting and pagination.
51
+ * Reject a sort outside the closed set the types promise. A type is not a
52
+ * runtime guard, and a SQLite adapter interpolates the direction straight
53
+ * into `ORDER BY`, so an unvalidated one is an injection sink reachable by
54
+ * any untrusted caller. See docs/spec/data-model.md § Sorting and pagination.
54
55
  */
55
56
  export declare function assertValidSort(sort: QuerySort | undefined): void;
56
57
  /**
@@ -71,72 +72,6 @@ export declare function normalizeSort(sort: QuerySort | undefined): (QuerySort &
71
72
  * — see docs/spec/data-model.md § Capability-gated filters.
72
73
  */
73
74
  export declare function assertSortCapability(sort: QuerySort | undefined, capabilities: Pick<StackCapabilities, 'sort'>): void;
74
- /** Every key each relationship target arm defines. */
75
- export declare const TARGET_KEYS: Record<RelationshipTarget['kind'], readonly string[]>;
76
- /** Every key each grantee arm defines, the default tier included. */
77
- export declare const GRANTEE_KEYS: Record<GrantGrantee['kind'], readonly string[]>;
78
- /**
79
- * The keys of `value` its arm does not define. An element carrying one is
80
- * refused rather than stored: an adapter keeps only the keys it has
81
- * columns for, so the rest would answer 200 and then vanish.
82
- * See docs/spec/data-model.md § Associations.
83
- */
84
- export declare function unknownKeys(value: object, keys: readonly string[]): string[];
85
- /** unknownKeys() as a refusal. 400, not 422: the key addresses nothing. */
86
- export declare function assertKnownKeys(value: object, keys: readonly string[], path: string): void;
87
- /**
88
- * Reject a relationship target outside the closed set the types promise.
89
- * A discriminated union is not a runtime guard — a server mapping a
90
- * request body onto an association supplies raw JSON — and an
91
- * unrecognized kind would otherwise be stored under the one arm that
92
- * names a Record in this stack. See docs/spec/data-model.md
93
- * § Relationship targets.
94
- *
95
- * A key the element's kind does not define is thrown as a 400 rather than
96
- * collected, at every depth: it addresses nothing, the way an unknown key
97
- * on a request body does. See docs/spec/data-model.md § Associations.
98
- */
99
- export declare function validateAssociation(association: Association, path?: string): ValidationError[];
100
- /**
101
- * Refuse an authority element reaching the data half of the partition.
102
- * The two share a table, a delta shape and a durability tier; they never
103
- * share a call, because an app editing tags would otherwise be able to
104
- * replace an ACL it was never shown. Thrown rather than collected: the
105
- * caller named the wrong surface, not a malformed value, and the verb it
106
- * wanted is `grantAccess()`/`revokeAccess()`.
107
- *
108
- * Lives here, in the invariant layer, so an unscoped `Stack`, an import
109
- * and a server mapping a request body are all held to it.
110
- * See docs/spec/access-control.md § Record-level permissions.
111
- */
112
- export declare function assertDataAssociations(associations: readonly Association[], surface: string): asserts associations is DataAssociation[];
113
- /**
114
- * The mirror of assertDataAssociations(): the `permissions` surface takes
115
- * authority kinds alone, so a tag routed through it is refused rather than
116
- * quietly becoming an ACL entry the `associations` projection never shows.
117
- */
118
- export declare function assertAuthorityAssociations(permissions: readonly Association[], surface: string): asserts permissions is AuthorityAssociation[];
119
- /** validateAssociation() over a create's `associations` array. */
120
- /**
121
- * Every association in a list, plus the one rule a list has that a single
122
- * association does not: **identities are distinct**. A list naming one
123
- * identity twice describes a state no store can hold — an adapter keys
124
- * associations by identity, so the second entry displaces the first — and
125
- * which of the two the record ends up with is a question the caller did
126
- * not mean to ask. Refused rather than collapsed, for the reason an empty
127
- * change set is refused: every way of producing one is a caller bug.
128
- * See docs/spec/data-model.md § Associations.
129
- */
130
- export declare function validateAssociations(associations: Association[] | undefined, path?: string): ValidationError[];
131
- /**
132
- * Hold an association edit list to the rules every verb shares: non-empty,
133
- * every element a known `op` over a well-formed association, one surface,
134
- * and each identity named once — a list that both removes and adds one
135
- * identity is the same ambiguity as naming it twice. `repoint` is the
136
- * journal's word, never a request. Asked of the whole list before anything
137
- * is read or written. See docs/spec/data-model.md § Mutations.
138
- */
139
- export declare function assertAssociationEdits(changes: unknown, surface: string, half: 'data' | 'authority'): asserts changes is AssociationEdit[];
140
75
  /**
141
76
  * Reject an association filter that names neither of its halves, or whose
142
77
  * relationship target is malformed. `RelatedToFilter` and `AttachmentFilter`
@@ -145,6 +80,12 @@ export declare function assertAssociationEdits(changes: unknown, surface: string
145
80
  * any association of that kind. See docs/spec/data-model.md § Filter.
146
81
  */
147
82
  export declare function assertValidAssociationFilters(filter: RecordFilter | undefined): void;
83
+ /**
84
+ * Refuse a `baseId` argument that cannot name a type family, as an
85
+ * argument error prefixed with the `surface` it was passed to. See
86
+ * familyIdProblem().
87
+ */
88
+ export declare function assertFamilyId(baseId: unknown, surface: string): void;
148
89
  /**
149
90
  * Refuse a `baseId` carrying an `@version` suffix. A family filter resolves
150
91
  * against registered families, so a TypeId there would match nothing and
@@ -154,17 +95,10 @@ export declare function assertValidBaseIdFilter(filter: {
154
95
  baseId?: string | string[];
155
96
  } | undefined): void;
156
97
  /**
157
- * Hold a journal window to the shape both adapters can honor identically.
158
- *
159
- * Unvalidated, a negative `limit` diverges rather than failing: a JS
160
- * `slice(0, -1)` drops the newest entry, while SQLite reads a negative
161
- * LIMIT as "no ceiling" and returns the whole log. Neither is what the
162
- * caller asked for, and the disagreement is invisible until a stack
163
- * changes adapters. Refuse at the surface so no adapter has to guess.
164
- *
165
- * No ceiling is imposed: unlike a query, omitting `limit` reads the whole
166
- * log by contract, so a clamp would silently truncate exactly the caller
167
- * reconstructing an association's full history.
98
+ * Hold a journal window to a shape both adapters honor identically: a
99
+ * negative `limit` drops the newest entry from a JS slice but reads as no
100
+ * ceiling in SQLite. No ceiling is imposed — omitting `limit` reads the
101
+ * whole log by contract, which a clamp would silently truncate.
168
102
  */
169
103
  export declare function assertValidJournalQuery(query: JournalQuery | undefined): void;
170
104
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"query-validation.d.ts","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-validation.d.ts","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,YAAY,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,GAC9C,IAAI,CAsDN;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAgD/E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,GAAG,OAAO,CAEnF;AAKD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB3D;AAaD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAsBjE;AAsDD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,GAAG,SAAS,GAC1B,CAAC,SAAS,GAAG;IAAE,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAKzD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,YAAY,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAC5C,IAAI,CAiCN;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAmBpF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAKrE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,CAOhG;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAW7E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAW/E"}