ultimabase 0.0.0-stage → 0.1.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 (411) hide show
  1. package/CHANGELOG.md +7 -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 +16 -0
  37. package/dist/cli-main.d.ts.map +1 -0
  38. package/dist/cli-main.js +151 -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 +165 -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
package/src/adapter.ts ADDED
@@ -0,0 +1,363 @@
1
+ // The adapter contract (D-73): what the kernel sends a storage adapter, fully
2
+ // prepared. Names are the models' own; `dbName` says what to store them as.
3
+ import type { JsonCondition } from './adapter-json.ts'
4
+ import type { Migrations } from './adapter-migrations.ts'
5
+ import type { Logger } from './app-options.ts'
6
+
7
+ export type {
8
+ Migration,
9
+ Migrations,
10
+ Run,
11
+ Statement,
12
+ Stored,
13
+ } from './adapter-migrations.ts'
14
+ export {
15
+ CheckFailed,
16
+ MigrationFailed,
17
+ OutOfRange,
18
+ RelationViolation,
19
+ UniqueViolation,
20
+ } from './adapter-errors.ts'
21
+
22
+ export type ScalarType =
23
+ | 'string'
24
+ | 'number'
25
+ | 'decimal'
26
+ | 'boolean'
27
+ | 'dateTime'
28
+ | 'date'
29
+ | 'json'
30
+ | 'enum'
31
+
32
+ export type SchemaField =
33
+ | {
34
+ readonly kind: 'scalar'
35
+ readonly name: string
36
+ readonly type: ScalarType
37
+ /** An `enum`'s values. */
38
+ readonly values?: readonly string[]
39
+ /**
40
+ * A list of `type`, a string, a number or an enum value: never
41
+ * `null`, `[]` when empty (D-120, D-127).
42
+ */
43
+ readonly list: boolean
44
+ /** A `number` of whole numbers from -2^31 to 2^31 - 1 (D-132). */
45
+ readonly integer?: true
46
+ /**
47
+ * A `decimal`'s digits, `scale` of them after the point; its values
48
+ * are strings at that scale (D-145).
49
+ */
50
+ readonly precision?: number
51
+ readonly scale?: number
52
+ readonly optional: boolean
53
+ readonly unique: boolean
54
+ /** A `string` in its model's document, which `_search` matches (D-148). */
55
+ readonly search?: true
56
+ readonly dbName?: string
57
+ /** Its default when it is a value, not a function (D-105). */
58
+ readonly default?: unknown
59
+ }
60
+ | {
61
+ readonly kind: 'one'
62
+ readonly name: string
63
+ readonly target: string
64
+ /** The target's field on the other side (D-37). */
65
+ readonly inverse: string
66
+ /** Whether this side stores the key, one per pair (D-37). */
67
+ readonly stored: boolean
68
+ /** One-to-one: the stored key is unique. */
69
+ readonly unique: boolean
70
+ readonly optional: boolean
71
+ readonly onDelete: 'cascade' | 'restrict' | 'setNull'
72
+ readonly dbName?: string
73
+ }
74
+ | {
75
+ readonly kind: 'many'
76
+ readonly name: string
77
+ readonly target: string
78
+ readonly inverse: string
79
+ /** Facing a `many`: a join holding the two keys only (D-64). */
80
+ readonly join: boolean
81
+ /** Its reads see the rows a filter keeps; it takes no `set` (D-151). */
82
+ readonly filtered?: true
83
+ /**
84
+ * A view: read-only, on the link of the `many` it names, with that
85
+ * relation's `inverse` and `join` (D-151).
86
+ */
87
+ readonly from?: string
88
+ }
89
+
90
+ export type SchemaModel = {
91
+ readonly name: string
92
+ readonly dbName?: string
93
+ /** `id`, `createdAt` and `updatedAt` are implicit (D-22). */
94
+ readonly fields: readonly SchemaField[]
95
+ readonly indexes: readonly {
96
+ readonly fields: readonly string[]
97
+ readonly unique: boolean
98
+ /** Serves `contains` and `mode: 'insensitive'` (D-141). */
99
+ readonly contains: boolean
100
+ }[]
101
+ }
102
+
103
+ export type Schema = { readonly models: readonly SchemaModel[] }
104
+
105
+ /** A normalized condition on one field: no shorthand, no `undefined`. */
106
+ export type Condition = JsonCondition & {
107
+ readonly equals?: unknown
108
+ readonly not?: unknown
109
+ readonly in?: readonly unknown[]
110
+ readonly notIn?: readonly unknown[]
111
+ readonly lt?: unknown
112
+ readonly lte?: unknown
113
+ readonly gt?: unknown
114
+ readonly gte?: unknown
115
+ readonly contains?: string
116
+ readonly startsWith?: string
117
+ readonly endsWith?: string
118
+ /** The string operators ignore case (D-140). */
119
+ readonly mode?: 'insensitive'
120
+ /** A list holds this element (D-120, D-127). */
121
+ readonly has?: unknown
122
+ /** A list holds one of these elements (D-120, D-127). */
123
+ readonly hasSome?: readonly unknown[]
124
+ /** A list holds each of these elements (D-149). */
125
+ readonly hasEvery?: readonly unknown[]
126
+ /** A list is empty, or not (D-149). */
127
+ readonly isEmpty?: boolean
128
+ readonly is?: Filter | null
129
+ readonly isNot?: Filter | null
130
+ readonly some?: Filter
131
+ readonly every?: Filter
132
+ readonly none?: Filter
133
+ /**
134
+ * A stored `one` key names a row that the delete at this index of the
135
+ * write's changes removed, a change before this one (D-102).
136
+ */
137
+ readonly removedBy?: number
138
+ /**
139
+ * Under the key `_search`: the row's searched fields match this text, in
140
+ * PostgreSQL's `websearch_to_tsquery` syntax (D-148).
141
+ */
142
+ readonly search?: string
143
+ }
144
+
145
+ /** A normalized `where`: `AND`, `OR` and `NOT` are lists (D-73). */
146
+ export interface Filter {
147
+ readonly AND?: readonly Filter[]
148
+ readonly OR?: readonly Filter[]
149
+ readonly NOT?: readonly Filter[]
150
+ readonly [field: string]: Condition | readonly Filter[] | undefined
151
+ }
152
+
153
+ /** A `one` relation a sort key goes through, to the rows `where` selects. */
154
+ export type Step = { readonly relation: string; readonly where?: Filter }
155
+
156
+ export type Order = {
157
+ /** A field of the row, or of the row `through` reaches. */
158
+ readonly field: string
159
+ readonly direction: 'asc' | 'desc'
160
+ /** Where `null` sorts: by default last ascending, first descending (D-149). */
161
+ readonly nulls?: 'first' | 'last'
162
+ /** The `one` relations followed first; an absent row sorts as `null` (D-134). */
163
+ readonly through?: readonly Step[]
164
+ /** `field` is a `many` relation: its rows this filter selects are counted (D-134). */
165
+ readonly count?: Filter
166
+ /** `field` is `_relevance`: how well the row matches this text (D-148). */
167
+ readonly relevance?: string
168
+ }
169
+
170
+ export type Sort = Pick<Order, 'direction' | 'nulls'>
171
+
172
+ /** A relation to read with its rows; a `one` relation reads `where` only. */
173
+ export type Nested = {
174
+ readonly where?: Filter
175
+ /** Always ends with `id`, so the order is total. */
176
+ readonly orderBy?: readonly Order[]
177
+ /** A unique target the page starts at, as Prisma's `cursor`. */
178
+ readonly cursor?: Filter
179
+ readonly skip?: number
180
+ /** Negative: the rows before the cursor, or the last ones. */
181
+ readonly take?: number
182
+ /**
183
+ * The system and scalar fields the rows return, `id` always; absent, every
184
+ * field and each `one` key (D-136).
185
+ */
186
+ readonly fields?: readonly string[]
187
+ readonly include?: { readonly [field: string]: Nested }
188
+ /** `many` relations to count in the row's `_count`, by filter (D-134). */
189
+ readonly count?: { readonly [field: string]: Filter }
190
+ }
191
+
192
+ export type Read = Nested & {
193
+ readonly model: string
194
+ /** Locks the root rows, in `id` order, until the transaction ends (D-99, D-133). */
195
+ readonly lock?: boolean
196
+ /**
197
+ * Keeps, of the rows with the same keys, the first in `orderBy`'s order,
198
+ * before `skip` and `take` (D-147).
199
+ */
200
+ readonly distinct?: readonly GroupKey[]
201
+ }
202
+
203
+ export type CountRead = { readonly model: string; readonly where?: Filter }
204
+
205
+ /** One aggregate: `count` without a field counts the rows (D-143). */
206
+ export type Aggregate = {
207
+ readonly operation: 'count' | 'sum' | 'avg' | 'min' | 'max'
208
+ /** A scalar field, neither a list nor `json`. */
209
+ readonly field?: string
210
+ }
211
+
212
+ /** A group's key: a field, or the `id` of the row `through` reaches (D-146). */
213
+ export type GroupKey = {
214
+ readonly field: string
215
+ readonly through?: readonly Step[]
216
+ }
217
+
218
+ /**
219
+ * Aggregates of the rows `where` selects, one value each, in order: a count
220
+ * is a number, the others `null` without a value (D-143). With `by`, of each
221
+ * group of rows with the same keys; an absent row gives `null` (D-146).
222
+ */
223
+ export type AggregateRead = CountRead & {
224
+ readonly aggregates: readonly Aggregate[]
225
+ readonly by?: readonly GroupKey[]
226
+ /** A position, `orderBy`'s `at` or a `having` key (D-149): keys, then aggregates. */
227
+ readonly having?: Filter
228
+ readonly orderBy?: readonly ({ readonly at: number } & Sort)[]
229
+ readonly skip?: number
230
+ readonly take?: number
231
+ }
232
+
233
+ /**
234
+ * A stored row: system and scalar fields, and each `one` relation as its key
235
+ * `{ id } | null`, or the included row. An included `many` is a list of rows.
236
+ */
237
+ export type Row = { readonly id: string; readonly [field: string]: unknown }
238
+
239
+ /**
240
+ * A number update computed on each row the write changes, `null` counting
241
+ * as 0; an integer's division truncates toward zero (D-132).
242
+ */
243
+ export type Arithmetic = {
244
+ readonly operation: 'increment' | 'decrement' | 'multiply' | 'divide'
245
+ readonly by: number
246
+ }
247
+
248
+ /**
249
+ * A list update computed on each row the write changes (D-149): `push`
250
+ * appends, `pushUnique` appends each element the list lacks, once, and
251
+ * `remove` drops every occurrence.
252
+ */
253
+ export type ListUpdate = {
254
+ readonly operation: 'push' | 'pushUnique' | 'remove'
255
+ readonly elements: readonly unknown[]
256
+ }
257
+
258
+ /** In a change, a stored `one` key is the target's id or `null`. */
259
+ export type Change =
260
+ | { readonly kind: 'insert'; readonly model: string; readonly row: Row }
261
+ | {
262
+ readonly kind: 'update'
263
+ readonly model: string
264
+ readonly where: Filter
265
+ readonly set: { readonly [field: string]: unknown }
266
+ readonly compute?: {
267
+ readonly [field: string]: Arithmetic | ListUpdate
268
+ }
269
+ }
270
+ | { readonly kind: 'delete'; readonly model: string; readonly where: Filter }
271
+ | {
272
+ readonly kind: 'link' | 'unlink'
273
+ readonly model: string
274
+ /** A `many` relation facing a `many`. */
275
+ readonly field: string
276
+ readonly id: string
277
+ readonly targets: readonly string[]
278
+ }
279
+
280
+ /** A count of rows a write needs before it changes anything (D-99). */
281
+ export type Check = {
282
+ readonly model: string
283
+ readonly where: Filter
284
+ readonly count: number
285
+ /** Locks the rows it counts until the transaction ends, as `Read.lock` (D-99). */
286
+ readonly lock?: boolean
287
+ }
288
+
289
+ /**
290
+ * One whole write: its checks first, which write nothing when one fails,
291
+ * then its changes, then `read`, in the same write. With `before`, the read
292
+ * selects among the rows of its model that the write's delete removed, as
293
+ * they were (D-102, D-104); when the write deletes none of them, among the
294
+ * rows its first update of that model changed, as it left them (D-133).
295
+ */
296
+ export type Write = {
297
+ readonly checks?: readonly Check[]
298
+ readonly changes: readonly Change[]
299
+ readonly read?: Read
300
+ readonly before?: boolean
301
+ }
302
+
303
+ /**
304
+ * What a committed write changed (D-154): `ids` is absent when they were
305
+ * more than `feedIds`, `fields` when they were every field or longer than
306
+ * `feedFields`. A delete's links go with its rows, unlisted. How changes
307
+ * group into entries and calls is the adapter's.
308
+ */
309
+ export type Changed =
310
+ | {
311
+ readonly kind: 'insert' | 'update' | 'delete'
312
+ readonly model: string
313
+ readonly ids?: readonly string[]
314
+ /** The fields an update set, `updatedAt` included. */
315
+ readonly fields?: readonly string[]
316
+ }
317
+ | {
318
+ readonly kind: 'link' | 'unlink'
319
+ readonly model: string
320
+ /** A `many` relation facing a `many`. */
321
+ readonly field: string
322
+ /** The model's id, then the target's. */
323
+ readonly pairs?: readonly (readonly [string, string])[]
324
+ }
325
+
326
+ /** The most ids or pairs a change lists (D-154). */
327
+ export const feedIds = 1000
328
+ /** The longest list of fields, as JSON, an update lists (D-154). */
329
+ export const feedFields = 1500
330
+
331
+ /** Where an adapter sends the changes each commit makes, on any server. */
332
+ export type Feed = {
333
+ readonly changed: (changes: readonly Changed[]) => void
334
+ /** Changes may have been lost, as when a listener reconnects. */
335
+ readonly missed: () => void
336
+ }
337
+
338
+ export interface Transaction {
339
+ find(read: Read): Promise<Row[]>
340
+ count(read: CountRead): Promise<number>
341
+ /**
342
+ * One list per group: its keys' values, then its aggregates'; without
343
+ * `by`, one list, even without rows (D-146).
344
+ */
345
+ aggregate(read: AggregateRead): Promise<unknown[][]>
346
+ write(write: Write): Promise<Row[]>
347
+ commit(): Promise<void>
348
+ rollback(): Promise<void>
349
+ }
350
+
351
+ /** A storage adapter: its own slot, not a plugin (D-02, D-73). */
352
+ export interface Adapter extends Omit<Transaction, 'commit' | 'rollback'> {
353
+ /**
354
+ * Connects; the kernel then syncs or checks the tables (D-105). `logger`
355
+ * is the kernel's, for what the adapter reports (D-140). With `feed`, each
356
+ * commit's changes reach it, this server's and the others' (D-154).
357
+ */
358
+ start(schema: Schema, logger: Logger, feed?: Feed): Promise<void>
359
+ stop(): Promise<void>
360
+ begin(): Promise<Transaction>
361
+ /** None for a database that starts empty every time, as `memory()`. */
362
+ readonly migrations?: Migrations
363
+ }
@@ -0,0 +1,136 @@
1
+ // `aggregate` (D-143): counts, sums, averages, minimums and maximums of the
2
+ // rows the caller reads, on scalar fields it may filter on.
3
+ import type { Aggregate } from './adapter.ts'
4
+ import { InvalidQuery } from './errors.ts'
5
+ import type { Context } from './query-context.ts'
6
+ import { filtered, given } from './query-context.ts'
7
+ import { entries, systemFields, unknownKey } from './query-where.ts'
8
+ import type { ModelInfo } from './schema.ts'
9
+ import type { Store } from './transaction.ts'
10
+
11
+ const operations = {
12
+ _count: 'count',
13
+ _sum: 'sum',
14
+ _avg: 'avg',
15
+ _min: 'min',
16
+ _max: 'max',
17
+ } as const
18
+ export type Key = keyof typeof operations
19
+ export const keys: readonly Key[] = ['_count', '_sum', '_avg', '_min', '_max']
20
+
21
+ /** The types each aggregate takes; `_count` takes every scalar. */
22
+ const takes: { readonly [K in Key]?: readonly string[] } = {
23
+ _sum: ['number', 'decimal'],
24
+ _avg: ['number', 'decimal'],
25
+ _min: ['number', 'decimal', 'string', 'enum', 'dateTime', 'date'],
26
+ _max: ['number', 'decimal', 'string', 'enum', 'dateTime', 'date'],
27
+ }
28
+
29
+ /** The field's type, which fails on a field an aggregate cannot take. */
30
+ export function typeOf(
31
+ model: ModelInfo,
32
+ field: string,
33
+ path: string,
34
+ verb = 'aggregated',
35
+ ): string {
36
+ const refuse = (kind: string): never => {
37
+ throw new InvalidQuery(path, `${path} is ${kind}, which cannot be ${verb}.`)
38
+ }
39
+ const known = model.fields.get(field)
40
+ if (known === undefined) {
41
+ if (!systemFields.includes(field)) throw unknownKey(path, model.name)
42
+ return field === 'id' ? 'string' : 'dateTime'
43
+ }
44
+ if (known.kind !== 'scalar') return refuse('a relation')
45
+ if (known.list) return refuse('a list')
46
+ if (known.type === 'json') return refuse('json')
47
+ if (known.codec !== undefined) return refuse('a plugin field')
48
+ return known.type
49
+ }
50
+
51
+ export type Asked = { readonly key: Key; readonly field: string | undefined }
52
+
53
+ /** Aggregate `key` of `field`, checked; `_all` counts the rows. */
54
+ export function checked(
55
+ { model, scope }: Context,
56
+ key: Key,
57
+ field: string,
58
+ path: string,
59
+ ): Asked {
60
+ if (key === '_count' && field === '_all') return { key, field: undefined }
61
+ const type = typeOf(model, field, path)
62
+ const types = takes[key]
63
+ if (types !== undefined && !types.includes(type)) {
64
+ throw new InvalidQuery(
65
+ path,
66
+ `${path} is a ${type} field; ${key} takes ${types.join(', ')} fields.`,
67
+ )
68
+ }
69
+ scope.check(model, field, path, 'aggregates')
70
+ return { key, field }
71
+ }
72
+
73
+ /** The aggregates `key` asks for, each checked. */
74
+ function asked(context: Context, key: Key, value: unknown): readonly Asked[] {
75
+ if (key === '_count' && value === true) return [{ key, field: undefined }]
76
+ return entries(value, key).map(([field, flag]): Asked => {
77
+ const path = `${key}.${field}`
78
+ if (flag !== true) {
79
+ throw new InvalidQuery(path, `${path} must be true.`)
80
+ }
81
+ return checked(context, key, field, path)
82
+ })
83
+ }
84
+
85
+ /** The aggregates the arguments ask for, in the order of `keys`. */
86
+ export const wanted = (
87
+ context: Context,
88
+ found: ReadonlyMap<string, unknown>,
89
+ ): readonly Asked[] =>
90
+ keys.flatMap((key) =>
91
+ found.has(key) ? asked(context, key, found.get(key)) : [],
92
+ )
93
+
94
+ export const toAggregate = ({ key, field }: Asked): Aggregate => ({
95
+ operation: operations[key],
96
+ ...(field !== undefined && { field }),
97
+ })
98
+
99
+ /** The aggregates' values under the keys the arguments ask for. */
100
+ export function shaped(
101
+ found: ReadonlyMap<string, unknown>,
102
+ list: readonly Asked[],
103
+ values: readonly unknown[],
104
+ ): { [key: string]: unknown } {
105
+ const result: { [key: string]: unknown } = {}
106
+ for (const [index, { key, field }] of list.entries()) {
107
+ const value = values[index]
108
+ if (key === '_count' && found.get(key) === true) {
109
+ result[key] = value
110
+ continue
111
+ }
112
+ const fields = result[key] ?? {}
113
+ result[key] = { ...fields, [field ?? '_all']: value }
114
+ }
115
+ for (const key of keys) {
116
+ if (found.has(key)) result[key] ??= {}
117
+ }
118
+ return result
119
+ }
120
+
121
+ export async function aggregate(
122
+ context: Context,
123
+ store: Store,
124
+ args: unknown,
125
+ ): Promise<unknown> {
126
+ const { model } = context
127
+ const found = given(args, model.name, ['where', ...keys], [])
128
+ const list = wanted(context, found)
129
+ const where = await filtered(context, found, 'read')
130
+ const [values = []] = await store.aggregate({
131
+ model: model.name,
132
+ ...(where && { where }),
133
+ aggregates: list.map(toAggregate),
134
+ })
135
+ return shaped(found, list, values)
136
+ }
@@ -0,0 +1,26 @@
1
+ // What the `ultimabase` commands read from an application (D-105): its
2
+ // options and its lifecycle, kept off its public surface.
3
+ import type { Lifecycle, LifecycleOptions } from './lifecycle.ts'
4
+
5
+ export type Internals = {
6
+ readonly options: LifecycleOptions
7
+ readonly app: Lifecycle
8
+ }
9
+
10
+ const internals = new WeakMap<object, Internals>()
11
+
12
+ /** Remembers the options `defineApp` built `app` from. */
13
+ export function remember<T extends Lifecycle>(
14
+ app: T,
15
+ options: LifecycleOptions,
16
+ ): T {
17
+ internals.set(app, { options, app })
18
+ return app
19
+ }
20
+
21
+ /** What `defineApp` kept of a value it returned, or `undefined`. */
22
+ export function internalsOf(value: unknown): Internals | undefined {
23
+ return typeof value === 'object' && value !== null
24
+ ? internals.get(value)
25
+ : undefined
26
+ }
@@ -0,0 +1,24 @@
1
+ // What `defineApp` takes beside its database, plugins and models (D-49,
2
+ // D-58).
3
+
4
+ type LogFunction = {
5
+ (message: string): void
6
+ (bindings: object, message?: string): void
7
+ }
8
+ /** Pino's interface (D-58); without one, the kernel writes JSON lines. */
9
+ export interface Logger {
10
+ readonly info: LogFunction
11
+ readonly warn: LogFunction
12
+ readonly error: LogFunction
13
+ child(bindings: object): Logger
14
+ }
15
+
16
+ /**
17
+ * Refused in production unless written `{ key, production: true }`, with 32
18
+ * characters at least (D-49).
19
+ * `undefined` leaves it off, so an unset environment variable passes as is.
20
+ */
21
+ export type MasterKey =
22
+ | string
23
+ | undefined
24
+ | { readonly key: string | undefined; readonly production: true }