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
@@ -0,0 +1,29 @@
1
+ import type { Adapter } from './adapter.ts';
2
+ import type { Logger } from './app-options.ts';
3
+ import type { Complete } from './complete.ts';
4
+ import type { FunctionDefinition } from './definition.ts';
5
+ import type { Resolved } from './schema.ts';
6
+ export type Running = {
7
+ readonly resolved: Resolved;
8
+ /** Its functions, by their `defineFunction` value (D-75). */
9
+ readonly functions: ReadonlyMap<object, FunctionDefinition>;
10
+ readonly adapter: Adapter;
11
+ readonly logger: Logger;
12
+ /** Each plugin's API, by its name (D-16). */
13
+ readonly apis: ReadonlyMap<string, unknown>;
14
+ readonly work: Work;
15
+ /** Completes a user caller with its plugins' keys (D-121). */
16
+ readonly complete: Complete;
17
+ };
18
+ /** The operations running, `*Commit` hooks included, that `stop` waits for. */
19
+ export declare class Work {
20
+ private count;
21
+ private readonly idle;
22
+ run<R>(run: () => Promise<R>): Promise<R>;
23
+ settled(): Promise<void>;
24
+ }
25
+ export declare function register(app: Running): void;
26
+ export declare function unregister(app: Running): void;
27
+ /** The running application, `undefined` before `start`. */
28
+ export declare function current(): Running | undefined;
29
+ //# sourceMappingURL=running.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"running.d.ts","sourceRoot":"","sources":["../src/running.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAC3B,CAAA;AAED,+EAA+E;AAC/E,qBAAa,IAAI;IAChB,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAEpC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ9C;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAK7B;CACD;AAID,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAK3C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED,2DAA2D;AAC3D,wBAAgB,OAAO,IAAI,OAAO,GAAG,SAAS,CAE7C"}
@@ -0,0 +1,39 @@
1
+ /** The operations running, `*Commit` hooks included, that `stop` waits for. */
2
+ export class Work {
3
+ count = 0;
4
+ idle = [];
5
+ async run(run) {
6
+ this.count += 1;
7
+ try {
8
+ return await run();
9
+ }
10
+ finally {
11
+ this.count -= 1;
12
+ if (this.count === 0)
13
+ for (const done of this.idle.splice(0))
14
+ done();
15
+ }
16
+ }
17
+ async settled() {
18
+ if (this.count === 0)
19
+ return;
20
+ await new Promise((done) => {
21
+ this.idle.push(done);
22
+ });
23
+ }
24
+ }
25
+ let running;
26
+ export function register(app) {
27
+ if (running !== undefined) {
28
+ throw new Error('An application is already running; stop it first.');
29
+ }
30
+ running = app;
31
+ }
32
+ export function unregister(app) {
33
+ if (running === app)
34
+ running = undefined;
35
+ }
36
+ /** The running application, `undefined` before `start`. */
37
+ export function current() {
38
+ return running;
39
+ }
@@ -0,0 +1,11 @@
1
+ import type { SchemaField } from './adapter.ts';
2
+ import type { IndexDefinition } from './definition.ts';
3
+ import type { ModelInfo } from './schema.ts';
4
+ /** Refuses an index over a field that is not one of the model's columns. */
5
+ export declare function checkIndexes(model: string, fields: ReadonlyMap<string, SchemaField>, indexes: readonly IndexDefinition[]): void;
6
+ /**
7
+ * A searched field is the kernel's string, which every caller may read: a
8
+ * match would reveal a value its read rule hides (D-148).
9
+ */
10
+ export declare function checkSearch(model: ModelInfo): void;
11
+ //# sourceMappingURL=schema-indexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-indexes.d.ts","sourceRoot":"","sources":["../src/schema-indexes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAqC5C,4EAA4E;AAC5E,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,OAAO,EAAE,SAAS,eAAe,EAAE,GACjC,IAAI,CAmBN;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAgBlD"}
@@ -0,0 +1,59 @@
1
+ import { readRules } from './access.js';
2
+ import { Refused } from './errors.js';
3
+ /** An index on a list is a GIN index of that list alone (D-120). */
4
+ function listIndex(model, name, index) {
5
+ if (index.fields.length > 1) {
6
+ throw new Refused(`${model}: the list '${name}' is indexed alone, in an index of its own.`);
7
+ }
8
+ if (index.unique === true) {
9
+ throw new Refused(`${model}: the list '${name}' cannot be unique.`);
10
+ }
11
+ }
12
+ /** A `contains` index covers one string field, not a list (D-141). */
13
+ function containsIndex(model, fields, index) {
14
+ const [name] = index.fields;
15
+ const field = name === undefined ? undefined : fields.get(name);
16
+ if (index.fields.length !== 1 ||
17
+ index.unique === true ||
18
+ field?.kind !== 'scalar' ||
19
+ field.type !== 'string' ||
20
+ field.list) {
21
+ throw new Refused(`${model}: a contains index covers one string field that is not a list, and is not unique.`);
22
+ }
23
+ }
24
+ /** Refuses an index over a field that is not one of the model's columns. */
25
+ export function checkIndexes(model, fields, indexes) {
26
+ for (const index of indexes) {
27
+ for (const name of index.fields) {
28
+ const field = fields.get(name);
29
+ if (field === undefined ||
30
+ field.kind === 'many' ||
31
+ (field.kind === 'one' && !field.stored)) {
32
+ throw new Refused(`${model}: index field '${name}' is not a scalar or a stored one relation.`);
33
+ }
34
+ if (field.kind === 'scalar' && field.list) {
35
+ listIndex(model, name, index);
36
+ }
37
+ }
38
+ if (index.contains === true)
39
+ containsIndex(model, fields, index);
40
+ }
41
+ }
42
+ /**
43
+ * A searched field is the kernel's string, which every caller may read: a
44
+ * match would reveal a value its read rule hides (D-148).
45
+ */
46
+ export function checkSearch(model) {
47
+ const rules = readRules(model);
48
+ for (const field of model.fields.values()) {
49
+ if (field.kind !== 'scalar' || field.search !== true)
50
+ continue;
51
+ const name = `${model.name}.${field.name}`;
52
+ if (field.codec !== undefined) {
53
+ throw new Refused(`${name}: a ${field.codec.plugin} field is not searched.`);
54
+ }
55
+ if (rules[field.name] !== undefined) {
56
+ throw new Refused(`${name} has a read rule, and a search would reveal its value: remove search or the rule.`);
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,19 @@
1
+ import type { ModelDefinition, Output } from './definition.ts';
2
+ import type { Standard } from './validation.ts';
3
+ export type VirtualInfo = {
4
+ readonly name: string;
5
+ readonly model: string;
6
+ readonly output: Output;
7
+ readonly input: Standard | undefined;
8
+ /** The scalar fields its rule reads, `id` first. */
9
+ readonly needs: readonly string[];
10
+ /** `runMany` takes the rows at once, `run` one by one. */
11
+ readonly many: boolean;
12
+ readonly run: (facts: object) => unknown;
13
+ /** A value without input is in the row without `select`. */
14
+ readonly default: boolean;
15
+ readonly description: string | undefined;
16
+ };
17
+ /** The virtual fields of a model, checked against its fields and models. */
18
+ export declare function virtualsOf(model: string, definition: ModelDefinition, models: ReadonlyMap<object, string>): ReadonlyMap<string, VirtualInfo>;
19
+ //# sourceMappingURL=schema-virtuals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-virtuals.d.ts","sourceRoot":"","sources":["../src/schema-virtuals.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAI9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAG/C,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAA;IACpC,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IACxC,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC,CAAA;AAsDD,4EAA4E;AAC5E,wBAAgB,UAAU,CACzB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAoDlC"}
@@ -0,0 +1,100 @@
1
+ import { outputOf } from './definition.js';
2
+ import { Refused } from './errors.js';
3
+ import { isObject, systemFields } from './query-where.js';
4
+ import { standardOf } from './validation.js';
5
+ /** The keys that shape a model output's rows, which no input property takes. */
6
+ const shaping = ['select', 'include', 'omit'];
7
+ /** An input's properties, from its JSON Schema export when it has one. */
8
+ function propertiesOf(input) {
9
+ const exporter = Reflect.get(input.self, 'jsonSchema');
10
+ const exported = isObject(exporter) ? exporter['input'] : undefined;
11
+ if (typeof exported !== 'function')
12
+ return [];
13
+ const node = Reflect.apply(exported, exporter, [
14
+ { target: 'draft-2020-12' },
15
+ ]);
16
+ const properties = isObject(node) ? node['properties'] : undefined;
17
+ return isObject(properties) ? Object.keys(properties) : [];
18
+ }
19
+ function outputFor(value, where) {
20
+ const standard = standardOf(value);
21
+ if (standard !== undefined)
22
+ return { kind: 'schema', schema: standard.schema };
23
+ if (typeof value !== 'function') {
24
+ throw new Refused(`${where} is a Standard Schema, or a model or a type behind an arrow.`);
25
+ }
26
+ const returned = Reflect.apply(value, undefined, []);
27
+ return outputOf(returned, where);
28
+ }
29
+ function ruleOf(given, where) {
30
+ const rule = given[where.slice(where.indexOf('.') + 1)];
31
+ if (!isObject(rule)) {
32
+ throw new Refused(`${where} is virtual; give its run or runMany in .with({ virtuals }).`);
33
+ }
34
+ const { run, runMany } = rule;
35
+ if ((typeof run === 'function') === (typeof runMany === 'function')) {
36
+ throw new Refused(`${where}: give run or runMany, one of them.`);
37
+ }
38
+ const chosen = typeof run === 'function' ? run : runMany;
39
+ if (typeof chosen !== 'function')
40
+ throw new TypeError('A rule is a function.');
41
+ return {
42
+ many: chosen === runMany,
43
+ run: (facts) => {
44
+ const value = Reflect.apply(chosen, rule, [facts]);
45
+ return value;
46
+ },
47
+ };
48
+ }
49
+ /** The virtual fields of a model, checked against its fields and models. */
50
+ export function virtualsOf(model, definition, models) {
51
+ const rules = isObject(definition.rules)
52
+ ? definition.rules['virtuals']
53
+ : undefined;
54
+ const given = isObject(rules) ? rules : {};
55
+ const virtuals = new Map();
56
+ for (const name of Object.keys(given)) {
57
+ if (definition.fields.get(name)?.kind !== 'virtual') {
58
+ throw new Refused(`${model}.virtuals.${name} names no virtual field.`);
59
+ }
60
+ }
61
+ for (const [name, field] of definition.fields) {
62
+ if (field.kind !== 'virtual')
63
+ continue;
64
+ const where = `${model}.${name}`;
65
+ const output = outputFor(field.output, where);
66
+ if (output.kind === 'model' && !models.has(output.value)) {
67
+ throw new Refused(`${where}: its output model is not in models.`);
68
+ }
69
+ const { input: schema, needs: listed, description } = field.options;
70
+ const input = schema === undefined ? undefined : standardOf(schema);
71
+ if (schema !== undefined && input === undefined) {
72
+ throw new Refused(`${where}: input is a Standard Schema of an object.`);
73
+ }
74
+ for (const key of input === undefined ? [] : propertiesOf(input)) {
75
+ if (shaping.includes(key)) {
76
+ throw new Refused(`${where}: no input property is named ${key}, which shapes a model's rows.`);
77
+ }
78
+ }
79
+ const needs = Array.isArray(listed) ? listed : [];
80
+ for (const need of needs) {
81
+ const scalar = typeof need === 'string' &&
82
+ (systemFields.includes(need) ||
83
+ definition.fields.get(need)?.kind === 'scalar');
84
+ if (!scalar) {
85
+ throw new Refused(`${where} needs ${String(need)}, no scalar field.`);
86
+ }
87
+ }
88
+ virtuals.set(name, {
89
+ name,
90
+ model,
91
+ output,
92
+ input,
93
+ needs: [...new Set(['id', ...needs.map(String)])],
94
+ ...ruleOf(given, where),
95
+ default: output.kind === 'schema' && input === undefined,
96
+ description: typeof description === 'string' ? description : undefined,
97
+ });
98
+ }
99
+ return virtuals;
100
+ }
@@ -0,0 +1,35 @@
1
+ import type { Schema, SchemaField } from './adapter.ts';
2
+ import type { Codec, FieldOptions, ModelDefinition, PluginCode, PluginUse } from './definition.ts';
3
+ import type { Enum } from './fields.ts';
4
+ import type { VirtualInfo } from './schema-virtuals.ts';
5
+ /**
6
+ * A field as the kernel reads it: its schema, its builder's options, a
7
+ * plugin field type's codec (D-122) and its shared enum (D-150).
8
+ */
9
+ export type FieldInfo = SchemaField & {
10
+ readonly options: FieldOptions;
11
+ readonly codec?: Codec;
12
+ readonly enum?: Enum;
13
+ };
14
+ export type ModelInfo = {
15
+ readonly name: string;
16
+ readonly definition: ModelDefinition;
17
+ readonly fields: ReadonlyMap<string, FieldInfo>;
18
+ /** The unique targets (D-52): `id`, unique fields, unique indexes. */
19
+ readonly uniques: readonly (readonly string[])[];
20
+ /** The plugins of its `use`, in the order of `plugins` (D-29). */
21
+ readonly plugins: readonly PluginUse[];
22
+ /** The plugin whose own model it is, if one (D-110). */
23
+ readonly owner: string | undefined;
24
+ /** Its fields computed on read, which the adapter never sees (D-151). */
25
+ readonly virtuals: ReadonlyMap<string, VirtualInfo>;
26
+ };
27
+ export type Resolved = {
28
+ readonly schema: Schema;
29
+ readonly models: ReadonlyMap<string, ModelInfo>;
30
+ /** The model each `defineModel` value stands for. */
31
+ readonly byValue: ReadonlyMap<object, ModelInfo>;
32
+ };
33
+ /** Resolves the application's models, or stops startup with a message. */
34
+ export declare function resolve(values: readonly unknown[], plugins?: readonly PluginCode[]): Resolved;
35
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAe,MAAM,cAAc,CAAA;AACpE,OAAO,KAAK,EACX,KAAK,EAEL,YAAY,EACZ,eAAe,EACf,UAAU,EACV,SAAS,EACT,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAMvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG;IACrC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC/C,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;IAChD,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAA;IACtC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAChD,CAAA;AA8MD,0EAA0E;AAC1E,wBAAgB,OAAO,CACtB,MAAM,EAAE,SAAS,OAAO,EAAE,EAC1B,OAAO,GAAE,SAAS,UAAU,EAAO,GACjC,QAAQ,CA0GV"}
package/dist/schema.js ADDED
@@ -0,0 +1,267 @@
1
+ import { modelDefinitions } from './definition.js';
2
+ import { Refused } from './errors.js';
3
+ import { installedUses } from './plugin-use.js';
4
+ import { checkRelations, isFiltered, viewField } from './relations.js';
5
+ import { checkIndexes, checkSearch } from './schema-indexes.js';
6
+ import { virtualsOf } from './schema-virtuals.js';
7
+ function fail(message) {
8
+ throw new Refused(message);
9
+ }
10
+ function inverseOf(link, links) {
11
+ const { model, name, target } = link;
12
+ const where = `${model}.${name}`;
13
+ const named = link.field.options['inverse'];
14
+ const back = links.filter((other) => other.model === target &&
15
+ other.target === model &&
16
+ !(other.model === model && other.name === name));
17
+ if (typeof named === 'string') {
18
+ const found = links.find((other) => other.model === target && other.name === named);
19
+ if (found === undefined || found.target !== model) {
20
+ fail(`${where}: inverse '${named}' is not a relation of ${target} to ${model}.`);
21
+ }
22
+ if (found.model === model && found.name === name) {
23
+ fail(`${where} cannot be its own inverse.`);
24
+ }
25
+ return found;
26
+ }
27
+ const candidates = back.filter((other) => {
28
+ const theirs = other.field.options['inverse'];
29
+ return typeof theirs !== 'string' || theirs === name;
30
+ });
31
+ const [only, ...others] = candidates;
32
+ if (only === undefined) {
33
+ fail(`${where}: ${target} has no relation to ${model}; add its side.`);
34
+ }
35
+ if (others.length > 0) {
36
+ fail(`${where}: ${target} has several relations to ${model}; name one with \`inverse\`.`);
37
+ }
38
+ return only;
39
+ }
40
+ function relationField(link, inverse) {
41
+ const { field } = link;
42
+ const optional = field.options['optional'] === true;
43
+ const where = `${link.model}.${link.name}`;
44
+ if (field.kind === 'many') {
45
+ return {
46
+ kind: 'many',
47
+ name: link.name,
48
+ target: link.target,
49
+ inverse: inverse.name,
50
+ join: inverse.field.kind === 'many',
51
+ options: field.options,
52
+ };
53
+ }
54
+ let stored = inverse.field.kind === 'many';
55
+ if (inverse.field.kind === 'one') {
56
+ const theirs = inverse.field.options['optional'] === true;
57
+ if (optional === theirs) {
58
+ fail(`${where} and ${inverse.model}.${inverse.name}: make one side of a one-to-one relation optional.`);
59
+ }
60
+ stored = !optional;
61
+ }
62
+ const asked = field.options['onDelete'];
63
+ if (!stored && asked !== undefined) {
64
+ fail(`${where}: onDelete belongs on ${inverse.model}.${inverse.name}, which stores the key.`);
65
+ }
66
+ if (asked === 'setNull' && !optional) {
67
+ throw new Refused(`${where}: setNull needs an optional relation.`);
68
+ }
69
+ const onDelete = asked === 'cascade' || asked === 'restrict' || asked === 'setNull'
70
+ ? asked
71
+ : optional
72
+ ? 'setNull'
73
+ : 'restrict';
74
+ const dbName = field.options['dbName'];
75
+ return {
76
+ kind: 'one',
77
+ name: link.name,
78
+ target: link.target,
79
+ inverse: inverse.name,
80
+ stored,
81
+ unique: stored && inverse.field.kind === 'one',
82
+ optional,
83
+ onDelete,
84
+ ...(typeof dbName === 'string' ? { dbName } : {}),
85
+ options: field.options,
86
+ };
87
+ }
88
+ /** A decimal's precision and scale, which its builder checked (D-145). */
89
+ const digitsOf = (options) => ({
90
+ precision: Number(options['precision']),
91
+ scale: Number(options['scale']),
92
+ });
93
+ function scalarField(name, field) {
94
+ if (field.kind !== 'scalar')
95
+ throw new Error('Expected a scalar field.');
96
+ const dbName = field.options['dbName'];
97
+ // A field type's default is a value code sees, never a column's; its
98
+ // stored field's fills the rows stored before it (D-122, D-152).
99
+ const fixed = field.codec === undefined ? field.options['default'] : field.codec.filled;
100
+ return {
101
+ kind: 'scalar',
102
+ name,
103
+ type: field.type,
104
+ ...(field.values === undefined ? {} : { values: field.values }),
105
+ list: field.options['list'] === true,
106
+ ...(field.type === 'number' && field.options['integer'] === true
107
+ ? { integer: true }
108
+ : {}),
109
+ ...(field.type === 'decimal' ? digitsOf(field.options) : {}),
110
+ optional: field.options['optional'] === true,
111
+ unique: field.options['unique'] === true,
112
+ ...(field.options['search'] === true ? { search: true } : {}),
113
+ ...(typeof dbName === 'string' ? { dbName } : {}),
114
+ // `null` is no value: a create without one stores none either.
115
+ ...(fixed === undefined || fixed === null || typeof fixed === 'function'
116
+ ? {}
117
+ : { default: fixed }),
118
+ options: field.options,
119
+ ...(field.codec === undefined ? {} : { codec: field.codec }),
120
+ ...(field.enum === undefined ? {} : { enum: field.enum }),
121
+ };
122
+ }
123
+ /** A field as the adapter reads it, without the builder's options. */
124
+ function schemaField(model, field) {
125
+ const { options: _options, codec: _codec, enum: _enum, ...schema } = field;
126
+ if (schema.kind !== 'many' || !isFiltered(model, field.name))
127
+ return schema;
128
+ return { ...schema, filtered: true };
129
+ }
130
+ const whose = (owner) => owner === undefined ? 'models lists' : `${owner}.models lists`;
131
+ /** The models, the application's then each plugin's, by name (D-110). */
132
+ function definitionsOf(values, plugins) {
133
+ const definitions = new Map();
134
+ const names = new Map();
135
+ const owners = new Map();
136
+ const lists = [
137
+ [undefined, values],
138
+ ...plugins.map((code) => [
139
+ code.name,
140
+ code.models,
141
+ ]),
142
+ ];
143
+ for (const [owner, list] of lists) {
144
+ for (const value of list) {
145
+ const definition = typeof value === 'object' && value !== null
146
+ ? modelDefinitions.get(value)
147
+ : undefined;
148
+ if (definition === undefined ||
149
+ typeof value !== 'object' ||
150
+ value === null) {
151
+ throw new Refused(`${whose(owner)} a value that defineModel did not return.`);
152
+ }
153
+ const { name } = definition;
154
+ if (owners.has(name)) {
155
+ const other = owners.get(name);
156
+ throw new Refused(owner === other
157
+ ? `${whose(owner)} two models named ${name}.`
158
+ : `${whose(owner)} a model named ${name}, as ${whose(other)}; name a plugin's models after it.`);
159
+ }
160
+ definitions.set(name, definition);
161
+ names.set(value, name);
162
+ owners.set(name, owner);
163
+ }
164
+ }
165
+ return { definitions, names, owners };
166
+ }
167
+ /** Resolves the application's models, or stops startup with a message. */
168
+ export function resolve(values, plugins = []) {
169
+ const { definitions, names, owners } = definitionsOf(values, plugins);
170
+ const links = [];
171
+ const views = [];
172
+ for (const [model, definition] of definitions) {
173
+ for (const [name, field] of definition.fields) {
174
+ if (field.kind === 'scalar' || field.kind === 'virtual')
175
+ continue;
176
+ const value = field.target();
177
+ const target = typeof value === 'object' && value !== null
178
+ ? names.get(value)
179
+ : undefined;
180
+ if (target === undefined) {
181
+ throw new Refused(`${model}.${name}: its target is not in models.`);
182
+ }
183
+ const owner = owners.get(model);
184
+ if (owner !== owners.get(target)) {
185
+ throw new Refused(`${model}.${name}: a plugin's model relates only to models of the same plugin; keep the id as a scalar.`);
186
+ }
187
+ // A view reads the link of another relation (D-151).
188
+ const from = field.kind === 'many' ? field.options['from'] : undefined;
189
+ const link = { model, name, field, target };
190
+ (typeof from === 'string' ? views : links).push(link);
191
+ }
192
+ }
193
+ const inverses = new Map(links.map((link) => [link, inverseOf(link, links)]));
194
+ for (const [link, inverse] of inverses) {
195
+ if (inverses.get(inverse) !== link) {
196
+ fail(`${link.model}.${link.name} and ${inverse.model}.${inverse.name} do not name each other.`);
197
+ }
198
+ }
199
+ const linkOf = (list, model, name) => list.find((each) => each.model === model && each.name === name);
200
+ const relationOf = (model, name) => {
201
+ const link = linkOf(links, model, name);
202
+ const inverse = link && inverses.get(link);
203
+ return link && inverse ? relationField(link, inverse) : undefined;
204
+ };
205
+ const fieldOf = (model, name, field) => {
206
+ const view = linkOf(views, model, name);
207
+ if (view === undefined) {
208
+ return relationOf(model, name) ?? scalarField(name, field);
209
+ }
210
+ const from = String(field.options['from']);
211
+ return viewField({ model, name, target: view.target, options: field.options }, from, linkOf(views, model, from) ? 'view' : relationOf(model, from));
212
+ };
213
+ const models = new Map();
214
+ const byValue = new Map();
215
+ const schemaModels = [];
216
+ for (const [model, definition] of definitions) {
217
+ const fields = new Map();
218
+ for (const [name, field] of definition.fields) {
219
+ // A virtual is no field of the adapter's (D-151).
220
+ if (field.kind === 'virtual')
221
+ continue;
222
+ const plugin = field.kind === 'scalar' ? field.codec?.plugin : undefined;
223
+ if (plugin !== undefined && !plugins.some((p) => p.name === plugin)) {
224
+ fail(`${model}.${name} is a ${plugin} field, and ${plugin} is not in plugins.`);
225
+ }
226
+ fields.set(name, fieldOf(model, name, field));
227
+ }
228
+ checkIndexes(model, fields, definition.indexes);
229
+ const uniques = [['id']];
230
+ for (const field of fields.values()) {
231
+ if (field.kind === 'scalar' && field.unique)
232
+ uniques.push([field.name]);
233
+ }
234
+ for (const index of definition.indexes) {
235
+ if (index.unique === true)
236
+ uniques.push(index.fields);
237
+ }
238
+ const info = {
239
+ name: model,
240
+ definition,
241
+ fields,
242
+ uniques,
243
+ plugins: installedUses(definition, plugins),
244
+ owner: owners.get(model),
245
+ virtuals: virtualsOf(model, definition, names),
246
+ };
247
+ checkSearch(info);
248
+ checkRelations(info);
249
+ models.set(model, info);
250
+ schemaModels.push({
251
+ name: model,
252
+ ...(definition.dbName === undefined ? {} : { dbName: definition.dbName }),
253
+ fields: [...fields.values()].map((field) => schemaField(info, field)),
254
+ indexes: definition.indexes.map((index) => ({
255
+ fields: index.fields,
256
+ unique: index.unique === true,
257
+ contains: index.contains === true,
258
+ })),
259
+ });
260
+ }
261
+ for (const [value, name] of names) {
262
+ const info = models.get(name);
263
+ if (info !== undefined)
264
+ byValue.set(value, info);
265
+ }
266
+ return { schema: { models: schemaModels }, models, byValue };
267
+ }
@@ -0,0 +1,46 @@
1
+ import type { Access } from './access.ts';
2
+ import type { Filter } from './adapter.ts';
3
+ import type { FindOperation } from './model.ts';
4
+ import type { Caller } from './rules.ts';
5
+ import type { FieldInfo, ModelInfo } from './schema.ts';
6
+ import type { Models, Scope, Verb } from './query-where.ts';
7
+ /**
8
+ * `readable` is synchronous, as the planning that calls it, but `beforeFind`
9
+ * may not be: a model read before its hook ran is recorded, and `ready` runs
10
+ * the hooks so the query can be planned again with their filters.
11
+ */
12
+ export declare class QueryScope implements Scope {
13
+ /** By `operation name`, as `read Post`. */
14
+ private readonly narrowed;
15
+ private readonly wanted;
16
+ readonly models: Models;
17
+ readonly caller: Caller;
18
+ /** `undefined` for Master, which skips access rules (D-48). */
19
+ readonly access: Access | undefined;
20
+ private readonly relations;
21
+ constructor(models: Models, caller: Caller, access: Access | undefined);
22
+ check(model: ModelInfo, field: string, path: string, verb: Verb): void;
23
+ ruled(model: ModelInfo, field: string): boolean;
24
+ /**
25
+ * The rows of `name` the query reads, or the write `operation` targets:
26
+ * its read rule and `beforeFind`.
27
+ */
28
+ readable(name: string, operation?: FindOperation): Filter | undefined;
29
+ related(model: ModelInfo, field: Extract<FieldInfo, {
30
+ readonly kind: 'many';
31
+ }>): Filter | undefined;
32
+ /**
33
+ * Runs the `beforeFind` hooks of the models read since the last call;
34
+ * whether one of them narrows, so the query must be planned again.
35
+ */
36
+ ready(): Promise<boolean>;
37
+ /**
38
+ * The rows of `name` a write reaches; `trusted` for a value a hook or a
39
+ * default wrote, which skips access rules but not `beforeFind` (D-67).
40
+ */
41
+ filter(name: string, trusted: boolean, operation?: FindOperation): Promise<Filter | undefined>;
42
+ private narrowing;
43
+ }
44
+ /** Plans a query, then again once the `beforeFind` hooks it reached ran. */
45
+ export declare function planned<T>(scope: QueryScope, build: () => T): Promise<T>;
46
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAG3D;;;;GAIG;AACH,qBAAa,UAAW,YAAW,KAAK;IACvC,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGpB;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IAErC,YAAY,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAKrE;IAED,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAErE;IAED,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE9C;IAED;;;OAGG;IACH,QAAQ,CACP,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,aAAsB,GAC/B,MAAM,GAAG,SAAS,CAEpB;IAED,OAAO,CACN,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,GAClD,MAAM,GAAG,SAAS,CAEpB;IAED;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAgB9B;IAED;;;OAGG;IACG,MAAM,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,aAAsB,GAC/B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAM7B;IAED,OAAO,CAAC,SAAS;CASjB;AAED,4EAA4E;AAC5E,wBAAsB,OAAO,CAAC,CAAC,EAC9B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,CAAC,GACZ,OAAO,CAAC,CAAC,CAAC,CAIZ"}