@mistriwork/engine 0.0.0-stage → 1.0.0-rc.10

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 (546) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -2
  3. package/dist/adapters/adapter.d.ts +693 -0
  4. package/dist/adapters/adapter.js +444 -0
  5. package/dist/adapters/cache/cacheStore.d.ts +75 -0
  6. package/dist/adapters/cache/cacheStore.js +160 -0
  7. package/dist/adapters/cache/resp.d.ts +52 -0
  8. package/dist/adapters/cache/resp.js +237 -0
  9. package/dist/adapters/commands/canonicalJson.d.ts +19 -0
  10. package/dist/adapters/commands/canonicalJson.js +154 -0
  11. package/dist/adapters/connect.d.ts +29 -0
  12. package/dist/adapters/connect.js +40 -0
  13. package/dist/adapters/connectionBudget.d.ts +101 -0
  14. package/dist/adapters/connectionBudget.js +128 -0
  15. package/dist/adapters/dbLatency.d.ts +35 -0
  16. package/dist/adapters/dbLatency.js +79 -0
  17. package/dist/adapters/epochCache.d.ts +50 -0
  18. package/dist/adapters/epochCache.js +85 -0
  19. package/dist/adapters/http/egress.d.ts +48 -0
  20. package/dist/adapters/http/egress.js +175 -0
  21. package/dist/adapters/http/httpAdapter.d.ts +71 -0
  22. package/dist/adapters/http/httpAdapter.js +512 -0
  23. package/dist/adapters/http/httpDescription.d.ts +32 -0
  24. package/dist/adapters/http/httpDescription.js +246 -0
  25. package/dist/adapters/http/openapi.d.ts +98 -0
  26. package/dist/adapters/http/openapi.js +487 -0
  27. package/dist/adapters/layoutRefusal.d.ts +24 -0
  28. package/dist/adapters/layoutRefusal.js +35 -0
  29. package/dist/adapters/net/networkPolicy.d.ts +44 -0
  30. package/dist/adapters/net/networkPolicy.js +123 -0
  31. package/dist/adapters/net/untrustedDatabase.d.ts +18 -0
  32. package/dist/adapters/net/untrustedDatabase.js +120 -0
  33. package/dist/adapters/poolAdmission.d.ts +43 -0
  34. package/dist/adapters/poolAdmission.js +184 -0
  35. package/dist/adapters/poolMetrics.d.ts +121 -0
  36. package/dist/adapters/poolMetrics.js +185 -0
  37. package/dist/adapters/postgres.d.ts +436 -0
  38. package/dist/adapters/postgres.js +1890 -0
  39. package/dist/adapters/postgresCatalog.d.ts +96 -0
  40. package/dist/adapters/postgresCatalog.js +387 -0
  41. package/dist/adapters/postgresCatalogDigest.d.ts +30 -0
  42. package/dist/adapters/postgresCatalogDigest.js +87 -0
  43. package/dist/adapters/postgresCatalogRows.d.ts +62 -0
  44. package/dist/adapters/postgresCatalogRows.js +37 -0
  45. package/dist/adapters/postgresDates.d.ts +1 -0
  46. package/dist/adapters/postgresDates.js +39 -0
  47. package/dist/adapters/postgresMaintenance.d.ts +33 -0
  48. package/dist/adapters/postgresMaintenance.js +179 -0
  49. package/dist/adapters/postgresPool.d.ts +255 -0
  50. package/dist/adapters/postgresPool.js +838 -0
  51. package/dist/adapters/postgresPooler.d.ts +28 -0
  52. package/dist/adapters/postgresPooler.js +267 -0
  53. package/dist/adapters/postgresReadCatalog.d.ts +31 -0
  54. package/dist/adapters/postgresReadCatalog.js +226 -0
  55. package/dist/adapters/postgresReadSnapshot.d.ts +46 -0
  56. package/dist/adapters/postgresReadSnapshot.js +133 -0
  57. package/dist/adapters/postgresSchemaEpoch.d.ts +24 -0
  58. package/dist/adapters/postgresSchemaEpoch.js +149 -0
  59. package/dist/adapters/postgresTransactionHandle.d.ts +173 -0
  60. package/dist/adapters/postgresTransactionHandle.js +524 -0
  61. package/dist/adapters/postgresValues.d.ts +30 -0
  62. package/dist/adapters/postgresValues.js +75 -0
  63. package/dist/adapters/replicas.d.ts +70 -0
  64. package/dist/adapters/replicas.js +208 -0
  65. package/dist/adapters/reservedSql.d.ts +38 -0
  66. package/dist/adapters/reservedSql.js +264 -0
  67. package/dist/adapters/rolePrivileges.d.ts +17 -0
  68. package/dist/adapters/rolePrivileges.js +22 -0
  69. package/dist/adapters/scoped/keyRows.d.ts +65 -0
  70. package/dist/adapters/scoped/keyRows.js +173 -0
  71. package/dist/adapters/scoped/postgresScopeCatalog.d.ts +16 -0
  72. package/dist/adapters/scoped/postgresScopeCatalog.js +117 -0
  73. package/dist/adapters/scoped/scopedCommandOperations.d.ts +5 -0
  74. package/dist/adapters/scoped/scopedCommandOperations.js +48 -0
  75. package/dist/adapters/scoped/scopedReads.d.ts +20 -0
  76. package/dist/adapters/scoped/scopedReads.js +174 -0
  77. package/dist/adapters/scoped/scopedTransaction.d.ts +89 -0
  78. package/dist/adapters/scoped/scopedTransaction.js +303 -0
  79. package/dist/adapters/scoped/sqliteScopeCatalog.d.ts +16 -0
  80. package/dist/adapters/scoped/sqliteScopeCatalog.js +241 -0
  81. package/dist/adapters/scoped/updateGuard.d.ts +3 -0
  82. package/dist/adapters/scoped/updateGuard.js +40 -0
  83. package/dist/adapters/serverSettings.d.ts +45 -0
  84. package/dist/adapters/serverSettings.js +46 -0
  85. package/dist/adapters/sqlite.d.ts +262 -0
  86. package/dist/adapters/sqlite.js +1434 -0
  87. package/dist/adapters/sqliteCostlyReads.d.ts +33 -0
  88. package/dist/adapters/sqliteCostlyReads.js +49 -0
  89. package/dist/adapters/sqliteDecimals.d.ts +22 -0
  90. package/dist/adapters/sqliteDecimals.js +57 -0
  91. package/dist/adapters/sqliteHandles.d.ts +43 -0
  92. package/dist/adapters/sqliteHandles.js +143 -0
  93. package/dist/adapters/sqliteStatementProcess.d.ts +29 -0
  94. package/dist/adapters/sqliteStatementProcess.js +131 -0
  95. package/dist/adapters/statementControl.d.ts +34 -0
  96. package/dist/adapters/statementControl.js +90 -0
  97. package/dist/adapters/storeHost.d.ts +130 -0
  98. package/dist/adapters/storeHost.js +13 -0
  99. package/dist/adapters/telemetry/drivers.d.ts +21 -0
  100. package/dist/adapters/telemetry/drivers.js +321 -0
  101. package/dist/adapters/telemetry/metrics.d.ts +63 -0
  102. package/dist/adapters/telemetry/metrics.js +122 -0
  103. package/dist/adapters/telemetry/otlp.d.ts +12 -0
  104. package/dist/adapters/telemetry/otlp.js +320 -0
  105. package/dist/adapters/telemetry/otlpEncode.d.ts +48 -0
  106. package/dist/adapters/telemetry/otlpEncode.js +366 -0
  107. package/dist/adapters/telemetry/otlpEnv.d.ts +1 -0
  108. package/dist/adapters/telemetry/otlpEnv.js +12 -0
  109. package/dist/adapters/telemetry/serverTiming.d.ts +83 -0
  110. package/dist/adapters/telemetry/serverTiming.js +503 -0
  111. package/dist/adapters/telemetry/start.d.ts +10 -0
  112. package/dist/adapters/telemetry/start.js +25 -0
  113. package/dist/adapters/telemetry/statement.d.ts +16 -0
  114. package/dist/adapters/telemetry/statement.js +134 -0
  115. package/dist/adapters/telemetry/trace.d.ts +127 -0
  116. package/dist/adapters/telemetry/trace.js +295 -0
  117. package/dist/adapters/writeAhead.d.ts +27 -0
  118. package/dist/adapters/writeAhead.js +46 -0
  119. package/dist/adapters/writeAttribution.d.ts +18 -0
  120. package/dist/adapters/writeAttribution.js +23 -0
  121. package/dist/adapters/writeCapture.d.ts +73 -0
  122. package/dist/adapters/writeCapture.js +20 -0
  123. package/dist/adapters/writeLanes.d.ts +94 -0
  124. package/dist/adapters/writeLanes.js +232 -0
  125. package/dist/engine.d.ts +15 -0
  126. package/dist/engine.js +13 -0
  127. package/dist/server/auth/credentials.d.ts +61 -0
  128. package/dist/server/auth/credentials.js +260 -0
  129. package/dist/server/cacheService.d.ts +50 -0
  130. package/dist/server/cacheService.js +110 -0
  131. package/dist/server/cli/args.d.ts +176 -0
  132. package/dist/server/cli/args.js +342 -0
  133. package/dist/server/cli/bin.d.ts +5 -0
  134. package/dist/server/cli/bin.js +66 -0
  135. package/dist/server/cli/browser.d.ts +15 -0
  136. package/dist/server/cli/browser.js +37 -0
  137. package/dist/server/cli/config.d.ts +50 -0
  138. package/dist/server/cli/config.js +206 -0
  139. package/dist/server/cli/startup.d.ts +36 -0
  140. package/dist/server/cli/startup.js +128 -0
  141. package/dist/server/cli/startupOptions.d.ts +63 -0
  142. package/dist/server/cli/startupOptions.js +143 -0
  143. package/dist/server/cli/subcommand.d.ts +28 -0
  144. package/dist/server/cli/subcommand.js +32 -0
  145. package/dist/server/cli/usage.d.ts +13 -0
  146. package/dist/server/cli/usage.js +31 -0
  147. package/dist/server/clientHttp.d.ts +184 -0
  148. package/dist/server/clientHttp.js +700 -0
  149. package/dist/server/clientSurface.d.ts +128 -0
  150. package/dist/server/clientSurface.js +182 -0
  151. package/dist/server/columnGrants.d.ts +103 -0
  152. package/dist/server/columnGrants.js +730 -0
  153. package/dist/server/compileCache.d.ts +1 -0
  154. package/dist/server/compileCache.js +30 -0
  155. package/dist/server/config/locations.d.ts +1 -0
  156. package/dist/server/config/locations.js +15 -0
  157. package/dist/server/configPaths.d.ts +7 -0
  158. package/dist/server/configPaths.js +34 -0
  159. package/dist/server/configSections.d.ts +64 -0
  160. package/dist/server/configSections.js +72 -0
  161. package/dist/server/connectionRedaction.d.ts +30 -0
  162. package/dist/server/connectionRedaction.js +77 -0
  163. package/dist/server/connections.d.ts +353 -0
  164. package/dist/server/connections.js +978 -0
  165. package/dist/server/constraints.d.ts +82 -0
  166. package/dist/server/constraints.js +169 -0
  167. package/dist/server/demo.d.ts +9 -0
  168. package/dist/server/demo.js +554 -0
  169. package/dist/server/devclient.d.ts +108 -0
  170. package/dist/server/devclient.js +361 -0
  171. package/dist/server/evidence.d.ts +55 -0
  172. package/dist/server/evidence.js +323 -0
  173. package/dist/server/hiddenColumns.d.ts +32 -0
  174. package/dist/server/hiddenColumns.js +238 -0
  175. package/dist/server/http/baselineHeaders.d.ts +24 -0
  176. package/dist/server/http/baselineHeaders.js +12 -0
  177. package/dist/server/http/captured.d.ts +35 -0
  178. package/dist/server/http/captured.js +73 -0
  179. package/dist/server/http/clock.d.ts +1 -0
  180. package/dist/server/http/clock.js +14 -0
  181. package/dist/server/http/connectionSource.d.ts +4 -0
  182. package/dist/server/http/connectionSource.js +48 -0
  183. package/dist/server/http/context.d.ts +189 -0
  184. package/dist/server/http/context.js +11 -0
  185. package/dist/server/http/crawlerText.d.ts +15 -0
  186. package/dist/server/http/crawlerText.js +32 -0
  187. package/dist/server/http/dataRoutes.d.ts +88 -0
  188. package/dist/server/http/dataRoutes.js +137 -0
  189. package/dist/server/http/door.d.ts +57 -0
  190. package/dist/server/http/door.js +39 -0
  191. package/dist/server/http/exportRoute.d.ts +15 -0
  192. package/dist/server/http/exportRoute.js +320 -0
  193. package/dist/server/http/firstPaint.d.ts +108 -0
  194. package/dist/server/http/firstPaint.js +262 -0
  195. package/dist/server/http/httpOperationRoutes.d.ts +11 -0
  196. package/dist/server/http/httpOperationRoutes.js +50 -0
  197. package/dist/server/http/pageReads.d.ts +20 -0
  198. package/dist/server/http/pageReads.js +205 -0
  199. package/dist/server/http/pageRoutes.d.ts +39 -0
  200. package/dist/server/http/pageRoutes.js +291 -0
  201. package/dist/server/http/probes.d.ts +22 -0
  202. package/dist/server/http/probes.js +27 -0
  203. package/dist/server/http/rateLimit.d.ts +131 -0
  204. package/dist/server/http/rateLimit.js +351 -0
  205. package/dist/server/http/readRoutes.d.ts +9 -0
  206. package/dist/server/http/readRoutes.js +131 -0
  207. package/dist/server/http/readRouting.d.ts +20 -0
  208. package/dist/server/http/readRouting.js +80 -0
  209. package/dist/server/http/recordCompose.d.ts +67 -0
  210. package/dist/server/http/recordCompose.js +167 -0
  211. package/dist/server/http/recordWrites.d.ts +89 -0
  212. package/dist/server/http/recordWrites.js +298 -0
  213. package/dist/server/http/refusalReport.d.ts +38 -0
  214. package/dist/server/http/refusalReport.js +63 -0
  215. package/dist/server/http/reply.d.ts +130 -0
  216. package/dist/server/http/reply.js +394 -0
  217. package/dist/server/http/requestOrigin.d.ts +11 -0
  218. package/dist/server/http/requestOrigin.js +8 -0
  219. package/dist/server/http/router.d.ts +45 -0
  220. package/dist/server/http/router.js +22 -0
  221. package/dist/server/http/serverCore.d.ts +68 -0
  222. package/dist/server/http/serverCore.js +177 -0
  223. package/dist/server/http/traceRequest.d.ts +30 -0
  224. package/dist/server/http/traceRequest.js +224 -0
  225. package/dist/server/http/trust.d.ts +261 -0
  226. package/dist/server/http/trust.js +472 -0
  227. package/dist/server/http/writeRefusal.d.ts +33 -0
  228. package/dist/server/http/writeRefusal.js +24 -0
  229. package/dist/server/httpConnection.d.ts +49 -0
  230. package/dist/server/httpConnection.js +170 -0
  231. package/dist/server/impact.d.ts +55 -0
  232. package/dist/server/impact.js +47 -0
  233. package/dist/server/journal.d.ts +134 -0
  234. package/dist/server/journal.js +398 -0
  235. package/dist/server/keysetReadHttp.d.ts +52 -0
  236. package/dist/server/keysetReadHttp.js +85 -0
  237. package/dist/server/layouts.d.ts +49 -0
  238. package/dist/server/layouts.js +192 -0
  239. package/dist/server/migrate/cli.d.ts +55 -0
  240. package/dist/server/migrate/cli.js +517 -0
  241. package/dist/server/migrate/database.d.ts +37 -0
  242. package/dist/server/migrate/database.js +247 -0
  243. package/dist/server/migrate/desired.d.ts +76 -0
  244. package/dist/server/migrate/desired.js +292 -0
  245. package/dist/server/migrate/files.d.ts +34 -0
  246. package/dist/server/migrate/files.js +141 -0
  247. package/dist/server/migrate/flyway.d.ts +7 -0
  248. package/dist/server/migrate/flyway.js +69 -0
  249. package/dist/server/migrate/history.d.ts +70 -0
  250. package/dist/server/migrate/history.js +211 -0
  251. package/dist/server/migrate/runner.d.ts +100 -0
  252. package/dist/server/migrate/runner.js +409 -0
  253. package/dist/server/migrate/snapshot.d.ts +30 -0
  254. package/dist/server/migrate/snapshot.js +239 -0
  255. package/dist/server/migrate/target.d.ts +33 -0
  256. package/dist/server/migrate/target.js +82 -0
  257. package/dist/server/openapiDraft.d.ts +25 -0
  258. package/dist/server/openapiDraft.js +171 -0
  259. package/dist/server/operations/diagnostics.d.ts +101 -0
  260. package/dist/server/operations/diagnostics.js +284 -0
  261. package/dist/server/operations/requestMetrics.d.ts +33 -0
  262. package/dist/server/operations/requestMetrics.js +94 -0
  263. package/dist/server/packageVersion.d.ts +1 -0
  264. package/dist/server/packageVersion.js +11 -0
  265. package/dist/server/poolConfig.d.ts +34 -0
  266. package/dist/server/poolConfig.js +114 -0
  267. package/dist/server/product.d.ts +20 -0
  268. package/dist/server/product.js +12 -0
  269. package/dist/server/recordHistoryOperations.d.ts +39 -0
  270. package/dist/server/recordHistoryOperations.js +43 -0
  271. package/dist/server/recordWriteOperations.d.ts +111 -0
  272. package/dist/server/recordWriteOperations.js +329 -0
  273. package/dist/server/resourceReadHttp.d.ts +81 -0
  274. package/dist/server/resourceReadHttp.js +606 -0
  275. package/dist/server/resourceReadOperations.d.ts +147 -0
  276. package/dist/server/resourceReadOperations.js +452 -0
  277. package/dist/server/scaffoldMachine.d.ts +54 -0
  278. package/dist/server/scaffoldMachine.js +184 -0
  279. package/dist/server/seed/cli.d.ts +20 -0
  280. package/dist/server/seed/cli.js +164 -0
  281. package/dist/server/seed/lexicon.d.ts +26 -0
  282. package/dist/server/seed/lexicon.js +585 -0
  283. package/dist/server/seed/seed.d.ts +70 -0
  284. package/dist/server/seed/seed.js +779 -0
  285. package/dist/server/seed/words.d.ts +21 -0
  286. package/dist/server/seed/words.js +164 -0
  287. package/dist/server/serverRequests.d.ts +6 -0
  288. package/dist/server/serverRequests.js +33 -0
  289. package/dist/server/serverTimeouts.d.ts +33 -0
  290. package/dist/server/serverTimeouts.js +32 -0
  291. package/dist/server/shapeonly.d.ts +32 -0
  292. package/dist/server/shapeonly.js +110 -0
  293. package/dist/server/startupWarnings.d.ts +32 -0
  294. package/dist/server/startupWarnings.js +92 -0
  295. package/dist/shared/addressParams.d.ts +28 -0
  296. package/dist/shared/addressParams.js +47 -0
  297. package/dist/shared/appCards.d.ts +123 -0
  298. package/dist/shared/appCards.js +385 -0
  299. package/dist/shared/appComponents.d.ts +177 -0
  300. package/dist/shared/appComponents.js +422 -0
  301. package/dist/shared/appDocuments.d.ts +43 -0
  302. package/dist/shared/appDocuments.js +131 -0
  303. package/dist/shared/appEmbeds.d.ts +21 -0
  304. package/dist/shared/appEmbeds.js +24 -0
  305. package/dist/shared/appIcons.d.ts +28 -0
  306. package/dist/shared/appIcons.js +223 -0
  307. package/dist/shared/appLinks.d.ts +17 -0
  308. package/dist/shared/appLinks.js +124 -0
  309. package/dist/shared/appListColumns.d.ts +3 -0
  310. package/dist/shared/appListColumns.js +66 -0
  311. package/dist/shared/appLocale.d.ts +36 -0
  312. package/dist/shared/appLocale.js +86 -0
  313. package/dist/shared/appMessages.d.ts +44 -0
  314. package/dist/shared/appMessages.js +78 -0
  315. package/dist/shared/appNoun.d.ts +21 -0
  316. package/dist/shared/appNoun.js +32 -0
  317. package/dist/shared/autoBucket.d.ts +98 -0
  318. package/dist/shared/autoBucket.js +305 -0
  319. package/dist/shared/autoValues.d.ts +25 -0
  320. package/dist/shared/autoValues.js +25 -0
  321. package/dist/shared/breakdown.d.ts +228 -0
  322. package/dist/shared/breakdown.js +557 -0
  323. package/dist/shared/breakdowntext.d.ts +41 -0
  324. package/dist/shared/breakdowntext.js +400 -0
  325. package/dist/shared/builtInThemes.d.ts +2 -0
  326. package/dist/shared/builtInThemes.js +771 -0
  327. package/dist/shared/chartSeparation.d.ts +11 -0
  328. package/dist/shared/chartSeparation.js +58 -0
  329. package/dist/shared/clauses.d.ts +22 -0
  330. package/dist/shared/clauses.js +97 -0
  331. package/dist/shared/columnCaption.d.ts +16 -0
  332. package/dist/shared/columnCaption.js +90 -0
  333. package/dist/shared/commandFieldPath.d.ts +2 -0
  334. package/dist/shared/commandFieldPath.js +7 -0
  335. package/dist/shared/commandWire.d.ts +26 -0
  336. package/dist/shared/commandWire.js +41 -0
  337. package/dist/shared/computed.d.ts +161 -0
  338. package/dist/shared/computed.js +378 -0
  339. package/dist/shared/computedParse.d.ts +13 -0
  340. package/dist/shared/computedParse.js +278 -0
  341. package/dist/shared/computedValue.d.ts +47 -0
  342. package/dist/shared/computedValue.js +191 -0
  343. package/dist/shared/connection.d.ts +30 -0
  344. package/dist/shared/connection.js +1 -0
  345. package/dist/shared/csv.d.ts +20 -0
  346. package/dist/shared/csv.js +63 -0
  347. package/dist/shared/dashLayout.d.ts +30 -0
  348. package/dist/shared/dashLayout.js +132 -0
  349. package/dist/shared/dashboardAsks.d.ts +93 -0
  350. package/dist/shared/dashboardAsks.js +129 -0
  351. package/dist/shared/dashboardTrend.d.ts +20 -0
  352. package/dist/shared/dashboardTrend.js +50 -0
  353. package/dist/shared/declaredReferences.d.ts +50 -0
  354. package/dist/shared/declaredReferences.js +202 -0
  355. package/dist/shared/definedFields.d.ts +63 -0
  356. package/dist/shared/definedFields.js +103 -0
  357. package/dist/shared/definedValues.d.ts +63 -0
  358. package/dist/shared/definedValues.js +184 -0
  359. package/dist/shared/displayDefaults.d.ts +135 -0
  360. package/dist/shared/displayDefaults.js +529 -0
  361. package/dist/shared/dueDate.d.ts +6 -0
  362. package/dist/shared/dueDate.js +6 -0
  363. package/dist/shared/duration.d.ts +4 -0
  364. package/dist/shared/duration.js +23 -0
  365. package/dist/shared/fileBounds.d.ts +9 -0
  366. package/dist/shared/fileBounds.js +9 -0
  367. package/dist/shared/filter.d.ts +217 -0
  368. package/dist/shared/filter.js +305 -0
  369. package/dist/shared/firstPaint.d.ts +24 -0
  370. package/dist/shared/firstPaint.js +33 -0
  371. package/dist/shared/form.d.ts +21 -0
  372. package/dist/shared/form.js +25 -0
  373. package/dist/shared/formValues.d.ts +104 -0
  374. package/dist/shared/formValues.js +352 -0
  375. package/dist/shared/funnel.d.ts +45 -0
  376. package/dist/shared/funnel.js +108 -0
  377. package/dist/shared/httpOperations.d.ts +48 -0
  378. package/dist/shared/httpOperations.js +9 -0
  379. package/dist/shared/iconGlyphs.d.ts +4 -0
  380. package/dist/shared/iconGlyphs.js +151 -0
  381. package/dist/shared/iconWeights.d.ts +3 -0
  382. package/dist/shared/iconWeights.js +162 -0
  383. package/dist/shared/imageWidths.d.ts +32 -0
  384. package/dist/shared/imageWidths.js +38 -0
  385. package/dist/shared/keysetPage.d.ts +64 -0
  386. package/dist/shared/keysetPage.js +161 -0
  387. package/dist/shared/like.d.ts +20 -0
  388. package/dist/shared/like.js +29 -0
  389. package/dist/shared/listEmpty.d.ts +12 -0
  390. package/dist/shared/listEmpty.js +36 -0
  391. package/dist/shared/listFilters.d.ts +28 -0
  392. package/dist/shared/listFilters.js +84 -0
  393. package/dist/shared/listPresentations.d.ts +199 -0
  394. package/dist/shared/listPresentations.js +7 -0
  395. package/dist/shared/listQuestion.d.ts +52 -0
  396. package/dist/shared/listQuestion.js +137 -0
  397. package/dist/shared/lookPalettes.d.ts +62 -0
  398. package/dist/shared/lookPalettes.js +306 -0
  399. package/dist/shared/maskQuoted.d.ts +24 -0
  400. package/dist/shared/maskQuoted.js +48 -0
  401. package/dist/shared/mentionLabel.d.ts +19 -0
  402. package/dist/shared/mentionLabel.js +38 -0
  403. package/dist/shared/mentionLookup.d.ts +17 -0
  404. package/dist/shared/mentionLookup.js +64 -0
  405. package/dist/shared/menuCounts.d.ts +16 -0
  406. package/dist/shared/menuCounts.js +74 -0
  407. package/dist/shared/model.d.ts +79 -0
  408. package/dist/shared/model.js +153 -0
  409. package/dist/shared/money.d.ts +44 -0
  410. package/dist/shared/money.js +81 -0
  411. package/dist/shared/moneyEntry.d.ts +7 -0
  412. package/dist/shared/moneyEntry.js +27 -0
  413. package/dist/shared/mount.d.ts +118 -0
  414. package/dist/shared/mount.js +248 -0
  415. package/dist/shared/niceTicks.d.ts +26 -0
  416. package/dist/shared/niceTicks.js +50 -0
  417. package/dist/shared/order.d.ts +59 -0
  418. package/dist/shared/order.js +133 -0
  419. package/dist/shared/page.d.ts +135 -0
  420. package/dist/shared/page.js +1187 -0
  421. package/dist/shared/pageAnatomy.d.ts +99 -0
  422. package/dist/shared/pageAnatomy.js +370 -0
  423. package/dist/shared/pageConfig.d.ts +25 -0
  424. package/dist/shared/pageConfig.js +1308 -0
  425. package/dist/shared/pageEmptyActions.d.ts +12 -0
  426. package/dist/shared/pageEmptyActions.js +20 -0
  427. package/dist/shared/pageLayouts.d.ts +72 -0
  428. package/dist/shared/pageLayouts.js +205 -0
  429. package/dist/shared/pageModel.d.ts +785 -0
  430. package/dist/shared/pageModel.js +121 -0
  431. package/dist/shared/pagePaths.d.ts +180 -0
  432. package/dist/shared/pagePaths.js +869 -0
  433. package/dist/shared/pagePlans.d.ts +52 -0
  434. package/dist/shared/pagePlans.js +108 -0
  435. package/dist/shared/pageRoutes.d.ts +9 -0
  436. package/dist/shared/pageRoutes.js +9 -0
  437. package/dist/shared/query.d.ts +166 -0
  438. package/dist/shared/query.js +1302 -0
  439. package/dist/shared/queryDates.d.ts +12 -0
  440. package/dist/shared/queryDates.js +101 -0
  441. package/dist/shared/queryOperands.d.ts +99 -0
  442. package/dist/shared/queryOperands.js +131 -0
  443. package/dist/shared/reads.d.ts +103 -0
  444. package/dist/shared/reads.js +154 -0
  445. package/dist/shared/recordLabel.d.ts +51 -0
  446. package/dist/shared/recordLabel.js +123 -0
  447. package/dist/shared/recordReadKeys.d.ts +30 -0
  448. package/dist/shared/recordReadKeys.js +51 -0
  449. package/dist/shared/recordReads.d.ts +268 -0
  450. package/dist/shared/recordReads.js +368 -0
  451. package/dist/shared/recordview.d.ts +198 -0
  452. package/dist/shared/recordview.js +356 -0
  453. package/dist/shared/referenceModel.d.ts +58 -0
  454. package/dist/shared/referenceModel.js +194 -0
  455. package/dist/shared/refusal.d.ts +64 -0
  456. package/dist/shared/refusal.js +144 -0
  457. package/dist/shared/relatedCreate.d.ts +30 -0
  458. package/dist/shared/relatedCreate.js +162 -0
  459. package/dist/shared/resourceHttp.d.ts +464 -0
  460. package/dist/shared/resourceHttp.js +1 -0
  461. package/dist/shared/richText.d.ts +85 -0
  462. package/dist/shared/richText.js +305 -0
  463. package/dist/shared/rollups.d.ts +143 -0
  464. package/dist/shared/rollups.js +64 -0
  465. package/dist/shared/rowScope.d.ts +72 -0
  466. package/dist/shared/rowScope.js +376 -0
  467. package/dist/shared/runtimeTables.d.ts +44 -0
  468. package/dist/shared/runtimeTables.js +79 -0
  469. package/dist/shared/schema.d.ts +523 -0
  470. package/dist/shared/schema.js +627 -0
  471. package/dist/shared/schematext.d.ts +38 -0
  472. package/dist/shared/schematext.js +101 -0
  473. package/dist/shared/scopeCatalog.d.ts +29 -0
  474. package/dist/shared/scopeCatalog.js +468 -0
  475. package/dist/shared/servedApp.d.ts +681 -0
  476. package/dist/shared/servedApp.js +45 -0
  477. package/dist/shared/sessionLease.d.ts +34 -0
  478. package/dist/shared/sessionLease.js +3 -0
  479. package/dist/shared/shape.d.ts +55 -0
  480. package/dist/shared/shape.js +168 -0
  481. package/dist/shared/slug.d.ts +1 -0
  482. package/dist/shared/slug.js +12 -0
  483. package/dist/shared/sortText.d.ts +14 -0
  484. package/dist/shared/sortText.js +26 -0
  485. package/dist/shared/sqlRelation.d.ts +4 -0
  486. package/dist/shared/sqlRelation.js +8 -0
  487. package/dist/shared/sqlsaved.d.ts +44 -0
  488. package/dist/shared/sqlsaved.js +63 -0
  489. package/dist/shared/stitchedPaths.d.ts +27 -0
  490. package/dist/shared/stitchedPaths.js +38 -0
  491. package/dist/shared/structuredFilter.d.ts +22 -0
  492. package/dist/shared/structuredFilter.js +1 -0
  493. package/dist/shared/subtitlePath.d.ts +20 -0
  494. package/dist/shared/subtitlePath.js +24 -0
  495. package/dist/shared/suggest.d.ts +18 -0
  496. package/dist/shared/suggest.js +59 -0
  497. package/dist/shared/tableSizing.d.ts +4 -0
  498. package/dist/shared/tableSizing.js +9 -0
  499. package/dist/shared/tagLists.d.ts +57 -0
  500. package/dist/shared/tagLists.js +34 -0
  501. package/dist/shared/textRules.d.ts +54 -0
  502. package/dist/shared/textRules.js +133 -0
  503. package/dist/shared/theme.d.ts +94 -0
  504. package/dist/shared/theme.js +800 -0
  505. package/dist/shared/themeColor.d.ts +34 -0
  506. package/dist/shared/themeColor.js +109 -0
  507. package/dist/shared/themeFaces.d.ts +30 -0
  508. package/dist/shared/themeFaces.js +42 -0
  509. package/dist/shared/themeInk.d.ts +20 -0
  510. package/dist/shared/themeInk.js +52 -0
  511. package/dist/shared/themeLooks.d.ts +9 -0
  512. package/dist/shared/themeLooks.js +572 -0
  513. package/dist/shared/themeParts.d.ts +26 -0
  514. package/dist/shared/themeParts.js +71 -0
  515. package/dist/shared/themePartsCheck.d.ts +21 -0
  516. package/dist/shared/themePartsCheck.js +91 -0
  517. package/dist/shared/themePresets.d.ts +85 -0
  518. package/dist/shared/themePresets.js +139 -0
  519. package/dist/shared/themeRecipeWords.d.ts +156 -0
  520. package/dist/shared/themeRecipeWords.js +156 -0
  521. package/dist/shared/themeRecipes.d.ts +213 -0
  522. package/dist/shared/themeRecipes.js +234 -0
  523. package/dist/shared/themeResolve.d.ts +55 -0
  524. package/dist/shared/themeResolve.js +52 -0
  525. package/dist/shared/themeTokens.d.ts +107 -0
  526. package/dist/shared/themeTokens.js +116 -0
  527. package/dist/shared/themeType.d.ts +38 -0
  528. package/dist/shared/themeType.js +205 -0
  529. package/dist/shared/unitWord.d.ts +4 -0
  530. package/dist/shared/unitWord.js +37 -0
  531. package/dist/shared/view.d.ts +195 -0
  532. package/dist/shared/view.js +987 -0
  533. package/dist/shared/viewLabels.d.ts +47 -0
  534. package/dist/shared/viewLabels.js +459 -0
  535. package/dist/shared/viewPaths.d.ts +248 -0
  536. package/dist/shared/viewPaths.js +294 -0
  537. package/dist/shared/viewtext.d.ts +57 -0
  538. package/dist/shared/viewtext.js +282 -0
  539. package/dist/shared/vocabulary.d.ts +71 -0
  540. package/dist/shared/vocabulary.js +249 -0
  541. package/dist/shared/weekStart.d.ts +7 -0
  542. package/dist/shared/weekStart.js +36 -0
  543. package/mark.svg +1 -0
  544. package/package.json +261 -4
  545. package/schema/model.d.ts +298 -0
  546. package/schema/theme.d.ts +587 -0
@@ -0,0 +1,779 @@
1
+ import { isMoneyColumn } from '../../shared/displayDefaults.js';
2
+ import { columnKind, isFlagColumn, momentColumn, stateStampColumn, } from '../../shared/schema.js';
3
+ import { draftMachine } from '../scaffoldMachine.js';
4
+ import * as L from './lexicon.js';
5
+ import * as W from './words.js';
6
+ /** A refusal before anything is written: said to the person, exit 2. */
7
+ export class SeedRefusal extends Error {
8
+ }
9
+ /* ---------- the generator ---------- */
10
+ function mulberry32(seed) {
11
+ let a = seed >>> 0;
12
+ return () => {
13
+ a = (a + 0x6d2b79f5) >>> 0;
14
+ let t = a;
15
+ t = Math.imul(t ^ (t >>> 15), t | 1);
16
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
17
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
18
+ };
19
+ }
20
+ class Dice {
21
+ next;
22
+ constructor(seed) {
23
+ this.next = mulberry32(seed);
24
+ }
25
+ int(lo, hi) {
26
+ return lo + Math.floor(this.next() * (hi - lo + 1));
27
+ }
28
+ pick(list) {
29
+ return list[Math.floor(this.next() * list.length)];
30
+ }
31
+ chance(p) {
32
+ return this.next() < p;
33
+ }
34
+ weighted(items, weight) {
35
+ const total = items.reduce((sum, item) => sum + weight(item), 0);
36
+ let at = this.next() * total;
37
+ for (const item of items)
38
+ if ((at -= weight(item)) < 0)
39
+ return item;
40
+ return items[items.length - 1];
41
+ }
42
+ }
43
+ /* ---------- reading the schema ---------- */
44
+ const DAY = 86_400_000;
45
+ const two = (n) => String(n).padStart(2, '0');
46
+ const dayText = (at) => at.toISOString().slice(0, 10);
47
+ const wallText = (at) => `${dayText(at)} ${two(at.getUTCHours())}:${two(at.getUTCMinutes())}:${two(at.getUTCSeconds())}`;
48
+ /* The runtime's own tables (the migration history, its stores, by their names before and since mistri) are not the
49
+ App's to fill. */
50
+ const OWN = /^(__)?mistri_|^_mistri/i;
51
+ const STAFF = /^(staff|users?|employees?|mechanics?|agents?|technicians?|members?|team|team_members?|operators?|engineers?|people|persons?|reps?)$/i;
52
+ const PERSON = /^(customers?|clients?|contacts?|patients?|students?|drivers?|owners?|authors?|guests?|tenants?|buyers?|sellers?|leads?|subscribers?|volunteers?|applicants?|candidates?)$/i;
53
+ const COMPANY = /^(companies|company|accounts?|organi[sz]ations?|orgs?|vendors?|suppliers?|partners?|businesses|business|firms?|brands?)$/i;
54
+ const BORN = [/created/i, /opened/i, /received|registered|reported|requested|raised|booked|logged/i, /ordered|placed|submitted/i, /date$/i];
55
+ /* Columns that hold when something is to happen, not when it did: a schedule's dashboards read "today" and "next". */
56
+ const SCHEDULE = /(^|_)(appointment|appt|scheduled|starts?|begins?|follow_?up|planned|booked_for|check_?in|session|visit)(_|$)|^start_(at|on|date|time)$/i;
57
+ /* Optional by nature: a note may well be blank; every other text column is filled nearly always. */
58
+ const OPTIONAL_TEXT = /(^|_)(notes?|comments?|remarks?|cancel(l?ation)?|middle_name|nickname|suffix|address_?line_?2|line_?2|fax|alt|secondary)(_|$)/i;
59
+ /* Roles in the building that a title is a job title for. */
60
+ const JOBLIKE = /^(doctors?|nurses?|physicians?|clinicians?|providers?|therapists?|teachers?|instructors?|professors?|technicians?|employees?|workers?|associates?|cashiers?|advisors?|managers?|caregivers?|pharmacists?|dentists?)$/i;
61
+ /* A table of things kept: a part, a product — the one place a "Compact filter" is the right name. */
62
+ const PRODUCTISH = /(^|_)(parts?|products?|items?|catalog|merchandise|goods|equipment|assets?|stock|inventory|skus?)$/i;
63
+ const DUE = /^(due|due_on|due_at|due_date|deadline)$|(^|_)(due|scheduled|planned|expected|promised)(_|$)/i;
64
+ const LIFECYCLE = /(^|_)(status|state|stage|phase)$/i;
65
+ /* A lookup's own name, and the columns that make a short list a catalog instead: a code, a count on the shelf. */
66
+ const LOOKUP_NAME = /^(name|title|label)$/i;
67
+ const CATALOG = /(^|_)(sku|code|barcode|upc|serial|serial_number|stock|in_stock|on_hand|inventory|e?mail|phone)$/i;
68
+ /* A lookup's rows by kind: a list of kinds (categories, types) by topic; anything else, an offering by tier, the
69
+ cheapest first, so a price or a duration beside it climbs with it. */
70
+ const SORTS = /(^|_)(categor(y|ies)|types?|kinds?|topics?|groups?|tags?|labels?|departments?|teams?|sources?|channels?|reasons?|priorit(y|ies)|statuses)$/i;
71
+ const TIERS = ['Basic', 'Standard', 'Premium', 'Express', 'Full', 'Deluxe', 'Quick', 'Seasonal', 'Annual', 'Custom', 'Starter', 'Pro'];
72
+ const TIER_PRICES = [29, 49, 89, 129, 189, 249];
73
+ const TIER_MINUTES = [15, 30, 45, 60, 90, 120];
74
+ const local = (name) => name.slice(name.lastIndexOf('.') + 1);
75
+ /** How a column holds a moment, the App's declaration first: `TEXT` named `due_date` is a day when the App says so. */
76
+ function moment(column, types) {
77
+ const declared = types?.[column.name];
78
+ if (declared === 'date')
79
+ return 'date';
80
+ if (declared === 'datetime')
81
+ return 'instant';
82
+ const read = momentColumn(column);
83
+ if (read)
84
+ return read;
85
+ if (columnKind(column.type ?? '') === 'date')
86
+ return /time/i.test(column.type) ? 'instant' : 'date';
87
+ return columnKind(column.type ?? '') === 'text' && /(^|_)date$/i.test(column.name) ? 'date' : undefined;
88
+ }
89
+ function draftedLife(table) {
90
+ const column = table.columns.find((c) => LIFECYCLE.test(c.name) && (c.allowed?.length ?? 0) >= 3);
91
+ const drafted = column && draftMachine(table, column);
92
+ if (!drafted)
93
+ return undefined;
94
+ const stamps = new Map();
95
+ const reasons = new Map();
96
+ for (const state of drafted.states) {
97
+ const own = stateStampColumn(state, table.columns, drafted);
98
+ stamps.set(state, own ? [own.name] : []);
99
+ }
100
+ for (const verb of drafted.verbs) {
101
+ stamps.set(verb.to, [...new Set([...(stamps.get(verb.to) ?? []), ...verb.stamps])]);
102
+ if (verb.reason)
103
+ reasons.set(verb.to, verb.reason);
104
+ }
105
+ return {
106
+ column: drafted.column,
107
+ ...(drafted.since ? { since: drafted.since } : {}),
108
+ path: drafted.path,
109
+ holds: drafted.holds,
110
+ exits: drafted.exits,
111
+ stamps,
112
+ reasons,
113
+ };
114
+ }
115
+ function referencesOf(schema, table) {
116
+ const refs = new Map();
117
+ for (const fk of schema.foreignKeys) {
118
+ if (fk.from.table !== table.id || fk.from.columns.length !== 1)
119
+ continue;
120
+ const column = table.columns.find((c) => c.name === fk.from.columns[0]);
121
+ if (column)
122
+ refs.set(column.name, { table: fk.to.table, column: fk.to.columns[0], nullable: column.nullable });
123
+ }
124
+ return refs;
125
+ }
126
+ /** Parents first. A reference that would close a loop is left empty, which is only possible where it may be. */
127
+ function ordered(schema, tables) {
128
+ const ids = new Set(tables.map((table) => table.id));
129
+ const done = new Set();
130
+ const out = [];
131
+ const pending = [...tables];
132
+ while (pending.length) {
133
+ let progressed = false;
134
+ for (const table of [...pending]) {
135
+ const refs = referencesOf(schema, table);
136
+ const waiting = [...refs.values()].filter((ref) => ref.table !== table.id && ids.has(ref.table) && !done.has(ref.table));
137
+ if (waiting.length)
138
+ continue;
139
+ const deferred = new Set([...refs].filter(([, ref]) => ref.table === table.id).map(([column]) => column));
140
+ out.push({ table, deferred });
141
+ done.add(table.id);
142
+ pending.splice(pending.indexOf(table), 1);
143
+ progressed = true;
144
+ }
145
+ if (progressed)
146
+ continue;
147
+ /* A loop: break it at the first table whose waiting references may all be empty. */
148
+ const breakable = pending.find((table) => [...referencesOf(schema, table).values()].every((ref) => ref.nullable || done.has(ref.table) || !ids.has(ref.table)));
149
+ if (!breakable)
150
+ throw new SeedRefusal(`${pending.map((table) => table.name).join(', ')} reference each other with required columns, so no one of them can be filled first.`);
151
+ const deferred = new Set([...referencesOf(schema, breakable)]
152
+ .filter(([, ref]) => ref.table === breakable.id || !done.has(ref.table))
153
+ .map(([column]) => column));
154
+ out.push({ table: breakable, deferred });
155
+ done.add(breakable.id);
156
+ pending.splice(pending.indexOf(breakable), 1);
157
+ }
158
+ return out;
159
+ }
160
+ /* ---------- making a row ---------- */
161
+ const slug = (text) => text
162
+ .toLowerCase()
163
+ .replace(/[^a-z0-9]+/g, '-')
164
+ .replace(/^-|-$/g, '');
165
+ const headWord = (table) => {
166
+ const word = local(table.name).replace(/_/g, ' ').replace(/ies$/, 'y').replace(/s$/, '');
167
+ return word.charAt(0).toUpperCase() + word.slice(1);
168
+ };
169
+ const initials = (table) => local(table.name)
170
+ .split('_')
171
+ .map((part) => part.charAt(0))
172
+ .join('')
173
+ .toUpperCase()
174
+ .slice(0, 3) || 'R';
175
+ function lifeOfRow(dice, life, today) {
176
+ const back = (days) => new Date(today.getTime() - days * DAY - dice.int(30, 8 * 60) * 60_000);
177
+ if (!life) {
178
+ const roll = dice.next();
179
+ const days = roll < 0.25 ? dice.int(0, 6) : roll < 0.6 ? dice.int(7, 29) : dice.int(30, 89);
180
+ return { born: back(days), entered: [], open: true };
181
+ }
182
+ const { path } = life;
183
+ const final = path[path.length - 1];
184
+ const open = path.slice(0, -1);
185
+ const holds = [...life.holds.keys()];
186
+ const roll = dice.next();
187
+ let visited;
188
+ if (life.exits.length && roll < 0.1) {
189
+ visited = [...path.slice(0, dice.int(1, Math.max(1, path.length - 1))), dice.pick(life.exits)];
190
+ }
191
+ else if (roll < 0.45 || !open.length) {
192
+ visited = path;
193
+ }
194
+ else if (holds.length && dice.chance(0.12)) {
195
+ const hold = dice.pick(holds);
196
+ visited = [...path.slice(0, path.indexOf(life.holds.get(hold)) + 1), hold];
197
+ }
198
+ else {
199
+ /* Earlier states hold more of the open work: it arrives faster than it finishes. */
200
+ const at = dice.weighted(open.map((_, i) => i), (i) => open.length - i + 1);
201
+ visited = path.slice(0, at + 1);
202
+ }
203
+ const state = visited[visited.length - 1];
204
+ const isOpen = state !== final && !life.exits.includes(state);
205
+ /* Open work is recent; finished work is spread over the quarter. */
206
+ const age = isOpen ? dice.int(0, 20) : dice.int(Math.max(3, visited.length * 2), 89);
207
+ const born = back(age);
208
+ const span = today.getTime() - born.getTime();
209
+ const entered = [{ state: visited[0], at: born }];
210
+ let at = born.getTime();
211
+ for (let i = 1; i < visited.length; i++) {
212
+ const room = (today.getTime() - at) / (visited.length - i + 1);
213
+ at = Math.min(at + Math.max(30 * 60_000, dice.next() * room), born.getTime() + span - 60_000);
214
+ entered.push({ state: visited[i], at: new Date(at) });
215
+ }
216
+ return { born, entered, state, open: isOpen };
217
+ }
218
+ /** Values already taken, per unique column (and per unique pair), so none repeats. */
219
+ class Taken {
220
+ sets = new Map();
221
+ has(key, value) {
222
+ return this.sets.get(key)?.has(String(value)) ?? false;
223
+ }
224
+ add(key, value) {
225
+ if (!this.sets.has(key))
226
+ this.sets.set(key, new Set());
227
+ this.sets.get(key).add(String(value));
228
+ }
229
+ }
230
+ function textFor(dice, plan, column, person, n, personLike, companyLike) {
231
+ const name = column.name.toLowerCase();
232
+ const table = plan.table;
233
+ if (/(^|_)e?mail(_address)?$/.test(name))
234
+ return companyLike && !personLike
235
+ ? `hello@${slug(person.company)}.example.com`
236
+ : `${slug(person.first)}.${slug(person.last)}@example.com`;
237
+ if (/^(first_name|firstname|given_name|forename)$/.test(name))
238
+ return person.first;
239
+ if (/^(last_name|lastname|surname|family_name)$/.test(name))
240
+ return person.last;
241
+ if (/(^|_)(phone|mobile|cell|tel|telephone|fax)(_number)?$/.test(name))
242
+ return `(${dice.pick(['206', '212', '303', '312', '404', '415', '503', '617'])}) 555-01${two(dice.int(0, 99))}`;
243
+ if (/(^|_)(company|organi[sz]ation|employer|business)(_name)?$/.test(name))
244
+ return person.company;
245
+ if (/^(name|full_name|display_name|contact_name|contact|customer_name|owner_name)$/.test(name)) {
246
+ if (personLike || /contact|customer|owner|full|display/.test(name))
247
+ return `${person.first} ${person.last}`;
248
+ if (companyLike)
249
+ return person.company;
250
+ const pool = L.entityNames(plan.domain, table.name);
251
+ if (pool)
252
+ return pool[n % pool.length] + (n >= pool.length ? ` ${Math.floor(n / pool.length) + 1}` : '');
253
+ if (PRODUCTISH.test(local(table.name)))
254
+ return `${dice.pick(W.THING_ADJ)} ${dice.pick(W.THING)}`;
255
+ return `${headWord(table)} ${n + 1}`;
256
+ }
257
+ const meaning = L.meaningOf(name, table.name, plan.job);
258
+ if (meaning === 'reason') {
259
+ /* Without a machine to say it, a reason on a visit or a request is the reason for it. */
260
+ const event = /appointment|visit|encounter|consult|booking|ticket|request|inquir/i.test(local(table.name));
261
+ return dice.pick(L.wordsFor(plan.domain, event ? 'subject' : 'reason'));
262
+ }
263
+ if (meaning)
264
+ return dice.pick(L.wordsFor(plan.domain, meaning));
265
+ if (/(^|_)city$/.test(name))
266
+ return dice.pick(W.CITIES);
267
+ if (/(^|_)(state|province|region)$/.test(name))
268
+ return dice.pick(W.STATES);
269
+ if (/(^|_)country(_code)?$/.test(name))
270
+ return name.endsWith('code') ? 'US' : 'United States';
271
+ if (/(^|_)(zip|zip_code|postal_code|postcode)$/.test(name))
272
+ return String(dice.int(10000, 99899));
273
+ if (/(^|_)(address|street|address_line_?1|line1)$/.test(name))
274
+ return `${dice.int(10, 9899)} ${dice.pick(W.STREETS)}`;
275
+ if (/(^|_)(make|brand|manufacturer)$/.test(name))
276
+ return dice.pick(W.MAKES);
277
+ if (/(^|_)model$/.test(name))
278
+ return `${dice.pick(W.MODELS)} ${dice.int(1, 9)}`;
279
+ if (/(^|_)colou?r$/.test(name))
280
+ return dice.pick(W.COLORS);
281
+ if (/(^|_)(url|website|homepage|link)$/.test(name))
282
+ return `https://example.com/${slug(local(table.name))}/${n + 1}`;
283
+ if (/(^|_)(sku|code|serial|serial_number|number|no|ref|reference|slug|key|tag)$/.test(name)) {
284
+ const prefix = /sku/.test(name) ? 'SKU' : /serial/.test(name) ? 'SN' : initials(table);
285
+ return name === 'slug' ? `${slug(headWord(table))}-${n + 1}` : `${prefix}-${String(1000 + n * 7 + dice.int(0, 6)).padStart(4, '0')}`;
286
+ }
287
+ if (/(^|_)team$/.test(name))
288
+ return dice.pick(L.wordsFor(plan.domain, 'department'));
289
+ if (/(^|_)(uuid|guid)$/.test(name) || /uuid/i.test(column.type))
290
+ return uuid(dice);
291
+ return `${headWord(table)} ${n + 1}`;
292
+ }
293
+ /**
294
+ * A lookup row's name, the n-th of its list: a topic for a list of kinds; a tier of what it offers ("Basic
295
+ * service") where the list is priced or timed; undefined otherwise, for the usual words.
296
+ */
297
+ function lookupName(table, n, domain) {
298
+ const list = L.lookupList(domain, table.name) ??
299
+ (table.columns.some((c) => lookupNumber(c, 0) !== undefined) ? L.entityNames(domain, table.name) : undefined);
300
+ if (list)
301
+ return list[n % list.length] + (n >= list.length ? ` ${Math.floor(n / list.length) + 1}` : '');
302
+ if (SORTS.test(local(table.name)))
303
+ return `${headWord(table)} ${n + 1}`;
304
+ if (!table.columns.some((column) => lookupNumber(column, 0) !== undefined))
305
+ return undefined;
306
+ const tier = TIERS[n];
307
+ return tier ? `${tier} ${headWord(table).toLowerCase()}` : `${headWord(table)} ${n + 1}`;
308
+ }
309
+ /** A lookup row's price or duration, climbing with its tier; undefined for any other number. */
310
+ function lookupNumber(column, n) {
311
+ const step = (list) => list[n % list.length] * (1 + Math.floor(n / list.length));
312
+ if (isMoneyColumn(column))
313
+ return step(TIER_PRICES);
314
+ if (/(^|_)(minutes|mins|duration|duration_minutes)$/i.test(column.name))
315
+ return step(TIER_MINUTES);
316
+ return undefined;
317
+ }
318
+ function uuid(dice) {
319
+ const hex = Array.from({ length: 32 }, () => dice.int(0, 15).toString(16));
320
+ hex[12] = '4';
321
+ hex[16] = ((dice.int(0, 15) & 0x3) | 0x8).toString(16);
322
+ const s = hex.join('');
323
+ return `${s.slice(0, 8)}-${s.slice(8, 12)}-${s.slice(12, 16)}-${s.slice(16, 20)}-${s.slice(20)}`;
324
+ }
325
+ function numberFor(dice, column, line, minor = false) {
326
+ const dollars = amountFor(dice, column, line, minor);
327
+ return minor ? Math.round(dollars * 100) : dollars;
328
+ }
329
+ function amountFor(dice, column, line, minor) {
330
+ const name = column.name.toLowerCase();
331
+ /* Minor units are drawn as dollars and counted in cents after, so the dollars are never whole-number-limited. */
332
+ const whole = !minor && /int|serial/i.test(column.type) && !/point|numeric|decimal/i.test(column.type);
333
+ const cents = (lo, hi) => (whole ? dice.int(lo, hi) : dice.int(lo * 100, hi * 100) / 100);
334
+ if (isMoneyColumn(column) || minor) {
335
+ if (/(unit_)?price|cost|rate$/.test(name))
336
+ return whole ? dice.int(5, 400) : dice.int(5, 400) - 0.01 * dice.pick([1, 5, 50, 100]);
337
+ if (/labou?r|fee|charge|deposit|shipping|tax/.test(name))
338
+ return cents(20, 400);
339
+ return cents(40, 2500);
340
+ }
341
+ if (/(^|_)(quantity|qty|units|count)$/.test(name))
342
+ return line ? dice.int(1, 4) : dice.int(1, 20);
343
+ if (/(^|_)(stock|on_hand|in_stock|quantity_on_hand|qty_on_hand|inventory)$/.test(name))
344
+ return dice.chance(0.1) ? 0 : dice.int(1, 120);
345
+ if (/(^|_)(rating|stars|score)$/.test(name))
346
+ return dice.int(1, 5);
347
+ if (/(percent|pct|discount|rate)$/.test(name))
348
+ return dice.int(0, 30);
349
+ if (/(^|_)year$/.test(name))
350
+ return dice.int(2012, 2025);
351
+ if (/(^|_)age$/.test(name))
352
+ return dice.int(18, 80);
353
+ if (/(^|_)(position|sort|sort_order|rank|priority)$/.test(name))
354
+ return dice.int(1, 10);
355
+ return whole ? dice.int(1, 100) : dice.int(100, 10000) / 100;
356
+ }
357
+ /* ---------- the run ---------- */
358
+ /** Fill the database. Throws SeedRefusal before writing when a table already holds rows and `append` is not set. */
359
+ export async function seedDatabase(adapter, schema, opts) {
360
+ if (!adapter.transaction)
361
+ throw new SeedRefusal('this connection cannot write, so there is nowhere to put rows.');
362
+ const dice = new Dice(opts.seed);
363
+ const now = opts.today ?? new Date();
364
+ const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
365
+ const resourceOf = (table) => opts.resources?.[table.name] ?? opts.resources?.[local(table.name)] ?? opts.resources?.[table.id];
366
+ /* The App's tables, and the parents a required reference of theirs needs; without an App, every table. */
367
+ const candidates = schema.tables.filter((table) => !table.isView && !table.union && table.insertable !== false && !OWN.test(local(table.name)));
368
+ let chosen = opts.resources ? candidates.filter((table) => resourceOf(table)) : candidates;
369
+ for (let grew = true; grew;) {
370
+ grew = false;
371
+ for (const table of [...chosen])
372
+ for (const ref of referencesOf(schema, table).values()) {
373
+ const parent = candidates.find((t) => t.id === ref.table);
374
+ if (!ref.nullable && parent && !chosen.includes(parent)) {
375
+ chosen = [...chosen, parent];
376
+ grew = true;
377
+ }
378
+ }
379
+ }
380
+ if (!chosen.length)
381
+ throw new SeedRefusal('there are no tables to fill.');
382
+ const domain = L.detectDomain(chosen.map((table) => table.name), chosen.flatMap((table) => table.columns.map((c) => c.name)));
383
+ const sizes = new Map();
384
+ const lookups = new Set();
385
+ const plans = ordered(schema, chosen).map(({ table, deferred }) => {
386
+ const resource = resourceOf(table);
387
+ const life = resource?.life ? resource.life(table) : opts.resources ? undefined : draftedLife(table);
388
+ const refs = new Map();
389
+ for (const [column, ref] of referencesOf(schema, table))
390
+ if (!deferred.has(column) && chosen.some((t) => t.id === ref.table))
391
+ refs.set(column, ref);
392
+ const staff = (opts.people && local(opts.people.table) === local(table.name)) ||
393
+ (STAFF.test(local(table.name)) && table.columns.some((c) => /e?mail/i.test(c.name)));
394
+ const nonKey = table.columns.filter((c) => !c.primaryKey && !refs.has(c.name));
395
+ /* A lookup is a short list other tables pick from and that points at nothing: a name and a value or two (a
396
+ service's price and minutes). Filled like a main table, a shop had 40 services named "Bright widget". One
397
+ that is kept in stock or by a code — parts, a catalog — or that holds people is a main table still. */
398
+ const referenced = schema.foreignKeys.some((fk) => fk.to.table === table.id);
399
+ const listed = L.lookupList(domain, table.name) !== undefined;
400
+ const lookup = !staff &&
401
+ referenced &&
402
+ ((listed && nonKey.length <= 8 && !PERSON.test(local(table.name))) ||
403
+ (!refs.size &&
404
+ (nonKey.length <= 2 ||
405
+ (nonKey.length <= 4 &&
406
+ !PERSON.test(local(table.name)) &&
407
+ !COMPANY.test(local(table.name)) &&
408
+ nonKey.some((c) => LOOKUP_NAME.test(c.name)) &&
409
+ !nonKey.some((c) => CATALOG.test(c.name))))));
410
+ const line = refs.size >= 2 && table.columns.some((c) => /(^|_)(quantity|qty|units)$/i.test(c.name));
411
+ const rows = staff
412
+ ? Math.min(opts.rows, Math.max(4, Math.round(opts.rows / 5)))
413
+ : lookup
414
+ ? Math.min(opts.rows, listed || SORTS.test(local(table.name)) ? 8 : nonKey.length <= 2 ? 8 : 6)
415
+ : line
416
+ ? Math.round(opts.rows * 2.5)
417
+ : opts.rows;
418
+ /* Children outnumber the parents they hang from, or the lightest parents could not each have one. */
419
+ const parentRows = Math.max(0, ...[...refs.values()].map((ref) => (sizes.get(ref.table) ?? 0) * (lookups.has(ref.table) ? 0 : 1)));
420
+ const grown = !lookup && !staff && parentRows ? Math.min(opts.rows * 3, Math.max(rows, Math.ceil(parentRows * 1.5))) : rows;
421
+ sizes.set(table.id, grown);
422
+ if (lookup)
423
+ lookups.add(table.id);
424
+ const minor = new Set(resource?.minor ?? []);
425
+ const job = JOBLIKE.test(local(table.name)) || STAFF.test(local(table.name));
426
+ return { table, resource, ...(life ? { life } : {}), rows: grown, domain, job, minor, refs, deferred, ...(lookup ? { lookup } : {}) };
427
+ });
428
+ const tables = new Map(schema.tables.map((table) => [table.id, table]));
429
+ return adapter.transaction(async (tx) => {
430
+ /* Refused before a row is written: someone's data is not a draft to add to unasked. */
431
+ const counts = new Map();
432
+ for (const plan of plans)
433
+ counts.set(plan.table.id, await tx.count(plan.table.id));
434
+ const holding = plans.filter((plan) => counts.get(plan.table.id) > 0);
435
+ if (holding.length && !opts.append)
436
+ throw new SeedRefusal(`${holding.map((plan) => `${plan.table.name} (${counts.get(plan.table.id)} rows)`).join(', ')} already ${holding.length === 1 ? 'holds' : 'hold'} rows. ` +
437
+ 'seed fills an empty database; pass --append to add to it anyway.');
438
+ /* What a reference can point at: the rows made here, and in --append the rows already there — whole rows, so a
439
+ child can agree with its parents (a work order's customer is its bike's owner, a line's price its part's). */
440
+ const rowsOf = new Map();
441
+ const rowList = (table) => {
442
+ if (!rowsOf.has(table))
443
+ rowsOf.set(table, []);
444
+ return rowsOf.get(table);
445
+ };
446
+ const taken = new Taken();
447
+ for (const plan of plans) {
448
+ if (!counts.get(plan.table.id))
449
+ continue;
450
+ const existing = await readAll(tx, plan.table.id, plan.table.columns.map((c) => c.name));
451
+ rowList(plan.table.id).push(...existing);
452
+ for (const row of existing)
453
+ for (const column of plan.table.unique ?? [])
454
+ taken.add(`${plan.table.id}.${column}`, row[column]);
455
+ }
456
+ const report = { tables: [], signIn: [] };
457
+ for (const plan of plans) {
458
+ const { table } = plan;
459
+ const types = plan.resource?.types;
460
+ const personLike = PERSON.test(local(table.name)) ||
461
+ STAFF.test(local(table.name)) ||
462
+ JOBLIKE.test(local(table.name)) ||
463
+ table.columns.some((c) => /^(first_name|last_name)$/i.test(c.name));
464
+ /* A person is named once in a table when there are names enough to go round. */
465
+ const usedNames = new Set();
466
+ const companyLike = COMPANY.test(local(table.name));
467
+ const line = plan.refs.size >= 2 && table.columns.some((c) => /(^|_)(quantity|qty|units)$/i.test(c.name));
468
+ const bornColumn = (() => {
469
+ const dated = table.columns.filter((c) => moment(c, types) &&
470
+ !DUE.test(c.name) &&
471
+ !SCHEDULE.test(c.name) &&
472
+ !(plan.life && [...plan.life.stamps.values()].flat().includes(c.name)) &&
473
+ c.name !== plan.life?.since);
474
+ for (const want of BORN) {
475
+ const hit = dated.find((c) => want.test(c.name));
476
+ if (hit)
477
+ return hit.name;
478
+ }
479
+ return undefined;
480
+ })();
481
+ const pairs = [...(table.uniquePairs ?? [])];
482
+ const primary = table.columns.filter((c) => c.primaryKey);
483
+ if (primary.length === 2)
484
+ pairs.push([primary[0].name, primary[1].name]);
485
+ const offset = counts.get(table.id) ?? 0;
486
+ let made = 0;
487
+ const ordersOf = new Map();
488
+ for (let n = offset; made < plan.rows && n < offset + plan.rows * 3; n++) {
489
+ const person = {
490
+ ...(() => {
491
+ let first = dice.pick(W.FIRST);
492
+ let last = dice.pick(W.LAST);
493
+ for (let tries = 0; personLike && usedNames.has(`${first} ${last}`) && tries < 40; tries++) {
494
+ first = dice.pick(W.FIRST);
495
+ last = dice.pick(W.LAST);
496
+ }
497
+ if (personLike)
498
+ usedNames.add(`${first} ${last}`);
499
+ return { first, last };
500
+ })(),
501
+ company: `${dice.pick(W.COMPANY_FIRST)} ${dice.pick(W.COMPANY_LAST)}${(() => {
502
+ const suffix = dice.pick(W.COMPANY_SUFFIX);
503
+ return suffix ? ` ${suffix}` : '';
504
+ })()}`,
505
+ };
506
+ const life = lifeOfRow(dice, plan.life, today);
507
+ const values = {};
508
+ const stamped = new Map();
509
+ if (plan.life && life.state) {
510
+ values[plan.life.column] = life.state;
511
+ for (const { state, at } of life.entered)
512
+ for (const column of plan.life.stamps.get(state) ?? [])
513
+ stamped.set(column, at);
514
+ if (plan.life.since)
515
+ stamped.set(plan.life.since, life.entered[life.entered.length - 1].at);
516
+ }
517
+ const machineStamps = new Set(plan.life ? [...plan.life.stamps.values()].flat() : []);
518
+ const parents = new Map();
519
+ let ok = true;
520
+ for (const column of table.columns) {
521
+ if (column.name in values || column.writable === false)
522
+ continue;
523
+ if (column.primaryKey && !plan.refs.has(column.name) && (column.identity || column.hasDefault || autoKey(column, primary)))
524
+ continue;
525
+ const ref = plan.refs.get(column.name);
526
+ if (plan.deferred.has(column.name)) {
527
+ if (column.nullable)
528
+ values[column.name] = null;
529
+ continue;
530
+ }
531
+ if (ref) {
532
+ const options = rowList(ref.table).filter((row) => row[ref.column] != null);
533
+ if (!options.length) {
534
+ if (column.nullable)
535
+ values[column.name] = null;
536
+ else
537
+ ok = false;
538
+ continue;
539
+ }
540
+ /* The first rows go one to each parent, so none is childless; the rest favor a few, as a busy doctor or a
541
+ popular product has more than a quiet one. */
542
+ const covering = made < options.length;
543
+ /* An optional reference is sometimes empty: not every work order has its mechanic yet. */
544
+ if (column.nullable && !covering && dice.chance(0.12)) {
545
+ values[column.name] = null;
546
+ continue;
547
+ }
548
+ let order = ordersOf.get(column.name);
549
+ if (!order)
550
+ ordersOf.set(column.name, (order = crowd(dice, options)));
551
+ if (!covering && (table.unique ?? []).includes(column.name)) {
552
+ ok = false;
553
+ continue;
554
+ }
555
+ const parent = covering ? order.rows[made] : order.pick(dice);
556
+ parents.set(column.name, parent);
557
+ values[column.name] = parent[ref.column];
558
+ continue;
559
+ }
560
+ const kind = moment(column, types);
561
+ if (kind) {
562
+ const at = (() => {
563
+ if (stamped.has(column.name))
564
+ return stamped.get(column.name);
565
+ if (machineStamps.has(column.name) || column.name === plan.life?.since)
566
+ return undefined;
567
+ if (column.name === bornColumn)
568
+ return life.born;
569
+ if (SCHEDULE.test(column.name) && !DUE.test(column.name)) {
570
+ if (plan.life && !life.open)
571
+ return new Date(Math.min(life.born.getTime() + dice.int(0, 3) * DAY, today.getTime() - 60_000));
572
+ return scheduledFor(dice, today);
573
+ }
574
+ if (DUE.test(column.name)) {
575
+ if (!plan.life)
576
+ return scheduledFor(dice, today);
577
+ if (!life.open)
578
+ return new Date(life.born.getTime() + dice.int(3, 14) * DAY);
579
+ const roll = dice.next();
580
+ return roll < 0.15
581
+ ? today
582
+ : roll < 0.35
583
+ ? new Date(today.getTime() - dice.int(1, 6) * DAY)
584
+ : new Date(today.getTime() + dice.int(1, 14) * DAY);
585
+ }
586
+ if (/birth|dob/i.test(column.name))
587
+ return new Date(Date.UTC(dice.int(1955, 2004), dice.int(0, 11), dice.int(1, 28)));
588
+ if (/expir|valid_until|renew|ends?_(at|on)/i.test(column.name))
589
+ return new Date(today.getTime() + dice.int(30, 365) * DAY);
590
+ if (column.nullable && !bornColumn && dice.chance(0.2))
591
+ return undefined;
592
+ return new Date(Math.min(life.born.getTime() + dice.int(0, 3) * DAY, today.getTime() - 60_000));
593
+ })();
594
+ if (at === undefined) {
595
+ if (column.nullable)
596
+ values[column.name] = null;
597
+ else
598
+ values[column.name] = written(life.born, kind);
599
+ }
600
+ else
601
+ values[column.name] = written(at, kind);
602
+ continue;
603
+ }
604
+ if (column.allowed?.length) {
605
+ if (column.nullable && dice.chance(0.1))
606
+ values[column.name] = null;
607
+ else
608
+ values[column.name] = dice.weighted(column.allowed, (value) => W.PRIORITY_WEIGHT[value.toLowerCase()] ?? 2);
609
+ continue;
610
+ }
611
+ if (isFlagColumn(column)) {
612
+ const p = /active|enabled|visible|published|available|in_stock/i.test(column.name) ? 0.85 : 0.2;
613
+ const yes = dice.chance(p);
614
+ values[column.name] = columnKind(column.type) === 'boolean' ? yes : yes ? 1 : 0;
615
+ continue;
616
+ }
617
+ const kindOf = columnKind(column.type ?? '');
618
+ if (kindOf === 'number') {
619
+ const tier = plan.lookup ? lookupNumber(column, n) : undefined;
620
+ values[column.name] =
621
+ tier !== undefined
622
+ ? plan.minor.has(column.name)
623
+ ? tier * 100
624
+ : tier
625
+ : numberFor(dice, column, line, plan.minor.has(column.name));
626
+ continue;
627
+ }
628
+ if (kindOf === 'boolean') {
629
+ values[column.name] = dice.chance(0.3);
630
+ continue;
631
+ }
632
+ if (kindOf === 'text') {
633
+ const reasonOf = plan.life ? [...plan.life.reasons].find(([, c]) => c === column.name)?.[0] : undefined;
634
+ if (reasonOf !== undefined || (plan.life && /(^|_)reason$/i.test(column.name))) {
635
+ values[column.name] =
636
+ life.state && (reasonOf === life.state || plan.life?.exits.includes(life.state))
637
+ ? dice.pick(L.wordsFor(plan.domain, 'reason'))
638
+ : column.nullable
639
+ ? null
640
+ : '';
641
+ continue;
642
+ }
643
+ if (/json/i.test(column.type)) {
644
+ values[column.name] = column.nullable ? null : '{}';
645
+ continue;
646
+ }
647
+ /* Text is filled: a first look at a table with every other cell blank says nothing. Only what is blank by
648
+ nature (a note, a second address line) is left so often. */
649
+ if (column.nullable &&
650
+ !/(^|_)(e?mail|name|title|subject|summary|problem|issue)$/i.test(column.name) &&
651
+ dice.chance(OPTIONAL_TEXT.test(column.name) ? 0.4 : 0.04)) {
652
+ values[column.name] = null;
653
+ continue;
654
+ }
655
+ let text = String((plan.lookup && LOOKUP_NAME.test(column.name) ? lookupName(plan.table, n, plan.domain) : undefined) ??
656
+ textFor(dice, plan, column, person, n, personLike, companyLike));
657
+ const max = column.text?.max;
658
+ if (max && text.length > max)
659
+ text = text.slice(0, max);
660
+ values[column.name] = text;
661
+ continue;
662
+ }
663
+ if (!column.nullable && !column.hasDefault)
664
+ ok = false;
665
+ }
666
+ if (!ok)
667
+ break;
668
+ /* Two references that must agree do: when the bike picked has an owner, the work order's customer is that owner. */
669
+ for (const [a, parent] of parents) {
670
+ const via = referencesOf(schema, tables.get(plan.refs.get(a).table));
671
+ for (const [b, refB] of plan.refs) {
672
+ if (b === a || values[b] === null)
673
+ continue;
674
+ const through = [...via].find(([, ref]) => ref.table === refB.table && ref.column === refB.column)?.[0];
675
+ if (through && parent[through] != null)
676
+ values[b] = parent[through];
677
+ }
678
+ }
679
+ /* A line's price is its part's price, as the App's form fills it. */
680
+ for (const column of table.columns) {
681
+ if (!isMoneyColumn(column) || plan.refs.has(column.name) || typeof values[column.name] !== 'number')
682
+ continue;
683
+ const bare = column.name.replace(/^unit_/, '');
684
+ for (const parent of parents.values()) {
685
+ const same = [column.name, bare].find((name) => typeof parent[name] === 'number' ||
686
+ (typeof parent[name] === 'string' && parent[name] !== '' && !Number.isNaN(Number(parent[name]))));
687
+ if (same) {
688
+ values[column.name] = Number(parent[same]);
689
+ break;
690
+ }
691
+ }
692
+ }
693
+ /* Never repeat what must be unique: a second "Ada Lam" gets a number, a second pair is skipped. */
694
+ for (const column of table.unique ?? []) {
695
+ const key = `${table.id}.${column}`;
696
+ const value = values[column];
697
+ if (value === undefined || value === null)
698
+ continue;
699
+ if (!taken.has(key, value))
700
+ continue;
701
+ let changed;
702
+ for (let k = 2; k < 1000 && changed === undefined; k++) {
703
+ const next = typeof value === 'number'
704
+ ? value + k * 1000
705
+ : /@/.test(String(value))
706
+ ? String(value).replace('@', `${k}@`)
707
+ : `${value} ${k}`;
708
+ if (!taken.has(key, next))
709
+ changed = next;
710
+ }
711
+ values[column] = changed ?? null;
712
+ }
713
+ const pairKeys = pairs.map(([a, b]) => `${table.id}.${a}+${b}`);
714
+ if (pairs.some(([a, b], i) => values[a] != null && values[b] != null && taken.has(pairKeys[i], `${values[a]}\u0000${values[b]}`)))
715
+ continue;
716
+ const inserted = await tx.insert({ table: table.id, values });
717
+ const row = { ...values, ...(inserted.row ?? {}), ...inserted.key };
718
+ for (const column of table.unique ?? [])
719
+ if (row[column] != null)
720
+ taken.add(`${table.id}.${column}`, row[column]);
721
+ pairs.forEach(([a, b], i) => taken.add(pairKeys[i], `${row[a]}\u0000${row[b]}`));
722
+ rowList(table.id).push(row);
723
+ if (opts.people && local(opts.people.table) === local(table.name) && report.signIn.length < 3 && row[opts.people.column])
724
+ report.signIn.push(String(row[opts.people.column]));
725
+ made++;
726
+ if (made >= plan.rows)
727
+ break;
728
+ }
729
+ report.tables.push({ table: table.name, rows: made });
730
+ }
731
+ return report;
732
+ });
733
+ }
734
+ function crowd(dice, options) {
735
+ const rows = [...options];
736
+ for (let i = rows.length - 1; i > 0; i--) {
737
+ const j = Math.floor(dice.next() * (i + 1));
738
+ [rows[i], rows[j]] = [rows[j], rows[i]];
739
+ }
740
+ let sum = 0;
741
+ const cumulative = rows.map((_, rank) => (sum += 1 / (rank + 1) ** 0.8));
742
+ return {
743
+ rows,
744
+ pick(d) {
745
+ const at = d.next() * sum;
746
+ let lo = 0;
747
+ let hi = cumulative.length - 1;
748
+ while (lo < hi) {
749
+ const mid = (lo + hi) >> 1;
750
+ if (cumulative[mid] < at)
751
+ lo = mid + 1;
752
+ else
753
+ hi = mid;
754
+ }
755
+ return rows[lo];
756
+ },
757
+ };
758
+ }
759
+ /** When a scheduled thing happens: a little of it today, most of it ahead, a good deal behind within the quarter. */
760
+ function scheduledFor(dice, today) {
761
+ const roll = dice.next();
762
+ const days = roll < 0.15 ? 0 : roll < 0.6 ? dice.int(1, 21) : -dice.int(1, 90);
763
+ return new Date(today.getTime() + days * DAY + dice.int(8, 17) * 3_600_000 + dice.int(0, 3) * 15 * 60_000);
764
+ }
765
+ /* SQLite's INTEGER PRIMARY KEY is the rowid: the database numbers it. */
766
+ const autoKey = (column, primary) => primary.length === 1 && /^integer$/i.test(column.type.trim());
767
+ function written(at, kind) {
768
+ return kind === 'date' ? dayText(at) : kind === 'instant-zoned' ? `${at.toISOString().slice(0, 19)}Z` : wallText(at);
769
+ }
770
+ async function readAll(tx, table, columns) {
771
+ const rows = [];
772
+ for (let offset = 0; offset < 20_000; offset += 1000) {
773
+ const page = await tx.query({ table, columns, limit: 1000, offset });
774
+ rows.push(...page.rows);
775
+ if (page.rows.length < 1000)
776
+ break;
777
+ }
778
+ return rows;
779
+ }