@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,503 @@
1
+ /**
2
+ * Where one request's time went, as a `Server-Timing` header and one log line:
3
+ * opt-in diagnostics for a deployment whose pages are slower than the same
4
+ * code on a laptop, where guessing at the network, the pools or the CPU had
5
+ * stopped converging. `MISTRI_SERVER_TIMING=1` switches it on; off, every
6
+ * entry point below is one boolean check and the work itself. For load tests
7
+ * only: the `proc` entry hands the process's heap, GC and pool use to any
8
+ * requester, so it stays off in production (SECURITY.md) — or is held back
9
+ * behind `MISTRI_SERVER_TIMING_TOKEN`: with that set, `proc` is added only to
10
+ * a request that sends the token as `x-mistri-timing`, and every other entry
11
+ * (each describes that request's own time) goes to anyone.
12
+ *
13
+ * What it counts, per request:
14
+ *
15
+ * - `total`: wall time from the request's arrival to its headers.
16
+ * - `db-<label>`: per database by its role (`app`, `auth`), never its URL —
17
+ * the flights sent (a pipelined batch leaves together and counts once), the
18
+ * time a connection spent awaiting the server, summed over connections, and
19
+ * the most connections awaiting at once. Counted at the leased client's
20
+ * `query`, the one place every statement and batch of either pool crosses.
21
+ * - `pool-<label>`: time spent waiting for a connection, which includes
22
+ * dialling one when the pool had none idle.
23
+ * - `auth`: time resolving the session.
24
+ * - `cpu`: the process's CPU over the request. Approximate: under concurrency
25
+ * it includes whatever else the process ran meanwhile.
26
+ * - `read.<route>`: the planned reads of a composed first page, by route.
27
+ * - `proc`: the process itself, not the request (see below).
28
+ *
29
+ * Nothing in a header or a log line comes from a request, a row or a
30
+ * statement: names are the code's own, values are durations and counts.
31
+ */
32
+ import { AsyncLocalStorage } from 'node:async_hooks';
33
+ import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
34
+ import { constants as perfConstants, monitorEventLoopDelay, performance as perf, PerformanceObserver } from 'node:perf_hooks';
35
+ import { getHeapStatistics } from 'node:v8';
36
+ let on = process.env.MISTRI_SERVER_TIMING?.trim() === '1';
37
+ /** Whether requests are timed: read once from the environment; tests set it. */
38
+ export function setServerTiming(value) {
39
+ on = value;
40
+ if (on)
41
+ startProcessSampler();
42
+ }
43
+ /* Development's own timing (`--dev`): on without MISTRI_SERVER_TIMING, so every response says its cost in a
44
+ Server-Timing header and the terminal gets one line a request that touched the database. It is the request's own
45
+ time and goes to anyone who can reach the dev server; the process entry never does, so the sampler is not started,
46
+ and the JSON log line is replaced by the line a person reads. An operator who set the variable keeps theirs. */
47
+ let developing = false;
48
+ /** Time requests as development does (see above). Nothing changes where the environment already switched timing on. */
49
+ export function setServerTimingDev() {
50
+ if (on)
51
+ return;
52
+ on = true;
53
+ developing = true;
54
+ }
55
+ /**
56
+ * The most database round trips a request should make (a flight: one message sent and awaited, a pipelined batch
57
+ * counted once). The numbers the platform's own tests hold: a read, a command with the reads that settle after it,
58
+ * and the first page of an App, which composes its reads. Past them the dev log says so.
59
+ */
60
+ export const ROUND_TRIP_BUDGETS = { read: 3, command: 6, entry: 16 };
61
+ /** Which budget a request answers to, or none for one that is not the App's (an asset). */
62
+ export function budgetOf(method, route) {
63
+ if (route === '/assets')
64
+ return undefined;
65
+ const read = method === 'GET' || method === 'HEAD';
66
+ if (route === 'page')
67
+ return read ? 'entry' : 'command';
68
+ return read ? 'read' : 'command';
69
+ }
70
+ const PERFORMANCE_PAGE = 'https://mistriwork.dev/docs/performance-by-default/';
71
+ /** What a developer is told of one request: its cost, and a warning line when it made more round trips than its budget. */
72
+ export function costLines(cost) {
73
+ const what = `${cost.method ?? 'GET'} ${cost.route === 'page' ? 'page' : cost.route}`;
74
+ const lines = [
75
+ `mistri: ${what} ${cost.status}: ${cost.roundTrips} round trip${cost.roundTrips === 1 ? '' : 's'}, db ${round(cost.dbMs)} ms, cpu ${round(cost.cpuMs)} ms`,
76
+ ];
77
+ const budget = budgetOf(cost.method, cost.route);
78
+ if (budget && cost.roundTrips > ROUND_TRIP_BUDGETS[budget])
79
+ lines.push(`mistri: warning: ${what} made ${cost.roundTrips} round trips; ${{ read: 'a read', command: 'a command', entry: "an App's first page" }[budget]} should make at most ${ROUND_TRIP_BUDGETS[budget]}. ${PERFORMANCE_PAGE}`);
80
+ return lines;
81
+ }
82
+ let token = process.env.MISTRI_SERVER_TIMING_TOKEN?.trim() || undefined;
83
+ /** The operator token that gates the `proc` entry: read once from the environment; tests set it. */
84
+ export function setServerTimingToken(value) {
85
+ token = value?.trim() || undefined;
86
+ }
87
+ /** Whether `header` is the operator token, compared over digests so neither length nor content shows in the time taken. */
88
+ function holdsToken(header) {
89
+ if (!token || typeof header !== 'string')
90
+ return false;
91
+ const digest = (text) => createHash('sha256').update(text).digest();
92
+ return timingSafeEqual(digest(header), digest(token));
93
+ }
94
+ /* The process entry. A load test needs the process's own state beside each
95
+ request's: which replica answered, whether its heap is climbing after
96
+ collections, whether the loop is saturated. It is sampled on a 5 s unref'd
97
+ timer into one cached string, so a request formats nothing. Only when the
98
+ flag is on does any of it run. */
99
+ const WINDOW_MS = 5_000;
100
+ const instance = randomBytes(4).toString('hex');
101
+ const bootedAt = Date.now();
102
+ const MB = 1024 * 1024;
103
+ const mb = (bytes) => Math.round((bytes / MB) * 10) / 10;
104
+ /** A count the process keeps elsewhere (a pool's leases, open streams), read at each sample; same-named gauges add.
105
+ * Returns its removal: a gauge's reader keeps what it reads alive, so an owner that closes (a pool) takes it out. */
106
+ const gauges = [];
107
+ export function registerGauge(name, read) {
108
+ const gauge = { name, read };
109
+ gauges.push(gauge);
110
+ return () => {
111
+ const at = gauges.indexOf(gauge);
112
+ if (at >= 0)
113
+ gauges.splice(at, 1);
114
+ };
115
+ }
116
+ /** Whether timing is on, for an owner that registers many gauges (a pool per manager) only when it matters. */
117
+ export const serverTimingOn = () => on;
118
+ const gcKinds = [
119
+ [perfConstants.NODE_PERFORMANCE_GC_MINOR, 'minor'],
120
+ [perfConstants.NODE_PERFORMANCE_GC_MAJOR, 'major'],
121
+ [perfConstants.NODE_PERFORMANCE_GC_INCREMENTAL, 'incremental'],
122
+ [perfConstants.NODE_PERFORMANCE_GC_WEAKCB, 'weak'],
123
+ ];
124
+ const gc = {
125
+ minor: { n: 0, ms: 0 },
126
+ major: { n: 0, ms: 0 },
127
+ incremental: { n: 0, ms: 0 },
128
+ weak: { n: 0, ms: 0 },
129
+ };
130
+ let heapAfterMajor = 0;
131
+ let procHeader = '';
132
+ let sampler;
133
+ let resample = () => { };
134
+ /** Take the process sample now instead of at the next tick (tests; the header is otherwise up to 5 s old). */
135
+ export const sampleProcessNow = () => resample();
136
+ function startProcessSampler() {
137
+ if (sampler)
138
+ return;
139
+ if (!token)
140
+ console.error('mistri: warning: MISTRI_SERVER_TIMING=1 puts the process entry (heap, garbage collection, pool use) in every response to any requester. Set MISTRI_SERVER_TIMING_TOKEN to require an x-mistri-timing header for it, or turn timing off in production.');
141
+ try {
142
+ new PerformanceObserver((list) => {
143
+ for (const entry of list.getEntries()) {
144
+ const kind = gcKinds.find(([flag]) => flag === entry.detail?.kind)?.[1];
145
+ if (!kind)
146
+ continue;
147
+ gc[kind].n += 1;
148
+ gc[kind].ms += entry.duration;
149
+ // Delivery is queued, so this reads the heap a moment after the collection: close enough for a floor.
150
+ if (kind === 'major')
151
+ heapAfterMajor = getHeapStatistics().used_heap_size;
152
+ }
153
+ }).observe({ entryTypes: ['gc'] });
154
+ }
155
+ catch {
156
+ // A runtime without gc entries leaves the gc fields at zero.
157
+ }
158
+ const delay = monitorEventLoopDelay({ resolution: 10 });
159
+ delay.enable();
160
+ let elu = perf.eventLoopUtilization();
161
+ let seq = 0;
162
+ const sample = () => {
163
+ const now = perf.eventLoopUtilization();
164
+ const window = perf.eventLoopUtilization(now, elu);
165
+ elu = now;
166
+ const mem = process.memoryUsage();
167
+ const cpu = process.cpuUsage();
168
+ const sums = new Map();
169
+ for (const gauge of gauges) {
170
+ try {
171
+ sums.set(gauge.name, (sums.get(gauge.name) ?? 0) + gauge.read());
172
+ }
173
+ catch {
174
+ // A gauge whose owner is gone reads as nothing.
175
+ }
176
+ }
177
+ const ms = (ns) => Math.round((ns / 1e6) * 10) / 10;
178
+ const kinds = (pick) => gcKinds.map(([, kind]) => pick(gc[kind])).join('/');
179
+ const fields = [
180
+ `i=${instance}`,
181
+ `n=${(seq += 1)}`,
182
+ `up=${Math.round((Date.now() - bootedAt) / 1000)}`,
183
+ `rss=${mb(mem.rss)}`,
184
+ `hu=${mb(mem.heapUsed)}`,
185
+ `ht=${mb(mem.heapTotal)}`,
186
+ `ext=${mb(mem.external)}`,
187
+ `ab=${mb(mem.arrayBuffers)}`,
188
+ `gch=${mb(heapAfterMajor)}`,
189
+ // minor/major/incremental/weak
190
+ `gcn=${kinds((k) => k.n)}`,
191
+ `gcms=${kinds((k) => Math.round(k.ms * 10) / 10)}`,
192
+ `el=${ms(delay.percentile(50))}/${ms(delay.percentile(99))}/${ms(delay.max)}`,
193
+ `elu=${Math.round(window.utilization * 1000) / 1000}`,
194
+ `cpu=${Math.round(cpu.user / 1000)}/${Math.round(cpu.system / 1000)}`,
195
+ ...[...sums].map(([name, value]) => `${name}=${value}`),
196
+ ];
197
+ delay.reset();
198
+ procHeader = `proc;desc="${fields.join(' ')}"`;
199
+ };
200
+ resample = sample;
201
+ sample();
202
+ sampler = setInterval(sample, WINDOW_MS);
203
+ sampler.unref();
204
+ }
205
+ class RequestTiming {
206
+ start = performance.now();
207
+ cpu = process.cpuUsage();
208
+ db = new Map();
209
+ pools = new Map();
210
+ sums = new Map();
211
+ parts = [];
212
+ sent = false;
213
+ dbOf(label) {
214
+ let count = this.db.get(label);
215
+ if (!count)
216
+ this.db.set(label, (count = { flights: 0, waitMs: 0, busy: 0, maxBusy: 0 }));
217
+ return count;
218
+ }
219
+ fields() {
220
+ const cpu = process.cpuUsage(this.cpu);
221
+ return {
222
+ total: round(performance.now() - this.start),
223
+ cpu: round((cpu.user + cpu.system) / 1000),
224
+ ...Object.fromEntries([...this.sums].map(([name, ms]) => [name, round(ms)])),
225
+ db: Object.fromEntries([...this.db].map(([label, c]) => [label, { flights: c.flights, wait: round(c.waitMs), max: c.maxBusy }])),
226
+ pool: Object.fromEntries([...this.pools].map(([label, p]) => [label, { wait: round(p.ms), n: p.n }])),
227
+ ...(this.parts.length ? { parts: this.parts.map(([name, ms]) => [name, round(ms)]) } : {}),
228
+ };
229
+ }
230
+ header(fields, withProc) {
231
+ const metrics = [`total;dur=${fields.total}`, `cpu;dur=${fields.cpu}`];
232
+ if (procHeader && withProc)
233
+ metrics.push(procHeader);
234
+ for (const [name, ms] of this.sums)
235
+ metrics.push(`${name};dur=${round(ms)}`);
236
+ for (const [label, c] of this.db)
237
+ metrics.push(`db-${label};dur=${round(c.waitMs)};desc="flights=${c.flights} max=${c.maxBusy}"`);
238
+ for (const [label, p] of this.pools)
239
+ metrics.push(`pool-${label};dur=${round(p.ms)};desc="n=${p.n}"`);
240
+ for (const [name, ms] of this.parts)
241
+ metrics.push(`${name};dur=${round(ms)}`);
242
+ return metrics.join(', ');
243
+ }
244
+ }
245
+ const round = (ms) => Math.round(ms * 10) / 10;
246
+ const storage = new AsyncLocalStorage();
247
+ /* What a log line may name a request by: an API route as the code spells it,
248
+ with any segment that could be a key replaced; anything else by its kind. */
249
+ function routeOf(url) {
250
+ const path = (url ?? '').split('?')[0];
251
+ if (path.startsWith('/assets/'))
252
+ return '/assets';
253
+ if (!path.startsWith('/api/'))
254
+ return 'page';
255
+ return path
256
+ .split('/')
257
+ .map((part) => (/\d|[^a-z-]/i.test(part) && part !== '' ? ':' : part))
258
+ .join('/');
259
+ }
260
+ /**
261
+ * `listener`, timing each request it is handed — or `listener` itself when
262
+ * timing is off. A request already timed (the tenant server hands its data
263
+ * requests to an inner listener in the same call) is not timed twice.
264
+ */
265
+ export function timedListener(listener) {
266
+ if (!on)
267
+ return listener;
268
+ if (!developing)
269
+ startProcessSampler();
270
+ return ((req, res) => {
271
+ if (storage.getStore())
272
+ return listener(req, res);
273
+ const timing = new RequestTiming();
274
+ /* Node writes every response's headers through writeHead, an implicit
275
+ one included: the last moment the header can still be set. */
276
+ const writeHead = res.writeHead;
277
+ res.writeHead = function (...args) {
278
+ if (!timing.sent) {
279
+ timing.sent = true;
280
+ const fields = timing.fields();
281
+ if (!this.headersSent)
282
+ this.setHeader('Server-Timing', timing.header(fields, !developing && (!token || holdsToken(req.headers['x-mistri-timing']))));
283
+ if (developing) {
284
+ const dbs = [...timing.db.values()];
285
+ const roundTrips = dbs.reduce((sum, c) => sum + c.flights, 0);
286
+ if (roundTrips > 0)
287
+ for (const line of costLines({
288
+ method: req.method,
289
+ route: routeOf(req.url),
290
+ status: args[0],
291
+ roundTrips,
292
+ dbMs: dbs.reduce((sum, c) => sum + c.waitMs, 0),
293
+ cpuMs: Number(fields.cpu),
294
+ }))
295
+ console.error(line);
296
+ }
297
+ else
298
+ process.stderr.write(`${JSON.stringify({ msg: 'server-timing', method: req.method, route: routeOf(req.url), status: args[0], ...fields })}\n`);
299
+ }
300
+ return writeHead.apply(this, args);
301
+ };
302
+ return storage.run(timing, () => listener(req, res));
303
+ });
304
+ }
305
+ /** Time every request `server` answers: its request listeners, each wrapped by timedListener. */
306
+ export function timeRequests(server) {
307
+ if (!on)
308
+ return server;
309
+ const listeners = server.listeners('request');
310
+ server.removeAllListeners('request');
311
+ for (const listener of listeners)
312
+ server.on('request', timedListener(listener));
313
+ return server;
314
+ }
315
+ /** `work`, its duration added to the request's `name` (`auth`). */
316
+ export async function timedSum(name, work) {
317
+ const timing = on ? storage.getStore() : undefined;
318
+ if (!timing)
319
+ return work();
320
+ const start = performance.now();
321
+ try {
322
+ return await work();
323
+ }
324
+ finally {
325
+ timing.sums.set(name, (timing.sums.get(name) ?? 0) + performance.now() - start);
326
+ }
327
+ }
328
+ /** `work`, its duration listed as one part of the request (`read.run`). */
329
+ export async function timedPart(name, work) {
330
+ const timing = on ? storage.getStore() : undefined;
331
+ if (!timing)
332
+ return work();
333
+ const start = performance.now();
334
+ try {
335
+ return await work();
336
+ }
337
+ finally {
338
+ timing.parts.push([name, performance.now() - start]);
339
+ }
340
+ }
341
+ /**
342
+ * `work`, outside whatever request it was asked from: for a process's own work that one request only set off. A
343
+ * timer or promise begun inside a request carries the request's timing to everything it runs, so a live sync pass a
344
+ * save woke had its reads counted as that save's round trips whenever the save was still answering 50 ms later.
345
+ */
346
+ export function untimed(work) {
347
+ return on ? storage.exit(work) : work();
348
+ }
349
+ /** A connection checkout begun: call the result once it is had (or refused). */
350
+ export function poolWait(label) {
351
+ const timing = on ? storage.getStore() : undefined;
352
+ if (!timing)
353
+ return () => { };
354
+ const start = performance.now();
355
+ return () => {
356
+ const pool = timing.pools.get(label) ?? { ms: 0, n: 0 };
357
+ pool.ms += performance.now() - start;
358
+ pool.n += 1;
359
+ timing.pools.set(label, pool);
360
+ };
361
+ }
362
+ /** A pool whose own `query` checks out through `connect` (pg-pool's), its checkouts timed as `label`. */
363
+ export function timePoolCheckouts(pool, label) {
364
+ if (!on)
365
+ return;
366
+ const connect = pool.connect.bind(pool);
367
+ pool.connect = (callback) => {
368
+ const had = poolWait(label);
369
+ if (typeof callback === 'function')
370
+ return connect((...results) => {
371
+ had();
372
+ callback(...results);
373
+ });
374
+ return connect().then((client) => {
375
+ had();
376
+ return client;
377
+ }, (error) => {
378
+ had();
379
+ throw error;
380
+ });
381
+ };
382
+ }
383
+ const timed = new WeakSet();
384
+ /**
385
+ * Count `client`'s round trips to the database `label` names. Its own `query`
386
+ * is wrapped, once, so whatever leases it — a pool's own `query`, a pooler's
387
+ * transaction wrapper, a snapshot — is counted where the statement leaves.
388
+ *
389
+ * A client that pipelines sends a statement asked while others are awaited
390
+ * at once, behind them: those share one flight. One that does not queues it
391
+ * until the one before is answered, so each statement is its own flight.
392
+ */
393
+ export function timeClient(client, label) {
394
+ if (!on || timed.has(client))
395
+ return;
396
+ timed.add(client);
397
+ const own = Object.hasOwn(client, 'query') ? client.query : undefined;
398
+ const proto = Object.getPrototypeOf(client);
399
+ const state = { inFlight: 0, since: 0 };
400
+ const pipelines = () => client.pipeline === true;
401
+ const sent = () => {
402
+ if (state.inFlight === 0) {
403
+ state.timing = storage.getStore();
404
+ state.since = performance.now();
405
+ const count = state.timing?.dbOf(label);
406
+ if (count) {
407
+ count.busy += 1;
408
+ count.maxBusy = Math.max(count.maxBusy, count.busy);
409
+ }
410
+ }
411
+ if (state.inFlight === 0 || !pipelines()) {
412
+ const count = state.timing?.dbOf(label);
413
+ if (count)
414
+ count.flights += 1;
415
+ }
416
+ state.inFlight += 1;
417
+ };
418
+ const answered = () => {
419
+ state.inFlight -= 1;
420
+ if (state.inFlight > 0)
421
+ return;
422
+ const count = state.timing?.dbOf(label);
423
+ if (count) {
424
+ count.busy -= 1;
425
+ count.waitMs += performance.now() - state.since;
426
+ }
427
+ state.timing = undefined;
428
+ };
429
+ client.query = function (...args) {
430
+ sent();
431
+ let once = false;
432
+ const done = () => {
433
+ if (once)
434
+ return;
435
+ once = true;
436
+ answered();
437
+ };
438
+ const last = args.at(-1);
439
+ if (typeof last === 'function')
440
+ args[args.length - 1] = (...results) => {
441
+ done();
442
+ last(...results);
443
+ };
444
+ let pending;
445
+ try {
446
+ pending = (own ?? proto.query).apply(this, args);
447
+ }
448
+ catch (error) {
449
+ done();
450
+ throw error;
451
+ }
452
+ if (typeof last !== 'function') {
453
+ const request = args[0];
454
+ if (pending && typeof pending.then === 'function')
455
+ pending.then(done, done);
456
+ // A submittable (a cursor, a stream) says it is done by its events.
457
+ else if (request && typeof request.once === 'function') {
458
+ request.once('end', done);
459
+ request.once('error', done);
460
+ }
461
+ else
462
+ done();
463
+ }
464
+ return pending;
465
+ };
466
+ }
467
+ const probed = new Set();
468
+ /**
469
+ * Ten `SELECT 1`s, one after another on a connection dialled for them, logged
470
+ * as the round trip from this process to the database `label` names: measured
471
+ * where the server runs, not from the laptop that deployed it. Once per label;
472
+ * `dial` is not called when timing is off or the label was measured.
473
+ */
474
+ export async function probeRoundTrips(label, dial, say = (line) => console.error(line)) {
475
+ if (!on || developing || probed.has(label))
476
+ return;
477
+ probed.add(label);
478
+ let client;
479
+ try {
480
+ client = dial();
481
+ if (!client)
482
+ return;
483
+ client.on?.('error', () => { });
484
+ const dialled = performance.now();
485
+ await client.connect();
486
+ const connectMs = performance.now() - dialled;
487
+ const times = [];
488
+ for (let i = 0; i < 10; i += 1) {
489
+ const start = performance.now();
490
+ await client.query('SELECT 1');
491
+ times.push(performance.now() - start);
492
+ }
493
+ times.sort((a, b) => a - b);
494
+ say(`mistri: server timing — ${label} database round trip min ${round(times[0])} ms, median ${round((times[4] + times[5]) / 2)} ms, ` +
495
+ `max ${round(times[9])} ms over 10 (connect ${round(connectMs)} ms)`);
496
+ }
497
+ catch (error) {
498
+ say(`mistri: server timing — ${label} database round trip not measured: ${error instanceof Error ? error.name : 'failed'}`);
499
+ }
500
+ finally {
501
+ await client?.end().catch(() => { });
502
+ }
503
+ }
@@ -0,0 +1,10 @@
1
+ interface Telemetry {
2
+ flush(): Promise<void>;
3
+ shutdown(): Promise<void>;
4
+ /** Register gauges read at each export (metrics.ts observeGauges); absent when nothing exports. */
5
+ gauges?: (read: Parameters<typeof import('./metrics.js').observeGauges>[0]) => () => void;
6
+ }
7
+ export declare function startTelemetry(env: Readonly<Record<string, string | undefined>>, version: string, say?: (line: string) => void,
8
+ /** Which binary is exporting (`service.name`, and the prefix of what it says). */
9
+ service?: 'tablewalk' | 'mistri'): Promise<Telemetry>;
10
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Switch telemetry on, when the environment asks — and load nothing when it
3
+ * does not. The exporter, its encoders and the driver wrappers are each a
4
+ * dynamic import behind `otlpRequested`, so a start without OTEL_* set has
5
+ * loaded trace.ts (a boolean and an AsyncLocalStorage) and no more.
6
+ */
7
+ import { otlpRequested } from './otlpEnv.js';
8
+ const NONE = { flush: async () => { }, shutdown: async () => { } };
9
+ export async function startTelemetry(env, version, say = (line) => console.error(line),
10
+ /** Which binary is exporting (`service.name`, and the prefix of what it says). */
11
+ service = 'mistri') {
12
+ if (!otlpRequested(env))
13
+ return NONE;
14
+ const [{ startOtlp }, { instrumentDrivers }, { observeGauges }] = await Promise.all([
15
+ import('./otlp.js'),
16
+ import('./drivers.js'),
17
+ import('./metrics.js'),
18
+ ]);
19
+ const exporter = startOtlp(env, version, service);
20
+ instrumentDrivers();
21
+ for (const warning of exporter.warnings)
22
+ say(`${service}: ${warning}`);
23
+ say(`${service}: OpenTelemetry on — ${exporter.signals.join(', ') || 'nothing'} exported over OTLP/HTTP`);
24
+ return Object.assign(exporter, { gauges: observeGauges });
25
+ }
@@ -0,0 +1,16 @@
1
+ interface StatementSummary {
2
+ /** `db.operation.name`: the statement's first keyword, upper-cased, or `OTHER`. */
3
+ operation: string;
4
+ /** `db.collection.name`: the first table it reads or writes, unquoted, when one can be told. */
5
+ table?: string;
6
+ /** `db.query.summary`. */
7
+ summary: string;
8
+ }
9
+ export declare function summarizeStatement(text: string): StatementSummary;
10
+ /**
11
+ * A statement's shape for grouping: the text with literals and numbers
12
+ * blanked, whitespace folded. Two runs of one shape with different
13
+ * parameters are the N+1 pattern the observer flags. Local only.
14
+ */
15
+ export declare function statementShape(text: string): string;
16
+ export {};
@@ -0,0 +1,134 @@
1
+ /**
2
+ * What a statement is, said without anything it carries: its kind and the
3
+ * table it names first. `SELECT loan`, `UPDATE "orders"`, `BEGIN`. That is
4
+ * the OpenTelemetry `db.query.summary`, and it is all a database span
5
+ * exports — never the text, whose literals can be anybody's data, and never
6
+ * a parameter.
7
+ */
8
+ const KINDS = new Set([
9
+ 'SELECT',
10
+ 'INSERT',
11
+ 'UPDATE',
12
+ 'DELETE',
13
+ 'WITH',
14
+ 'BEGIN',
15
+ 'COMMIT',
16
+ 'ROLLBACK',
17
+ 'SAVEPOINT',
18
+ 'RELEASE',
19
+ 'START',
20
+ 'SET',
21
+ 'SHOW',
22
+ 'PRAGMA',
23
+ 'EXPLAIN',
24
+ 'CREATE',
25
+ 'ALTER',
26
+ 'DROP',
27
+ 'ANALYZE',
28
+ 'VACUUM',
29
+ 'LOCK',
30
+ 'CALL',
31
+ 'VALUES',
32
+ 'REPLACE',
33
+ 'MERGE',
34
+ 'TRUNCATE',
35
+ 'LISTEN',
36
+ 'NOTIFY',
37
+ 'UNLISTEN',
38
+ 'DECLARE',
39
+ 'FETCH',
40
+ 'CLOSE',
41
+ 'COPY',
42
+ 'GRANT',
43
+ 'REVOKE',
44
+ 'KILL',
45
+ 'USE',
46
+ 'DO',
47
+ 'RESET',
48
+ 'DISCARD',
49
+ 'PREPARE',
50
+ 'EXECUTE',
51
+ 'DEALLOCATE',
52
+ 'ATTACH',
53
+ 'DETACH',
54
+ 'REINDEX',
55
+ ]);
56
+ /* A quoted identifier or a bare one, optionally schema-qualified. Only the
57
+ last part is kept: a schema name says nothing a table name does not, and a
58
+ tenant's schema is the tenant. */
59
+ const IDENT = String.raw `(?:"(?:[^"]|"")+"|\x60[^\x60]+\x60|\[[^\]]+\]|[A-Za-z_][\w$]*)`;
60
+ const QUALIFIED = new RegExp(`^(${IDENT})(?:\\s*\\.\\s*(${IDENT}))?(?:\\s*\\.\\s*(${IDENT}))?`);
61
+ const unquote = (name) => name.startsWith('"') ? name.slice(1, -1).replace(/""/g, '"') : /^[`[]/.test(name) ? name.slice(1, -1) : name;
62
+ /** Strip comments and string literals, so a keyword inside either is never read as the statement's. */
63
+ function skeleton(text, limit = 4000) {
64
+ return text
65
+ .slice(0, limit)
66
+ .replace(/--[^\n]*/g, ' ')
67
+ .replace(/\/\*[\s\S]*?\*\//g, ' ')
68
+ .replace(/'(?:[^']|'')*'/g, "''");
69
+ }
70
+ function tableAfter(text, keyword) {
71
+ const at = keyword.exec(text);
72
+ if (!at)
73
+ return undefined;
74
+ const rest = text.slice(at.index + at[0].length).trimStart();
75
+ if (rest.startsWith('('))
76
+ return undefined;
77
+ const match = QUALIFIED.exec(rest);
78
+ if (!match)
79
+ return undefined;
80
+ const last = match[3] ?? match[2] ?? match[1];
81
+ const name = unquote(last);
82
+ // A keyword where a name was expected (`FROM (SELECT…)`, `DELETE FROM ONLY`) is no table.
83
+ return /^(select|only|lateral|unnest|json_each|generate_series|values)$/i.test(name) ? undefined : name.slice(0, 128);
84
+ }
85
+ export function summarizeStatement(text) {
86
+ const body = skeleton(text).trim();
87
+ const word = /^[A-Za-z]+/.exec(body)?.[0]?.toUpperCase();
88
+ const operation = word && KINDS.has(word) ? word : 'OTHER';
89
+ let table;
90
+ switch (operation) {
91
+ case 'SELECT':
92
+ case 'WITH':
93
+ case 'DELETE':
94
+ case 'EXPLAIN':
95
+ table = tableAfter(body, /\bFROM\s+/i);
96
+ break;
97
+ case 'INSERT':
98
+ case 'REPLACE':
99
+ table = tableAfter(body, /\bINTO\s+/i);
100
+ break;
101
+ case 'UPDATE':
102
+ table = tableAfter(body, /^UPDATE\s+(?:ONLY\s+)?/i);
103
+ break;
104
+ case 'TRUNCATE':
105
+ table = tableAfter(body, /^TRUNCATE\s+(?:TABLE\s+)?(?:ONLY\s+)?/i);
106
+ break;
107
+ case 'PRAGMA':
108
+ table = /^PRAGMA\s+(?:\w+\.)?(\w+)/i.exec(body)?.[1]?.toLowerCase();
109
+ break;
110
+ default:
111
+ break;
112
+ }
113
+ // A WITH names its CTEs first; the statement it wraps is the one that acts.
114
+ if (operation === 'WITH') {
115
+ const main = /\)\s*(SELECT|INSERT|UPDATE|DELETE)\b[\s\S]*$/i.exec(body);
116
+ if (main) {
117
+ const inner = summarizeStatement(main[0].slice(main[0].indexOf(main[1])));
118
+ return { operation: inner.operation, ...(inner.table ? { table: inner.table } : {}), summary: inner.summary };
119
+ }
120
+ }
121
+ return { operation, ...(table ? { table } : {}), summary: table && operation !== 'PRAGMA' ? `${operation} ${table}` : operation };
122
+ }
123
+ /**
124
+ * A statement's shape for grouping: the text with literals and numbers
125
+ * blanked, whitespace folded. Two runs of one shape with different
126
+ * parameters are the N+1 pattern the observer flags. Local only.
127
+ */
128
+ export function statementShape(text) {
129
+ // Whole, not cut short: a long shared prefix (a row scope's CTEs) would make ten different statements one shape.
130
+ return skeleton(text, 50_000)
131
+ .replace(/\b\d+(\.\d+)?\b/g, '?')
132
+ .replace(/\s+/g, ' ')
133
+ .trim();
134
+ }