ultimabase 0.0.0-stage → 0.1.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.
Files changed (411) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +4 -2
  3. package/dist/access.d.ts +62 -0
  4. package/dist/access.d.ts.map +1 -0
  5. package/dist/access.js +258 -0
  6. package/dist/adapter-errors.d.ts +43 -0
  7. package/dist/adapter-errors.d.ts.map +1 -0
  8. package/dist/adapter-errors.js +72 -0
  9. package/dist/adapter-json.d.ts +20 -0
  10. package/dist/adapter-json.d.ts.map +1 -0
  11. package/dist/adapter-json.js +2 -0
  12. package/dist/adapter-migrations.d.ts +90 -0
  13. package/dist/adapter-migrations.d.ts.map +1 -0
  14. package/dist/adapter-migrations.js +1 -0
  15. package/dist/adapter.d.ts +333 -0
  16. package/dist/adapter.d.ts.map +1 -0
  17. package/dist/adapter.js +5 -0
  18. package/dist/aggregate.d.ts +31 -0
  19. package/dist/aggregate.d.ts.map +1 -0
  20. package/dist/aggregate.js +99 -0
  21. package/dist/app-internals.d.ts +10 -0
  22. package/dist/app-internals.d.ts.map +1 -0
  23. package/dist/app-internals.js +12 -0
  24. package/dist/app-options.d.ts +22 -0
  25. package/dist/app-options.d.ts.map +1 -0
  26. package/dist/app-options.js +3 -0
  27. package/dist/cascade.d.ts +47 -0
  28. package/dist/cascade.d.ts.map +1 -0
  29. package/dist/cascade.js +209 -0
  30. package/dist/cli-config.d.ts +6 -0
  31. package/dist/cli-config.d.ts.map +1 -0
  32. package/dist/cli-config.js +45 -0
  33. package/dist/cli-deploy.d.ts +14 -0
  34. package/dist/cli-deploy.d.ts.map +1 -0
  35. package/dist/cli-deploy.js +193 -0
  36. package/dist/cli-main.d.ts +15 -0
  37. package/dist/cli-main.d.ts.map +1 -0
  38. package/dist/cli-main.js +155 -0
  39. package/dist/cli-migrate.d.ts +20 -0
  40. package/dist/cli-migrate.d.ts.map +1 -0
  41. package/dist/cli-migrate.js +105 -0
  42. package/dist/cli.d.ts +3 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +4 -0
  45. package/dist/complete.d.ts +13 -0
  46. package/dist/complete.d.ts.map +1 -0
  47. package/dist/complete.js +60 -0
  48. package/dist/console-logger.d.ts +3 -0
  49. package/dist/console-logger.d.ts.map +1 -0
  50. package/dist/console-logger.js +62 -0
  51. package/dist/create-many.d.ts +7 -0
  52. package/dist/create-many.d.ts.map +1 -0
  53. package/dist/create-many.js +88 -0
  54. package/dist/decimal.d.ts +23 -0
  55. package/dist/decimal.d.ts.map +1 -0
  56. package/dist/decimal.js +50 -0
  57. package/dist/define-app.d.ts +59 -0
  58. package/dist/define-app.d.ts.map +1 -0
  59. package/dist/define-app.js +5 -0
  60. package/dist/define-enum.d.ts +6 -0
  61. package/dist/define-enum.d.ts.map +1 -0
  62. package/dist/define-enum.js +18 -0
  63. package/dist/define-function.d.ts +25 -0
  64. package/dist/define-function.d.ts.map +1 -0
  65. package/dist/define-function.js +111 -0
  66. package/dist/define-model.d.ts +48 -0
  67. package/dist/define-model.d.ts.map +1 -0
  68. package/dist/define-model.js +85 -0
  69. package/dist/definition.d.ts +179 -0
  70. package/dist/definition.d.ts.map +1 -0
  71. package/dist/definition.js +165 -0
  72. package/dist/delete-many.d.ts +13 -0
  73. package/dist/delete-many.d.ts.map +1 -0
  74. package/dist/delete-many.js +58 -0
  75. package/dist/engine.d.ts +16 -0
  76. package/dist/engine.d.ts.map +1 -0
  77. package/dist/engine.js +174 -0
  78. package/dist/errors.d.ts +50 -0
  79. package/dist/errors.d.ts.map +1 -0
  80. package/dist/errors.js +43 -0
  81. package/dist/exact.d.ts +20 -0
  82. package/dist/exact.d.ts.map +1 -0
  83. package/dist/exact.js +1 -0
  84. package/dist/feed.d.ts +6 -0
  85. package/dist/feed.d.ts.map +1 -0
  86. package/dist/feed.js +33 -0
  87. package/dist/field-codec.d.ts +11 -0
  88. package/dist/field-codec.d.ts.map +1 -0
  89. package/dist/field-codec.js +48 -0
  90. package/dist/field-rules.d.ts +57 -0
  91. package/dist/field-rules.d.ts.map +1 -0
  92. package/dist/field-rules.js +1 -0
  93. package/dist/field-type.d.ts +51 -0
  94. package/dist/field-type.d.ts.map +1 -0
  95. package/dist/field-type.js +106 -0
  96. package/dist/fields.d.ts +295 -0
  97. package/dist/fields.d.ts.map +1 -0
  98. package/dist/fields.js +1 -0
  99. package/dist/function.d.ts +126 -0
  100. package/dist/function.d.ts.map +1 -0
  101. package/dist/function.js +1 -0
  102. package/dist/functions.d.ts +18 -0
  103. package/dist/functions.d.ts.map +1 -0
  104. package/dist/functions.js +99 -0
  105. package/dist/group-by.d.ts +10 -0
  106. package/dist/group-by.d.ts.map +1 -0
  107. package/dist/group-by.js +145 -0
  108. package/dist/group-having.d.ts +8 -0
  109. package/dist/group-having.d.ts.map +1 -0
  110. package/dist/group-having.js +97 -0
  111. package/dist/hooks.d.ts +41 -0
  112. package/dist/hooks.d.ts.map +1 -0
  113. package/dist/hooks.js +149 -0
  114. package/dist/hosts.d.ts +3 -0
  115. package/dist/hosts.d.ts.map +1 -0
  116. package/dist/hosts.js +8 -0
  117. package/dist/identify.d.ts +15 -0
  118. package/dist/identify.d.ts.map +1 -0
  119. package/dist/identify.js +71 -0
  120. package/dist/index.d.ts +25 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +12 -0
  123. package/dist/internal.d.ts +28 -0
  124. package/dist/internal.d.ts.map +1 -0
  125. package/dist/internal.js +39 -0
  126. package/dist/lifecycle.d.ts +21 -0
  127. package/dist/lifecycle.d.ts.map +1 -0
  128. package/dist/lifecycle.js +149 -0
  129. package/dist/list-update.d.ts +12 -0
  130. package/dist/list-update.d.ts.map +1 -0
  131. package/dist/list-update.js +52 -0
  132. package/dist/live.d.ts +37 -0
  133. package/dist/live.d.ts.map +1 -0
  134. package/dist/live.js +139 -0
  135. package/dist/manifest.d.ts +11 -0
  136. package/dist/manifest.d.ts.map +1 -0
  137. package/dist/manifest.js +60 -0
  138. package/dist/memory-aggregate.d.ts +7 -0
  139. package/dist/memory-aggregate.d.ts.map +1 -0
  140. package/dist/memory-aggregate.js +107 -0
  141. package/dist/memory-conditions.d.ts +8 -0
  142. package/dist/memory-conditions.d.ts.map +1 -0
  143. package/dist/memory-conditions.js +82 -0
  144. package/dist/memory-draft.d.ts +34 -0
  145. package/dist/memory-draft.d.ts.map +1 -0
  146. package/dist/memory-draft.js +255 -0
  147. package/dist/memory-json.d.ts +6 -0
  148. package/dist/memory-json.d.ts.map +1 -0
  149. package/dist/memory-json.js +86 -0
  150. package/dist/memory-read.d.ts +45 -0
  151. package/dist/memory-read.d.ts.map +1 -0
  152. package/dist/memory-read.js +244 -0
  153. package/dist/memory-search.d.ts +16 -0
  154. package/dist/memory-search.d.ts.map +1 -0
  155. package/dist/memory-search.js +110 -0
  156. package/dist/memory-values.d.ts +23 -0
  157. package/dist/memory-values.d.ts.map +1 -0
  158. package/dist/memory-values.js +82 -0
  159. package/dist/memory.d.ts +4 -0
  160. package/dist/memory.d.ts.map +1 -0
  161. package/dist/memory.js +157 -0
  162. package/dist/migrate.d.ts +22 -0
  163. package/dist/migrate.d.ts.map +1 -0
  164. package/dist/migrate.js +131 -0
  165. package/dist/model.d.ts +239 -0
  166. package/dist/model.d.ts.map +1 -0
  167. package/dist/model.js +1 -0
  168. package/dist/nested-write.d.ts +64 -0
  169. package/dist/nested-write.d.ts.map +1 -0
  170. package/dist/nested-write.js +274 -0
  171. package/dist/number-update.d.ts +18 -0
  172. package/dist/number-update.d.ts.map +1 -0
  173. package/dist/number-update.js +96 -0
  174. package/dist/plugin-app.d.ts +48 -0
  175. package/dist/plugin-app.d.ts.map +1 -0
  176. package/dist/plugin-app.js +230 -0
  177. package/dist/plugin-code.d.ts +17 -0
  178. package/dist/plugin-code.d.ts.map +1 -0
  179. package/dist/plugin-code.js +125 -0
  180. package/dist/plugin-use.d.ts +22 -0
  181. package/dist/plugin-use.d.ts.map +1 -0
  182. package/dist/plugin-use.js +161 -0
  183. package/dist/plugin.d.ts +357 -0
  184. package/dist/plugin.d.ts.map +1 -0
  185. package/dist/plugin.js +17 -0
  186. package/dist/query-aggregate.d.ts +82 -0
  187. package/dist/query-aggregate.d.ts.map +1 -0
  188. package/dist/query-aggregate.js +1 -0
  189. package/dist/query-args.d.ts +41 -0
  190. package/dist/query-args.d.ts.map +1 -0
  191. package/dist/query-args.js +263 -0
  192. package/dist/query-bulk.d.ts +35 -0
  193. package/dist/query-bulk.d.ts.map +1 -0
  194. package/dist/query-bulk.js +1 -0
  195. package/dist/query-conditions.d.ts +9 -0
  196. package/dist/query-conditions.d.ts.map +1 -0
  197. package/dist/query-conditions.js +46 -0
  198. package/dist/query-context.d.ts +32 -0
  199. package/dist/query-context.d.ts.map +1 -0
  200. package/dist/query-context.js +55 -0
  201. package/dist/query-filter.d.ts +46 -0
  202. package/dist/query-filter.d.ts.map +1 -0
  203. package/dist/query-filter.js +1 -0
  204. package/dist/query-group.d.ts +82 -0
  205. package/dist/query-group.d.ts.map +1 -0
  206. package/dist/query-group.js +1 -0
  207. package/dist/query-json.d.ts +9 -0
  208. package/dist/query-json.d.ts.map +1 -0
  209. package/dist/query-json.js +66 -0
  210. package/dist/query-order.d.ts +15 -0
  211. package/dist/query-order.d.ts.map +1 -0
  212. package/dist/query-order.js +115 -0
  213. package/dist/query-project.d.ts +15 -0
  214. package/dist/query-project.d.ts.map +1 -0
  215. package/dist/query-project.js +45 -0
  216. package/dist/query-search.d.ts +24 -0
  217. package/dist/query-search.d.ts.map +1 -0
  218. package/dist/query-search.js +2 -0
  219. package/dist/query-values.d.ts +28 -0
  220. package/dist/query-values.d.ts.map +1 -0
  221. package/dist/query-values.js +91 -0
  222. package/dist/query-where.d.ts +46 -0
  223. package/dist/query-where.d.ts.map +1 -0
  224. package/dist/query-where.js +200 -0
  225. package/dist/query-write.d.ts +14 -0
  226. package/dist/query-write.d.ts.map +1 -0
  227. package/dist/query-write.js +260 -0
  228. package/dist/query.d.ts +254 -0
  229. package/dist/query.d.ts.map +1 -0
  230. package/dist/query.js +1 -0
  231. package/dist/record.d.ts +257 -0
  232. package/dist/record.d.ts.map +1 -0
  233. package/dist/record.js +1 -0
  234. package/dist/recorder.d.ts +32 -0
  235. package/dist/recorder.d.ts.map +1 -0
  236. package/dist/recorder.js +152 -0
  237. package/dist/relation-write.d.ts +41 -0
  238. package/dist/relation-write.d.ts.map +1 -0
  239. package/dist/relation-write.js +112 -0
  240. package/dist/relations.d.ts +42 -0
  241. package/dist/relations.d.ts.map +1 -0
  242. package/dist/relations.js +119 -0
  243. package/dist/rules.d.ts +97 -0
  244. package/dist/rules.d.ts.map +1 -0
  245. package/dist/rules.js +71 -0
  246. package/dist/running.d.ts +29 -0
  247. package/dist/running.d.ts.map +1 -0
  248. package/dist/running.js +39 -0
  249. package/dist/schema-indexes.d.ts +11 -0
  250. package/dist/schema-indexes.d.ts.map +1 -0
  251. package/dist/schema-indexes.js +59 -0
  252. package/dist/schema-virtuals.d.ts +19 -0
  253. package/dist/schema-virtuals.d.ts.map +1 -0
  254. package/dist/schema-virtuals.js +100 -0
  255. package/dist/schema.d.ts +35 -0
  256. package/dist/schema.d.ts.map +1 -0
  257. package/dist/schema.js +267 -0
  258. package/dist/scope.d.ts +46 -0
  259. package/dist/scope.d.ts.map +1 -0
  260. package/dist/scope.js +82 -0
  261. package/dist/scratch.d.ts +14 -0
  262. package/dist/scratch.d.ts.map +1 -0
  263. package/dist/scratch.js +10 -0
  264. package/dist/serve.d.ts +2 -0
  265. package/dist/serve.d.ts.map +1 -0
  266. package/dist/serve.js +4 -0
  267. package/dist/symbols.d.ts +10 -0
  268. package/dist/symbols.d.ts.map +1 -0
  269. package/dist/symbols.js +1 -0
  270. package/dist/transaction.d.ts +28 -0
  271. package/dist/transaction.d.ts.map +1 -0
  272. package/dist/transaction.js +156 -0
  273. package/dist/types.d.ts +58 -0
  274. package/dist/types.d.ts.map +1 -0
  275. package/dist/types.js +1 -0
  276. package/dist/update-many.d.ts +7 -0
  277. package/dist/update-many.d.ts.map +1 -0
  278. package/dist/update-many.js +182 -0
  279. package/dist/uuid.d.ts +7 -0
  280. package/dist/uuid.d.ts.map +1 -0
  281. package/dist/uuid.js +48 -0
  282. package/dist/validation.d.ts +24 -0
  283. package/dist/validation.d.ts.map +1 -0
  284. package/dist/validation.js +72 -0
  285. package/dist/virtual-read.d.ts +9 -0
  286. package/dist/virtual-read.d.ts.map +1 -0
  287. package/dist/virtual-read.js +145 -0
  288. package/dist/virtual.d.ts +142 -0
  289. package/dist/virtual.d.ts.map +1 -0
  290. package/dist/virtual.js +1 -0
  291. package/dist/write-context.d.ts +46 -0
  292. package/dist/write-context.d.ts.map +1 -0
  293. package/dist/write-context.js +102 -0
  294. package/dist/write-data.d.ts +26 -0
  295. package/dist/write-data.d.ts.map +1 -0
  296. package/dist/write-data.js +144 -0
  297. package/dist/write-plan.d.ts +107 -0
  298. package/dist/write-plan.d.ts.map +1 -0
  299. package/dist/write-plan.js +170 -0
  300. package/dist/write-target.d.ts +17 -0
  301. package/dist/write-target.d.ts.map +1 -0
  302. package/dist/write-target.js +59 -0
  303. package/dist/writes.d.ts +23 -0
  304. package/dist/writes.d.ts.map +1 -0
  305. package/dist/writes.js +246 -0
  306. package/dist/writing.d.ts +10 -0
  307. package/dist/writing.d.ts.map +1 -0
  308. package/dist/writing.js +66 -0
  309. package/package.json +42 -3
  310. package/src/access.ts +329 -0
  311. package/src/adapter-errors.ts +89 -0
  312. package/src/adapter-json.ts +21 -0
  313. package/src/adapter-migrations.ts +98 -0
  314. package/src/adapter.ts +363 -0
  315. package/src/aggregate.ts +136 -0
  316. package/src/app-internals.ts +26 -0
  317. package/src/app-options.ts +24 -0
  318. package/src/cascade.ts +297 -0
  319. package/src/cli-config.ts +45 -0
  320. package/src/cli-deploy.ts +235 -0
  321. package/src/cli-main.ts +166 -0
  322. package/src/cli-migrate.ts +143 -0
  323. package/src/cli.ts +5 -0
  324. package/src/complete.ts +73 -0
  325. package/src/console-logger.ts +87 -0
  326. package/src/create-many.ts +126 -0
  327. package/src/decimal.ts +74 -0
  328. package/src/define-app.ts +108 -0
  329. package/src/define-enum.ts +26 -0
  330. package/src/define-function.ts +188 -0
  331. package/src/define-model.ts +220 -0
  332. package/src/definition.ts +352 -0
  333. package/src/delete-many.ts +76 -0
  334. package/src/engine.ts +281 -0
  335. package/src/errors.ts +97 -0
  336. package/src/exact.ts +49 -0
  337. package/src/feed.ts +39 -0
  338. package/src/field-codec.ts +72 -0
  339. package/src/field-rules.ts +77 -0
  340. package/src/field-type.ts +219 -0
  341. package/src/fields.ts +383 -0
  342. package/src/function.ts +143 -0
  343. package/src/functions.ts +154 -0
  344. package/src/group-by.ts +186 -0
  345. package/src/group-having.ts +143 -0
  346. package/src/hooks.ts +215 -0
  347. package/src/hosts.ts +11 -0
  348. package/src/identify.ts +95 -0
  349. package/src/index.ts +125 -0
  350. package/src/internal.ts +68 -0
  351. package/src/lifecycle.ts +214 -0
  352. package/src/list-update.ts +71 -0
  353. package/src/live.ts +199 -0
  354. package/src/manifest.ts +71 -0
  355. package/src/memory-aggregate.ts +162 -0
  356. package/src/memory-conditions.ts +88 -0
  357. package/src/memory-draft.ts +319 -0
  358. package/src/memory-json.ts +91 -0
  359. package/src/memory-read.ts +311 -0
  360. package/src/memory-search.ts +149 -0
  361. package/src/memory-values.ts +106 -0
  362. package/src/memory.ts +173 -0
  363. package/src/migrate.ts +152 -0
  364. package/src/model.ts +312 -0
  365. package/src/nested-write.ts +390 -0
  366. package/src/number-update.ts +142 -0
  367. package/src/plugin-app.ts +308 -0
  368. package/src/plugin-code.ts +158 -0
  369. package/src/plugin-use.ts +217 -0
  370. package/src/plugin.ts +400 -0
  371. package/src/query-aggregate.ts +96 -0
  372. package/src/query-args.ts +375 -0
  373. package/src/query-bulk.ts +53 -0
  374. package/src/query-conditions.ts +53 -0
  375. package/src/query-context.ts +104 -0
  376. package/src/query-filter.ts +54 -0
  377. package/src/query-group.ts +137 -0
  378. package/src/query-json.ts +90 -0
  379. package/src/query-order.ts +158 -0
  380. package/src/query-project.ts +73 -0
  381. package/src/query-search.ts +31 -0
  382. package/src/query-values.ts +131 -0
  383. package/src/query-where.ts +318 -0
  384. package/src/query-write.ts +360 -0
  385. package/src/query.ts +400 -0
  386. package/src/record.ts +379 -0
  387. package/src/recorder.ts +212 -0
  388. package/src/relation-write.ts +176 -0
  389. package/src/relations.ts +165 -0
  390. package/src/rules.ts +188 -0
  391. package/src/running.ts +62 -0
  392. package/src/schema-indexes.ts +88 -0
  393. package/src/schema-virtuals.ts +134 -0
  394. package/src/schema.ts +367 -0
  395. package/src/scope.ts +123 -0
  396. package/src/scratch.ts +28 -0
  397. package/src/serve.ts +5 -0
  398. package/src/symbols.ts +11 -0
  399. package/src/transaction.ts +211 -0
  400. package/src/types.ts +79 -0
  401. package/src/update-many.ts +268 -0
  402. package/src/uuid.ts +51 -0
  403. package/src/validation.ts +107 -0
  404. package/src/virtual-read.ts +198 -0
  405. package/src/virtual.ts +187 -0
  406. package/src/write-context.ts +170 -0
  407. package/src/write-data.ts +188 -0
  408. package/src/write-plan.ts +273 -0
  409. package/src/write-target.ts +92 -0
  410. package/src/writes.ts +361 -0
  411. package/src/writing.ts +93 -0
@@ -0,0 +1,58 @@
1
+ import { cascadeOf, cascadeWhere } from './cascade.js';
2
+ import { settle } from './hooks.js';
3
+ import { filtered, given } from './query-context.js';
4
+ import { byIds } from './query-where.js';
5
+ import { checkedWrite, guarded } from './write-target.js';
6
+ import { cascaded, writingOf } from './writing.js';
7
+ export async function removeMany(context, store, commits, args) {
8
+ const { models, model, scope } = context;
9
+ const found = given(args, model.name, ['where'], []);
10
+ const where = (await filtered(context, found, 'delete')) ?? {};
11
+ const reach = cascadeWhere(models, model, where);
12
+ if (reach !== undefined && scope.access === undefined) {
13
+ // The write reads its rows as they were, to count them (D-102).
14
+ const read = { model: model.name, where };
15
+ const { checks } = reach;
16
+ const rows = await guarded(store.last({
17
+ checks: checks.map(({ check }) => check),
18
+ changes: reach.changes,
19
+ read,
20
+ before: true,
21
+ }), checks);
22
+ return { count: rows.length };
23
+ }
24
+ // In id order, so two calls on the same rows wait instead of deadlocking.
25
+ const orderBy = [{ field: 'id', direction: 'asc' }];
26
+ const rows = await store.find({
27
+ model: model.name,
28
+ where,
29
+ orderBy,
30
+ lock: true,
31
+ });
32
+ // One row refused, none deleted (D-111).
33
+ for (const row of rows)
34
+ scope.access?.allow(model, 'delete', { record: row });
35
+ if (rows.length > 0)
36
+ await deleted(context, store, commits, rows);
37
+ return { count: rows.length };
38
+ }
39
+ /**
40
+ * Deletes `rows`, which the caller may delete, as `delete` does: in one write
41
+ * when nothing runs (D-102), else with their cascade or redirect, then the
42
+ * hooks.
43
+ */
44
+ export async function deleted(context, store, commits, rows) {
45
+ const { models, model, caller, scope } = context;
46
+ const locked = cascadeWhere(models, model, byIds(rows.map(({ id }) => id)));
47
+ if (locked !== undefined) {
48
+ await checkedWrite(store, locked.checks, locked.changes);
49
+ return;
50
+ }
51
+ const events = [];
52
+ const writing = writingOf(scope, store, events);
53
+ const cascade = await cascadeOf(models, model, rows, store);
54
+ const changes = await cascaded(writing, cascade);
55
+ if (changes.length > 0)
56
+ await checkedWrite(store, writing.checks, changes);
57
+ await settle(store, caller, events, commits);
58
+ }
@@ -0,0 +1,16 @@
1
+ import type { Identity } from './rules.ts';
2
+ import type { Read, Row } from './adapter.ts';
3
+ import type { Store } from './transaction.ts';
4
+ export type Operation = 'findMany' | 'findFirst' | 'findUnique' | 'findFirstOrThrow' | 'findUniqueOrThrow' | 'count' | 'aggregate' | 'groupBy' | 'create' | 'update' | 'upsert' | 'delete' | 'updateMany' | 'createMany' | 'updateManyAndReturn' | 'createManyAndReturn' | 'deleteMany' | 'upserted';
5
+ /**
6
+ * `{ as }` only; without it, the caller is anonymous (D-19). The kernel
7
+ * completes a user one (D-121).
8
+ */
9
+ export declare function callerOf(options: unknown, model: string): Identity;
10
+ /** Finds a read's root rows, decoded; a live read may serve them (D-154). */
11
+ export type RootFind = (store: Store, read: Read) => Promise<Row[]>;
12
+ /** Runs one query of a model of the running application. */
13
+ export declare function query(name: string, operation: Operation, args: unknown, options: unknown): Promise<unknown>;
14
+ /** `findMany(args)` as `options` says, its root rows found by `root` (D-154). */
15
+ export declare function rootFind(name: string, args: unknown, options: unknown, root: RootFind): Promise<unknown>;
16
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAU7C,OAAO,KAAK,EAAU,KAAK,EAAE,MAAM,kBAAkB,CAAA;AASrD,MAAM,MAAM,SAAS,GAClB,UAAU,GACV,WAAW,GACX,YAAY,GACZ,kBAAkB,GAClB,mBAAmB,GACnB,OAAO,GACP,WAAW,GACX,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,qBAAqB,GACrB,qBAAqB,GACrB,YAAY,GAEZ,UAAU,CAAA;AAIb;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAgClE;AAYD,6EAA6E;AAC7E,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;AAgJnE,4DAA4D;AAC5D,wBAAsB,KAAK,CAC1B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,OAAO,CAAC,CAelB;AAED,iFAAiF;AACjF,wBAAsB,QAAQ,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,QAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,CASlB"}
package/dist/engine.js ADDED
@@ -0,0 +1,174 @@
1
+ // The queries a model sends to the running application (D-18): each one
2
+ // checked, run on the adapter, in the open transaction if any (D-36), and
3
+ // returned in the shape it asked for.
4
+ import { accessFor, and } from './access.js';
5
+ import { InvalidQuery, PublicError } from './errors.js';
6
+ import { isMaster } from './rules.js';
7
+ import { current } from './running.js';
8
+ import { filtered, first, given, picked, shapedRows } from './query-context.js';
9
+ import { oneKeys, plan, restrict, uniqueWhere } from './query-args.js';
10
+ import { counted } from './virtual-read.js';
11
+ import { entries, isObject, unknownKey } from './query-where.js';
12
+ import { QueryScope, planned } from './scope.js';
13
+ import { reading, writing } from './transaction.js';
14
+ import { aggregate } from './aggregate.js';
15
+ import { distinctOf, groupBy } from './group-by.js';
16
+ import { removeMany } from './delete-many.js';
17
+ import { updateMany, updateManyAndReturn } from './update-many.js';
18
+ import { createMany, createManyAndReturn } from './create-many.js';
19
+ import { create, remove, update, upsert } from './writes.js';
20
+ const anonymous = Object.freeze({ kind: 'anonymous' });
21
+ /**
22
+ * `{ as }` only; without it, the caller is anonymous (D-19). The kernel
23
+ * completes a user one (D-121).
24
+ */
25
+ export function callerOf(options, model) {
26
+ if (options === undefined)
27
+ return anonymous;
28
+ const keys = new Map(entries(options, 'options'));
29
+ for (const key of keys.keys()) {
30
+ if (key !== 'as')
31
+ throw unknownKey(`options.${key}`, model);
32
+ }
33
+ const caller = keys.get('as');
34
+ if (caller === undefined)
35
+ return anonymous;
36
+ if (!isObject(caller)) {
37
+ throw new InvalidQuery('options.as', 'options.as must be a caller.');
38
+ }
39
+ switch (caller['kind']) {
40
+ case 'anonymous':
41
+ return anonymous;
42
+ case 'user':
43
+ if (!isObject(caller['user']) ||
44
+ typeof caller['user']['id'] !== 'string') {
45
+ throw new InvalidQuery('options.as', 'options.as.user must be { id }.');
46
+ }
47
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- the kernel reads only the id; the record's other fields are the server code's.
48
+ return caller;
49
+ case 'master':
50
+ // Only the kernel creates Master (D-19): a copy is a forgery.
51
+ if (!isMaster(caller)) {
52
+ throw new Error('options.as is a Master the kernel did not create.');
53
+ }
54
+ return caller;
55
+ default:
56
+ throw new InvalidQuery('options.as', 'options.as must be a caller.');
57
+ }
58
+ }
59
+ const manyKeys = new Set([
60
+ 'where',
61
+ ...oneKeys,
62
+ 'orderBy',
63
+ 'take',
64
+ 'skip',
65
+ 'cursor',
66
+ ]);
67
+ const distinctKeys = new Set([...manyKeys, 'distinct']);
68
+ const onStore = async (store, read) => store.find(read);
69
+ async function find(context, store, args, single, root = onStore) {
70
+ const { models, model, scope } = context;
71
+ const keys = single ? manyKeys : distinctKeys;
72
+ const { read, shape, readable } = await planned(scope, () => ({
73
+ ...plan(models, model, args, '', 'many', keys, scope),
74
+ readable: scope.readable(model.name),
75
+ }));
76
+ const take = read.take ?? 1;
77
+ const limited = single ? { ...read, take: Math.sign(take) } : read;
78
+ const distinct = single ? undefined : await distinctOf(context, args);
79
+ const rows = await root(store, {
80
+ model: model.name,
81
+ ...restrict(limited, readable),
82
+ ...(distinct && { distinct }),
83
+ });
84
+ if (single)
85
+ return first(context, store, rows, shape, scope.access);
86
+ return shapedRows(context, store, rows, shape, scope.access);
87
+ }
88
+ async function findUnique(context, store, args) {
89
+ const { models, model, scope } = context;
90
+ const found = given(args, model.name, ['where', ...oneKeys], ['where']);
91
+ const { read, shape, where } = await planned(scope, () => ({
92
+ ...plan(models, model, picked(found), '', 'one', oneKeys, scope),
93
+ where: and(uniqueWhere(models, model, found.get('where'), 'where', scope), scope.readable(model.name)),
94
+ }));
95
+ const rows = await store.find({ model: model.name, ...read, where });
96
+ return first(context, store, rows, shape, scope.access);
97
+ }
98
+ async function count(context, store, args) {
99
+ const { model } = context;
100
+ const where = await filtered(context, given(args, model.name, ['where'], []), 'read');
101
+ return store.count({ model: model.name, ...(where && { where }) });
102
+ }
103
+ /** The read, which fails with `NOT_FOUND` rather than return `null` (D-135). */
104
+ const orThrow = (read) => async (context, store, args) => {
105
+ const row = await read(context, store, args);
106
+ if (row !== null)
107
+ return row;
108
+ throw new PublicError('NOT_FOUND', `No ${context.model.name} matches.`);
109
+ };
110
+ const reads = {
111
+ findMany: async (context, store, args) => find(context, store, args, false),
112
+ findFirst: async (context, store, args) => find(context, store, args, true),
113
+ findUnique,
114
+ findFirstOrThrow: orThrow(async (context, store, args) => find(context, store, args, true)),
115
+ findUniqueOrThrow: orThrow(findUnique),
116
+ count,
117
+ aggregate,
118
+ groupBy,
119
+ };
120
+ const writes = {
121
+ create,
122
+ update,
123
+ upsert: async (context, store, commits, args) => (await upsert(context, store, commits, args)).row,
124
+ upserted: upsert,
125
+ delete: remove,
126
+ updateMany,
127
+ createMany,
128
+ updateManyAndReturn,
129
+ createManyAndReturn,
130
+ deleteMany: removeMany,
131
+ };
132
+ function isRead(operation) {
133
+ return Object.hasOwn(reads, operation);
134
+ }
135
+ /** The running application and its model `name`. */
136
+ function runningModel(name) {
137
+ const app = current();
138
+ const model = app?.resolved.models.get(name);
139
+ if (app === undefined || model === undefined) {
140
+ throw new Error(`${name} is not a model of a started application.`);
141
+ }
142
+ return { app, model };
143
+ }
144
+ async function contextOf(app, model, identity) {
145
+ const caller = await app.complete(identity);
146
+ const { models } = app.resolved;
147
+ const access = accessFor(models, caller, app.logger);
148
+ const scope = new QueryScope(models, caller, access);
149
+ return { app, models, model, caller, scope };
150
+ }
151
+ /** Runs one query of a model of the running application. */
152
+ export async function query(name, operation, args, options) {
153
+ const { app, model } = runningModel(name);
154
+ const identity = callerOf(options, name);
155
+ counted();
156
+ return app.work.run(async () => {
157
+ const context = await contextOf(app, model, identity);
158
+ if (isRead(operation)) {
159
+ const read = reads[operation];
160
+ return reading(app, async (store) => read(context, store, args));
161
+ }
162
+ const write = writes[operation];
163
+ return writing(app, async (store, commits) => write(context, store, commits, args));
164
+ });
165
+ }
166
+ /** `findMany(args)` as `options` says, its root rows found by `root` (D-154). */
167
+ export async function rootFind(name, args, options, root) {
168
+ const { app, model } = runningModel(name);
169
+ const identity = callerOf(options, name);
170
+ return app.work.run(async () => {
171
+ const context = await contextOf(app, model, identity);
172
+ return reading(app, async (store) => find(context, store, args, false, root));
173
+ });
174
+ }
@@ -0,0 +1,50 @@
1
+ import type { JsonValue } from './fields.ts';
2
+ /** The kernel's codes; a transport gives each its own status (D-72). */
3
+ export type ErrorCode = 'ACCESS_DENIED' | 'NOT_FOUND' | 'VALIDATION_FAILED' | 'UNIQUE_VIOLATION' | 'RELATION_RESTRICTED' | 'UNAUTHENTICATED' | 'INVALID_CREDENTIALS' | 'TOO_MANY_ATTEMPTS' | 'INTERNAL';
4
+ /** One failing value, as Standard Schema reports it (D-23). */
5
+ export type Issue = {
6
+ readonly path: readonly (string | number)[];
7
+ readonly message: string;
8
+ };
9
+ type Details<C> = C extends 'VALIDATION_FAILED' ? {
10
+ readonly issues: readonly Issue[];
11
+ } : C extends 'TOO_MANY_ATTEMPTS' ? {
12
+ readonly retryAfter: number;
13
+ } : JsonValue;
14
+ /** An error whose code, message and details reach the client. */
15
+ export interface PublicError extends Error {
16
+ readonly code: ErrorCode | Uppercase<string>;
17
+ readonly details?: JsonValue;
18
+ }
19
+ type PublicErrorConstructor = {
20
+ new <const C extends string>(code: C extends Uppercase<C> ? C : Uppercase<C>, message: string, options?: {
21
+ readonly details?: Details<C>;
22
+ readonly cause?: unknown;
23
+ }): PublicError;
24
+ readonly prototype: PublicError;
25
+ };
26
+ /**
27
+ * The code is a kernel code, which keeps its meaning, or the application's
28
+ * own, in capitals. Only the constructor is generic: `instanceof` would type
29
+ * a generic class's members as `any`.
30
+ */
31
+ export declare const PublicError: PublicErrorConstructor;
32
+ /**
33
+ * A query argument the kernel does not know (D-20): a bug of the server
34
+ * code, never public.
35
+ */
36
+ export declare class InvalidQuery extends Error {
37
+ readonly code = "INVALID_QUERY";
38
+ readonly path: string;
39
+ constructor(path: string, message: string);
40
+ }
41
+ /**
42
+ * A configuration refused while the application is defined or starts, whose
43
+ * message says what is wrong and how to fix it: a command prints it without
44
+ * its stack (D-119).
45
+ */
46
+ export declare class Refused extends Error {
47
+ constructor(message: string, options?: ErrorOptions);
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAClB,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,UAAU,CAAA;AAEb,+DAA+D;AAC/D,MAAM,MAAM,KAAK,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,mBAAmB,GAC5C;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GACrC,CAAC,SAAS,mBAAmB,GAC5B;IAA6B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1D,SAAS,CAAA;AAEb,iEAAiE;AACjE,MAAM,WAAW,WAAY,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAC5B;AAED,KAAK,sBAAsB,GAAG;IAC7B,KAAK,KAAK,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAC/C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACnE,WAAW,CAAA;IACd,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAA;CAC/B,CAAA;AAqBD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,sBAE4B,CAAA;AAEtD;;;GAGG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,mBAAkB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAIxC;CACD;AAED;;;;GAIG;AACH,qBAAa,OAAQ,SAAQ,KAAK;IACjC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACD"}
package/dist/errors.js ADDED
@@ -0,0 +1,43 @@
1
+ class PublicErrorClass extends Error {
2
+ code;
3
+ details;
4
+ constructor(code, message, options) {
5
+ super(message, options && 'cause' in options ? { cause: options.cause } : {});
6
+ this.name = 'PublicError';
7
+ this.code = code;
8
+ if (options?.details !== undefined)
9
+ this.details = options.details;
10
+ }
11
+ }
12
+ /**
13
+ * The code is a kernel code, which keeps its meaning, or the application's
14
+ * own, in capitals. Only the constructor is generic: `instanceof` would type
15
+ * a generic class's members as `any`.
16
+ */
17
+ export const PublicError =
18
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- the class is the constructor; only its generic signature is added.
19
+ PublicErrorClass;
20
+ /**
21
+ * A query argument the kernel does not know (D-20): a bug of the server
22
+ * code, never public.
23
+ */
24
+ export class InvalidQuery extends Error {
25
+ code = 'INVALID_QUERY';
26
+ path;
27
+ constructor(path, message) {
28
+ super(message);
29
+ this.name = 'InvalidQuery';
30
+ this.path = path;
31
+ }
32
+ }
33
+ /**
34
+ * A configuration refused while the application is defined or starts, whose
35
+ * message says what is wrong and how to fix it: a command prints it without
36
+ * its stack (D-119).
37
+ */
38
+ export class Refused extends Error {
39
+ constructor(message, options) {
40
+ super(message, options);
41
+ this.name = 'Refused';
42
+ }
43
+ }
@@ -0,0 +1,20 @@
1
+ type Leaf = string | number | boolean | bigint | symbol | Date | null | undefined;
2
+ type Shapes<S> = Exclude<Extract<S, object>, Date | readonly unknown[] | ((...args: never[]) => unknown)>;
3
+ type Keys<S> = S extends unknown ? keyof S : never;
4
+ type At<S, K> = S extends unknown ? (K extends keyof S ? S[K] : never) : never;
5
+ type Items<S> = Extract<S, readonly unknown[]>[number];
6
+ type Same<A, S> = (<T>() => T extends A ? 1 : 2) extends <T>() => (T extends S ? 1 : 2) ? true : false;
7
+ type Fine<O> = [keyof O] extends [never] ? unknown : O;
8
+ type Fields<A, S> = Fine<{
9
+ readonly [K in keyof A as K extends Keys<S> ? unknown extends Exact<A[K], At<S, K>> ? never : K : K]: K extends Keys<S> ? Exact<A[K], At<S, K>> : {
10
+ readonly error: `'${K & string}' is not a key here`;
11
+ };
12
+ }>;
13
+ export type Exact<A, S> = [A] extends [Leaf] ? unknown : {} extends A ? unknown : Same<A, S> extends true ? unknown : A extends readonly unknown[] ? Fits<A, {
14
+ readonly [I in keyof A]: Exact<A[I], Items<S>>;
15
+ }> : Fields<A, Shapes<S>>;
16
+ type Fits<A, E> = {
17
+ readonly [I in keyof A]: unknown;
18
+ } extends E ? unknown : E;
19
+ export {};
20
+ //# sourceMappingURL=exact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exact.d.ts","sourceRoot":"","sources":["../src/exact.ts"],"names":[],"mappings":"AAKA,KAAK,IAAI,GACR,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAA;AACtE,KAAK,MAAM,CAAC,CAAC,IAAI,OAAO,CACvB,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,EAClB,IAAI,GAAG,SAAS,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,CAC3D,CAAA;AACD,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,MAAM,CAAC,GAAG,KAAK,CAAA;AAClD,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAA;AAC9E,KAAK,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAEb,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,QAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA,GAChE,IAAI,GACJ,KAAK,CAAA;AACT,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,CAAC,CAAA;AAEtD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACxB,QAAQ,EACP,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,GAC9B,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GACpC,KAAK,GACL,CAAC,GACF,CAAC,GACF,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,GACjB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GACrB;QAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,MAAM,qBAAqB,CAAA;KAAE;CAC1D,CAAC,CAAA;AAKF,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GACzC,OAAO,GACP,EAAE,SAAS,CAAC,GACX,OAAO,GACP,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,IAAI,GACtB,OAAO,GACP,CAAC,SAAS,SAAS,OAAO,EAAE,GAC3B,IAAI,CAAC,CAAC,EAAE;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,GAC3D,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;AAG1B,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO;CAAE,SAAS,CAAC,GAAG,OAAO,GAAG,CAAC,CAAA"}
package/dist/exact.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/feed.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { Feed } from './adapter.ts';
2
+ import type { PluginRecord } from './definition.ts';
3
+ import { type Installed } from './plugin-app.ts';
4
+ /** Calls each plugin's `changed` and `missed`, in declaration order. */
5
+ export declare function feedOf(records: readonly PluginRecord[], plugins: readonly Installed[]): Feed | undefined;
6
+ //# sourceMappingURL=feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAMzD,wEAAwE;AACxE,wBAAgB,MAAM,CACrB,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,SAAS,SAAS,EAAE,GAC3B,IAAI,GAAG,SAAS,CAuBlB"}
package/dist/feed.js ADDED
@@ -0,0 +1,33 @@
1
+ // The change feed (D-154): what each commit changed, to the plugins that
2
+ // take it. The adapter feeds nothing when none does.
3
+ import { AsyncLocalStorage } from 'node:async_hooks';
4
+ import { inOrder } from './plugin-app.js';
5
+ // Outside every async context: an adapter may deliver from within the write,
6
+ // whose transaction and recording a hook's queries must not join.
7
+ const outside = AsyncLocalStorage.snapshot();
8
+ /** Calls each plugin's `changed` and `missed`, in declaration order. */
9
+ export function feedOf(records, plugins) {
10
+ const takers = inOrder(records, plugins).filter(({ code }) => code.changed !== undefined);
11
+ if (takers.length === 0)
12
+ return undefined;
13
+ // A plugin failing on a change must not stop the others nor the write.
14
+ const each = (hook, args) => {
15
+ for (const { code, context } of takers) {
16
+ const run = code[hook];
17
+ if (run === undefined)
18
+ continue;
19
+ try {
20
+ outside(() => {
21
+ Reflect.apply(run, undefined, [...args, context]);
22
+ });
23
+ }
24
+ catch (error) {
25
+ context.logger.error({ err: error }, `The plugin's ${hook} failed.`);
26
+ }
27
+ }
28
+ };
29
+ return {
30
+ changed: (changes) => each('changed', [changes]),
31
+ missed: () => each('missed', []),
32
+ };
33
+ }
@@ -0,0 +1,11 @@
1
+ import type { Nested, Row } from './adapter.ts';
2
+ import type { ModelInfo } from './schema.ts';
3
+ type Models = ReadonlyMap<string, ModelInfo>;
4
+ /** A value the kernel reads as a row: an object with a string `id`. */
5
+ export declare const isRow: (value: unknown) => value is Row;
6
+ /** The rows `read` returned, decoded. */
7
+ export declare function decoded(models: Models, read: (Nested & {
8
+ readonly model: string;
9
+ }) | undefined, rows: Row[]): Row[];
10
+ export {};
11
+ //# sourceMappingURL=field-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-codec.d.ts","sourceRoot":"","sources":["../src/field-codec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,KAAK,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAmD5C,uEAAuE;AACvE,eAAO,MAAM,KAAK,UAAW,OAAO,KAAG,KAAK,IAAI,GACG,CAAA;AAEnD,yCAAyC;AACzC,wBAAgB,OAAO,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,CAAC,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,EACvD,IAAI,EAAE,GAAG,EAAE,GACT,GAAG,EAAE,CAIP"}
@@ -0,0 +1,48 @@
1
+ import { isObject } from './query-where.js';
2
+ const known = new WeakMap();
3
+ function codecsOf(model) {
4
+ const found = known.get(model);
5
+ if (found !== undefined)
6
+ return found;
7
+ const codecs = [...model.fields.values()].flatMap((field) => field.kind === 'scalar' && field.codec !== undefined
8
+ ? [[field.name, field.codec]]
9
+ : []);
10
+ known.set(model, codecs);
11
+ return codecs;
12
+ }
13
+ /** The row with its plugin fields decoded, its included rows' too. */
14
+ function decodedRow(models, model, read, row) {
15
+ const changed = {};
16
+ // `null` is stored as is, never decoded.
17
+ for (const [name, codec] of codecsOf(model)) {
18
+ const value = row[name];
19
+ if (value !== undefined && value !== null) {
20
+ changed[name] = codec.decode(value);
21
+ }
22
+ }
23
+ for (const [name, nested] of Object.entries(read.include ?? {})) {
24
+ const field = model.fields.get(name);
25
+ const target = field === undefined || field.kind === 'scalar'
26
+ ? undefined
27
+ : models.get(field.target);
28
+ const value = row[name];
29
+ if (target === undefined)
30
+ continue;
31
+ if (Array.isArray(value)) {
32
+ changed[name] = value.map((item) => isRow(item) ? decodedRow(models, target, nested, item) : item);
33
+ }
34
+ else if (isRow(value)) {
35
+ changed[name] = decodedRow(models, target, nested, value);
36
+ }
37
+ }
38
+ return Object.keys(changed).length === 0 ? row : { ...row, ...changed };
39
+ }
40
+ /** A value the kernel reads as a row: an object with a string `id`. */
41
+ export const isRow = (value) => isObject(value) && typeof value['id'] === 'string';
42
+ /** The rows `read` returned, decoded. */
43
+ export function decoded(models, read, rows) {
44
+ const model = read === undefined ? undefined : models.get(read.model);
45
+ if (read === undefined || model === undefined)
46
+ return rows;
47
+ return rows.map((row) => decodedRow(models, model, read, row));
48
+ }
@@ -0,0 +1,57 @@
1
+ import type { RecordFor } from './record.ts';
2
+ import type { Caller } from './rules.ts';
3
+ import type { declaredRecord } from './symbols.ts';
4
+ type ReadFacts<R extends object> = {
5
+ readonly caller: Caller;
6
+ readonly operation: 'read';
7
+ readonly record: RecordFor<R>;
8
+ };
9
+ type CreateFacts<V> = {
10
+ readonly caller: Caller;
11
+ readonly operation: 'create';
12
+ readonly value: V;
13
+ };
14
+ type UpdateFacts<R extends object, V> = {
15
+ readonly caller: Caller;
16
+ readonly operation: 'update';
17
+ readonly record: RecordFor<R>;
18
+ readonly value: V;
19
+ };
20
+ type Rule<F> = (facts: F) => boolean;
21
+ type FieldReadRule<R extends object> = Rule<ReadFacts<R>>;
22
+ type FieldCreateRule<V> = Rule<CreateFacts<V>>;
23
+ type FieldUpdateRule<R extends object, V> = Rule<UpdateFacts<R, V>>;
24
+ type FieldWriteRule<R extends object, V> = Rule<CreateFacts<V> | UpdateFacts<R, V>>;
25
+ type FieldRule<R extends object, V> = Rule<ReadFacts<R> | CreateFacts<V> | UpdateFacts<R, V>>;
26
+ /** A field keeps its declared record type, which `defineModel` checks. */
27
+ export type Declared<R> = [R] extends [never] ? unknown : {
28
+ readonly [declaredRecord]: {
29
+ readonly [P in keyof R]: (value: R[P]) => R[P];
30
+ };
31
+ };
32
+ /** One rule, or one rule per operation (D-44). */
33
+ export type FieldAccess<R extends object, V> = FieldRule<R, V> | {
34
+ readonly read?: FieldReadRule<R>;
35
+ readonly create?: FieldCreateRule<V>;
36
+ readonly update?: FieldUpdateRule<R, V>;
37
+ readonly write?: FieldWriteRule<R, V>;
38
+ };
39
+ /**
40
+ * The rules of the model's plugins for one field, each under the plugin's
41
+ * name and typed by the field's value (D-12, D-57).
42
+ */
43
+ type PluginFieldRules<T, V> = {
44
+ readonly [X in T as X extends {
45
+ readonly name: infer N extends string;
46
+ readonly fieldWith: object;
47
+ } ? N : never]?: X extends {
48
+ readonly fieldWith: object;
49
+ } ? (X & {
50
+ readonly value: V;
51
+ })['fieldWith'] : never;
52
+ };
53
+ export type FieldWith<R extends object, V, T = never> = {
54
+ readonly access?: FieldAccess<R, V>;
55
+ } & PluginFieldRules<T, V>;
56
+ export {};
57
+ //# sourceMappingURL=field-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-rules.d.ts","sourceRoot":"","sources":["../src/field-rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAKlD,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CAC7B,CAAA;AACD,KAAK,WAAW,CAAC,CAAC,IAAI;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CACjB,CAAA;AACD,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IAAI;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CACjB,CAAA;AACD,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAA;AAEpC,KAAK,aAAa,CAAC,CAAC,SAAS,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;AACzD,KAAK,eAAe,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9C,KAAK,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACnE,KAAK,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IAAI,IAAI,CAC9C,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAClC,CAAA;AACD,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IAAI,IAAI,CACzC,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CACjD,CAAA;AAED,0EAA0E;AAG1E,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC1C,OAAO,GACP;IACA,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE;QAC1B,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KAC9C,CAAA;CACD,CAAA;AAEH,kDAAkD;AAClD,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,IACxC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GACf;IACA,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CACpC,CAAA;AAEJ;;;GAGG;AACH,KAAK,gBAAgB,CAAC,CAAC,EAAE,CAAC,IAAI;IAC7B,QAAQ,EACP,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;QACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;QACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAC1B,GACE,CAAC,GACD,KAAK,CACR,CAAC,EAAE,CAAC,SAAS;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GACzC,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC,WAAW,CAAC,GACxC,KAAK;CACR,CAAA;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CACnC,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,51 @@
1
+ import type { DefaultFunction, Described, Field, FieldBuilders, JsonValue, SchemaTypes, StandardSchema } from './fields.ts';
2
+ import type { fieldType } from './symbols.ts';
3
+ /** A kernel scalar field, as `stored` returns it. */
4
+ type Stored = {
5
+ readonly [fieldType]: {
6
+ readonly kind: 'scalar';
7
+ readonly value: unknown;
8
+ readonly options: unknown;
9
+ };
10
+ };
11
+ type StoredValue<S> = S extends {
12
+ readonly [fieldType]: {
13
+ readonly value: infer V;
14
+ };
15
+ } ? V : never;
16
+ type StoredOptions<S> = S extends {
17
+ readonly [fieldType]: {
18
+ readonly options: infer O;
19
+ };
20
+ } ? O : never;
21
+ /** What `defineFieldType` takes (D-122), each function given the options. */
22
+ export type FieldTypeDefinition<P extends string, S, V, X, O extends object> = {
23
+ /** The plugin that provides the field type, which `plugins` lists (D-32). */
24
+ readonly plugin: P;
25
+ /** The names of the field type's own options, beside `default` (D-152). */
26
+ readonly options?: readonly NoInfer<keyof O & string>[];
27
+ /** The kernel field that stores, filters and indexes the value. */
28
+ readonly stored: (f: FieldBuilders<never>, options: O) => S;
29
+ readonly decode: (stored: StoredValue<S>, options: O) => V;
30
+ readonly encode: (value: V, options: O) => StoredValue<S>;
31
+ /** Takes the value or its JSON, and gives the value. */
32
+ readonly schema: X | ((options: O) => X);
33
+ /** What a client reads. */
34
+ readonly toJSON: (value: V, options: O) => JsonValue;
35
+ /** What `toJSON` gives, which types it for clients (D-152). */
36
+ readonly shape?: StandardSchema | ((options: O) => StandardSchema);
37
+ };
38
+ /** A field type's options: the stored field says whether it may be `null`. */
39
+ export type FieldTypeOptions<I> = Described & {
40
+ readonly default?: I | DefaultFunction<I>;
41
+ };
42
+ /** The builder `defineFieldType` returns (D-122). */
43
+ export type FieldType<P extends string, S, V, I, O extends object = Described> = <const G extends FieldTypeOptions<I> & Partial<O> = {}>(options?: G) => Field<V, StoredOptions<S> & G, P, never, I, true, S>;
44
+ /**
45
+ * A plugin's field type (D-122): its builder takes `default`, `description`
46
+ * (D-150) and the type's own options (D-152), and its value is stored through
47
+ * `stored`, encoded after the hooks and decoded on each read.
48
+ */
49
+ export declare function defineFieldType<const P extends string, S extends Stored, V, X extends StandardSchema<unknown, V>, O extends object = Described>(definition: FieldTypeDefinition<P, S, V, X, O>): FieldType<P, S, V, SchemaTypes<X>['input'], O>;
50
+ export {};
51
+ //# sourceMappingURL=field-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-type.d.ts","sourceRoot":"","sources":["../src/field-type.ts"],"names":[],"mappings":"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"}