@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,700 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { brotliCompressSync, constants as zlib, createBrotliCompress, createGzip, gzipSync } from 'node:zlib';
3
+ import { readFile, readdir } from 'node:fs/promises';
4
+ import { extname, join, normalize, relative, sep } from 'node:path';
5
+ import { SOURCE_CLIENT, devClient } from './devclient.js';
6
+ import { localePreloads, lookPreloads, SURFACE_PAGES, surfaceFor, tenantPreloads } from './clientSurface.js';
7
+ import { FONT_TOKENS, PALETTE_TOKENS, parseThemes, shapeTokens } from '../shared/theme.js';
8
+ import { headingWeight, inheritThemePreset, lookNavRole } from '../shared/themePresets.js';
9
+ import { typeTokens } from '../shared/themeType.js';
10
+ import { fieldEdge } from '../shared/themeColor.js';
11
+ import { recipeAttributes } from '../shared/themeRecipes.js';
12
+ const MIME = {
13
+ '.html': 'text/html; charset=utf-8',
14
+ '.js': 'text/javascript; charset=utf-8',
15
+ '.css': 'text/css; charset=utf-8',
16
+ '.svg': 'image/svg+xml',
17
+ '.json': 'application/json',
18
+ '.map': 'application/json; charset=utf-8',
19
+ '.woff2': 'font/woff2',
20
+ '.txt': 'text/plain; charset=utf-8',
21
+ };
22
+ /**
23
+ * The page's Content-Security-Policy: what the shell — the one page every
24
+ * App, sign-in and the Workbench are drawn in — may load and talk to.
25
+ *
26
+ * The reason is egress. Every endpoint the page can reach is authorized on
27
+ * the server, so a script in the page can do nothing the reader could not;
28
+ * what the server cannot stop is a script sending what the reader sees
29
+ * somewhere else. So scripts come from this origin and from the inline
30
+ * startup scripts in index.html, pinned by their hashes, and the page talks
31
+ * to this origin alone (`connect-src 'self'`, which also admits the dev
32
+ * server's hot-reload socket on the same port). Images may come from any
33
+ * https address, because an App may name a picture by URL in a column (a
34
+ * card's image); nothing else leaves the origin. Styles keep
35
+ * `'unsafe-inline'`: React's style props, the layout preview's copied
36
+ * sheets and the dev server's injected stylesheets are all inline, and a
37
+ * stylesheet cannot send anything the image and connect rules do not let
38
+ * out. The hashes are read from the page being sent — Vite adds its own
39
+ * inline script in development — so a changed startup script cannot drift
40
+ * from its policy.
41
+ */
42
+ export function shellPolicy(html, { fromSource = false, socket } = {}) {
43
+ const hashes = [];
44
+ for (const [, attributes, body] of html.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi)) {
45
+ /* A data block (firstPaint.ts) is never run, so it is never allowed to be. */
46
+ if (/\bsrc\s*=/i.test(attributes) || /\btype\s*=\s*"application\/json"/i.test(attributes))
47
+ continue;
48
+ hashes.push(`'sha256-${createHash('sha256').update(body, 'utf8').digest('base64')}'`);
49
+ }
50
+ return [
51
+ "default-src 'self'",
52
+ ["script-src 'self'", ...hashes].join(' '),
53
+ "style-src 'self' 'unsafe-inline'",
54
+ "img-src 'self' data: blob: https:",
55
+ "font-src 'self' data:",
56
+ /* From source only, the dev client's hot-reload socket where it is not this origin's (devclient.ts devSocket). */
57
+ ["connect-src 'self'", ...(fromSource && socket ? [socket] : [])].join(' '),
58
+ "object-src 'none'",
59
+ /* An attached PDF is previewed in a frame of a Blob the page made from
60
+ bytes it checked begin `%PDF-` (FilePreview.tsx): a document of this
61
+ origin, typed by the page, never a URL a column names. */
62
+ "frame-src 'self' blob:",
63
+ "base-uri 'none'",
64
+ "frame-ancestors 'self'",
65
+ /* From source only: Vite's client, when its hot-reload socket drops,
66
+ waits for the server in a shared worker it makes from a blob. The
67
+ built client has no such worker and is not offered one. */
68
+ ...(fromSource ? ["worker-src 'self' blob:"] : []),
69
+ ].join('; ');
70
+ }
71
+ /** The egress of the Apps a server serves, from their `ui`, whether each serves components, and the origin of the
72
+ human check widget its public forms draw (the App framework's commands/challenges.ts), if any. */
73
+ export function shellEgress(apps) {
74
+ const connect = [...new Set(apps.flatMap((app) => app.ui.csp?.connect ?? []))].sort();
75
+ const images = [...new Set(apps.flatMap((app) => app.ui.csp?.images ?? []))].sort();
76
+ const narrowImages = apps.some((app) => app.components);
77
+ const widgets = [...new Set(apps.flatMap((app) => (app.widget ? [new URL(app.widget).origin] : [])))].sort();
78
+ return connect.length || images.length || narrowImages || widgets.length
79
+ ? { connect, images, narrowImages, ...(widgets.length ? { widgets } : {}) }
80
+ : undefined;
81
+ }
82
+ /** The shell's policy with the served Apps' egress in its connect and image sources (shellPolicy writes both directives exactly so). */
83
+ export function withEgress(policy, egress) {
84
+ if (!egress)
85
+ return policy;
86
+ return policy
87
+ .split('; ')
88
+ .map((directive) => {
89
+ const widgets = egress.widgets ?? [];
90
+ if (directive.startsWith("connect-src 'self'"))
91
+ return [directive, ...egress.connect, ...widgets].join(' ');
92
+ if (widgets.length && (directive.startsWith("script-src 'self'") || directive.startsWith("frame-src 'self'")))
93
+ return [directive, ...widgets].join(' ');
94
+ if (directive.startsWith('img-src ') && egress.narrowImages)
95
+ return ["img-src 'self' data: blob:", ...egress.images].join(' ');
96
+ if (directive.startsWith('img-src '))
97
+ return [directive, ...egress.images].join(' ');
98
+ return directive;
99
+ })
100
+ .join('; ');
101
+ }
102
+ /**
103
+ * The shell's policy with who may frame it: `'self'` alone, unless the page
104
+ * was asked for as a frame (`?embed=frame`, http/handler.ts) and a host's
105
+ * origins are listed for it (embed/crossOrigin.ts) — the iframe fallback for
106
+ * a page that is not a React app, or whose own unlayered CSS would reach an
107
+ * embedded shell. Only an origin listed is ever named: everyone else is
108
+ * refused the frame, as before. shellPolicy writes the directive exactly so.
109
+ */
110
+ function withFrameAncestors(policy, origins) {
111
+ if (!origins?.length)
112
+ return policy;
113
+ return policy.replace("frame-ancestors 'self'", ["frame-ancestors 'self'", ...origins].join(' '));
114
+ }
115
+ /** A page's whole policy: its own, the served Apps' egress, and who may frame it. */
116
+ const pagePolicy = (policy, shell) => shell?.unframed
117
+ ? withEgress(policy, shell.egress).replace("frame-ancestors 'self'", "frame-ancestors 'none'")
118
+ : withFrameAncestors(withEgress(policy, shell?.egress), shell?.frameAncestors);
119
+ const escapeHtml = (text) => text.replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]);
120
+ /** Whether a page's head changes its bytes: anything but the egress, which is only its policy. */
121
+ const writesHead = (head) => Boolean(head?.title ||
122
+ head?.canonical ||
123
+ head?.mount ||
124
+ head?.workbench ||
125
+ head?.observe ||
126
+ head?.density ||
127
+ head?.scheme ||
128
+ head?.grounds ||
129
+ head?.branding ||
130
+ head?.looks?.length ||
131
+ head?.social ||
132
+ head?.pane ||
133
+ head?.pwa);
134
+ /** Generate only registered token names and validated theme values. Row text
135
+ * exists only in escaped JSON; it can never close a style/script element. */
136
+ function brandingHead(html, presentation) {
137
+ const theme = parseThemes([presentation.value.theme], 'Request branding')[0];
138
+ const declarations = (mode) => {
139
+ const pairs = [];
140
+ for (const [key, token] of Object.entries(PALETTE_TOKENS)) {
141
+ const value = theme[mode][key];
142
+ if (value)
143
+ pairs.push([token, value]);
144
+ }
145
+ // A command form's field edge at rest, as the App's theme writer derives it (appTheme.js).
146
+ const edge = fieldEdge(theme[mode]);
147
+ if (edge)
148
+ pairs.push(['--field-edge', edge]);
149
+ for (const [key, token] of Object.entries(FONT_TOKENS)) {
150
+ const value = theme.fonts?.[key];
151
+ if (value)
152
+ pairs.push([token, value]);
153
+ }
154
+ for (const [token, value] of Object.entries(shapeTokens(theme)))
155
+ pairs.push([token, value]);
156
+ for (const [token, value] of Object.entries(typeTokens(inheritThemePreset(theme).type)))
157
+ pairs.push([token, value]);
158
+ pairs.push(['--heading-weight', String(headingWeight(theme))]);
159
+ return pairs.map(([key, value]) => `${key}:${value}`).join(';');
160
+ };
161
+ const root = ':root[data-record-branding]';
162
+ const css = `${root}{${declarations('light')}}@media(prefers-color-scheme:dark){${root}:not([data-theme="light"]){${declarations('dark')}}}${root}[data-theme="dark"]{${declarations('dark')}}`;
163
+ const json = JSON.stringify(presentation).replace(/[<>&\u2028\u2029]/g, (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
164
+ const block = `<style id="mistri-branding-style">${css}</style><script type="application/json" id="mistri-branding">${json}</script>`;
165
+ /* The recipes are menu values (parseThemes refused anything else), written as attributes the sheets answer. */
166
+ const looks = Object.entries(recipeAttributes(inheritThemePreset(theme), lookNavRole(theme)).attributes)
167
+ .map(([name, value]) => ` ${name}="${escapeHtml(value)}"`)
168
+ .join('');
169
+ let out = html.replace(/<html\b([^>]*)>/i, (_, attributes) => `<html${attributes} data-record-branding data-custom-theme data-visual-theme="${theme.id}" data-theme-style="${theme.base ?? ''}" data-theme-palette="default"${looks}>`);
170
+ out = /<meta charset[^>]*>/i.test(out)
171
+ ? out.replace(/<meta charset[^>]*>/i, (match) => `${match}\n${block}`)
172
+ : /<head>/i.test(out)
173
+ ? out.replace(/<head>/i, (match) => `${match}${block}`)
174
+ : `${block}${out}`;
175
+ return out;
176
+ }
177
+ /**
178
+ * The shell with a page's own head written in. Under a base path the page's
179
+ * own files are said under it (a component's host modules are said under it
180
+ * where the component is served, componentRoutes.ts). An inline script the
181
+ * head adds changes the page, so a caller whose page changed takes its policy
182
+ * from the page it sends (shellPolicy), never the static file's.
183
+ */
184
+ export function withHead(html, head) {
185
+ if (!writesHead(head))
186
+ return html;
187
+ let out = html;
188
+ if (head?.branding)
189
+ out = brandingHead(out, head.branding);
190
+ const base = head.mount?.base;
191
+ if (base) {
192
+ out = out.replace(/(\s(?:src|href)=")\/(?=assets\/)/g, (_, attribute) => `${attribute}${base}/`);
193
+ }
194
+ /* Before any script reads them: index.html's first script keys its startup colours by App and stamps its scheme. */
195
+ const beforeScripts = (meta) => {
196
+ out = /<meta charset[^>]*>/i.test(out)
197
+ ? out.replace(/<meta charset[^>]*>/i, (match) => `${match}\n ${meta}`)
198
+ : /<head>/i.test(out)
199
+ ? out.replace(/<head>/i, (match) => `${match}${meta}`)
200
+ : out.replace(/<title>|<script/i, (match) => `${meta}${match}`);
201
+ };
202
+ if (head.mount)
203
+ beforeScripts(`<meta name="mistri-mount" content="${escapeHtml(head.mount.json)}">`);
204
+ /* Read by the entry before it starts a main (packages/kit/src/client/shellStart.js): the Workbench's, not an App's. */
205
+ if (head.workbench)
206
+ beforeScripts('<meta name="mistri-shell" content="workbench">');
207
+ if (head.scheme)
208
+ beforeScripts(`<meta name="mistri-scheme" content="${escapeHtml(head.scheme)}">`);
209
+ if (head.grounds)
210
+ out = out.replace(/<\/head>/i, () => ` ${groundsMeta(head.grounds)}\n </head>`);
211
+ if (head.observe)
212
+ out = out.replace(/<\/head>/i, () => ` <meta name="mistri-observe" content="${escapeHtml(head.observe)}">\n </head>`);
213
+ if (head.density)
214
+ out = out.replace(/<\/head>/i, () => ` <meta name="mistri-density" content="${escapeHtml(head.density)}">\n </head>`);
215
+ /* An installable App: its manifest, and the script that registers its
216
+ worker once the page has loaded. Both from this origin, so no inline
217
+ script is needed and the page's policy admits them as they stand. */
218
+ if (head.pwa)
219
+ out = out.replace(/<\/head>/i, () => ` <link rel="manifest" href="${escapeHtml(head.pwa.manifest)}">\n <script src="${escapeHtml(head.pwa.register)}" defer></script>\n </head>`);
220
+ if (!head?.title && !head?.canonical)
221
+ return out;
222
+ /* Replaced by a function, never a replacement string: a string's `$&`,
223
+ `` $` `` and `$'` are patterns, and a record's name is anybody's text —
224
+ `$'` in a title would pour the rest of the page into it. */
225
+ const title = head.title && `<title>${escapeHtml(head.title)}</title>`;
226
+ const canonical = head.canonical && ` <link rel="canonical" href="${escapeHtml(head.canonical)}">\n`;
227
+ const social = head.social ? socialMeta(head.social) : '';
228
+ if (title)
229
+ out = out.replace(/<title>[^<]*<\/title>/i, () => title);
230
+ if (canonical || social)
231
+ out = out.replace(/<\/head>/i, () => `${canonical || ''}${social} </head>`);
232
+ return out;
233
+ }
234
+ /**
235
+ * What the browser draws around the page: the form controls and scroll bars in the scheme the theme wears
236
+ * (`color-scheme`; a dark-only theme says dark alone), and the address bar and overscroll in its ground, one
237
+ * `theme-color` for each mode the reader's machine can be in. Plain HTML in the head: nothing for a script to wait on.
238
+ */
239
+ export function groundsMeta(grounds) {
240
+ const colors = [grounds.light, grounds.dark].map(escapeHtml);
241
+ if (grounds.scheme === 'dark-only')
242
+ return `<meta name="color-scheme" content="dark">\n <meta name="theme-color" content="${colors[1]}">`;
243
+ return [
244
+ '<meta name="color-scheme" content="light dark">',
245
+ `<meta name="theme-color" content="${colors[0]}" media="(prefers-color-scheme: light)">`,
246
+ `<meta name="theme-color" content="${colors[1]}" media="(prefers-color-scheme: dark)">`,
247
+ ].join('\n ');
248
+ }
249
+ /** The tags a link preview and a search result read, every value escaped: a record's name and words are anybody's text. */
250
+ function socialMeta(social) {
251
+ const tags = [
252
+ ['name', 'description', social.description],
253
+ ['property', 'og:type', social.type],
254
+ ['property', 'og:site_name', social.site],
255
+ ['property', 'og:title', social.title],
256
+ ['property', 'og:url', social.url],
257
+ ['property', 'og:description', social.description],
258
+ ['property', 'og:image', social.image],
259
+ ['property', 'og:image:alt', social.image ? social.imageAlt || undefined : undefined],
260
+ ['name', 'twitter:card', social.image ? 'summary_large_image' : 'summary'],
261
+ ['name', 'twitter:title', social.title],
262
+ ['name', 'twitter:description', social.description],
263
+ ['name', 'twitter:image', social.image],
264
+ ];
265
+ return tags
266
+ .filter(([, , value]) => value)
267
+ .map(([attribute, key, value]) => ` <meta ${attribute}="${key}" content="${escapeHtml(value)}">\n`)
268
+ .join('');
269
+ }
270
+ /** The tag that opens the content pane, and everything to its close: the place a server-drawn pane goes. */
271
+ const PANE = /<main\b([^>]*\bid="content"[^>]*)>[\s\S]*?<\/main>/i;
272
+ /** The page with its content pane drawn in, and marked with its kind for the client (client serverDrawing.js). */
273
+ function withPane(html, pane) {
274
+ if (!pane)
275
+ return html;
276
+ return html.replace(PANE, (_, attributes) => `<main${attributes} data-ssr="${pane.kind}">${pane.html}</main>`);
277
+ }
278
+ /** The pane, or none: a page is served whole whether or not the server could draw it. */
279
+ async function drawnPane(shell, data) {
280
+ if (!shell?.pane)
281
+ return undefined;
282
+ try {
283
+ return await shell.pane(data?.answers);
284
+ }
285
+ catch {
286
+ return undefined;
287
+ }
288
+ }
289
+ /** The page asking for its look's sheets, its reader's words and a tenant host's flows beside the entry (clientSurface.ts), ahead of the entry's own script. */
290
+ function withLooks(html, shell, files) {
291
+ const assets = [...files];
292
+ const links = lookPreloads(shell?.looks ?? [], assets, shell?.faces) +
293
+ (shell?.appFaces ?? '') +
294
+ localePreloads(shell?.locale, assets) +
295
+ (shell?.tenant && !shell.workbench && surfaceFor(shell.path ?? '') === 'shell' ? tenantPreloads(assets) : '');
296
+ if (!links)
297
+ return html;
298
+ return /<script type="module"/i.test(html)
299
+ ? html.replace(/<script type="module"/i, (match) => `${links.trimStart()} ${match}`)
300
+ : html.replace(/<\/head>/i, () => `${links} </head>`);
301
+ }
302
+ /** The page with its data block (firstPaint.ts) at the end of its body, where nothing waits on it. */
303
+ function withData(html, data) {
304
+ if (!data)
305
+ return html;
306
+ return /<\/body>/i.test(html) ? html.replace(/<\/body>/i, () => `${data.block}\n </body>`) : `${html}${data.block}`;
307
+ }
308
+ /** The page's data, or none: a page is served whole whether or not its data could be asked. */
309
+ async function pageData(shell, head) {
310
+ if (head || !shell?.data)
311
+ return undefined;
312
+ try {
313
+ return await shell.data();
314
+ }
315
+ catch {
316
+ return undefined;
317
+ }
318
+ }
319
+ /**
320
+ * How a page is kept. The shell alone is everybody's and revalidated; one
321
+ * that may carry answers is one reader's (`Vary: Cookie`) and is not kept at
322
+ * all: who-am-I, the first of them, never is either.
323
+ */
324
+ const PERSONAL = 'private, no-store';
325
+ const pageCache = (data, shell) => (data || shell?.branding?.private ? PERSONAL : 'no-cache');
326
+ /**
327
+ * A page that carries its data, sent as it is made: everything up to the end
328
+ * of its body at once — the entry and its preloads start downloading — and
329
+ * the data block once it is asked, then the rest. The entry is a module,
330
+ * which runs once the page is parsed, so it reads the block however late it
331
+ * comes; the browser's wait for the answers overlaps its wait for the script.
332
+ * Compressed as it streams, flushed at the break. No ETag: the bytes are not
333
+ * known when the headers go, and the page is not kept anyway.
334
+ */
335
+ async function streamPage(res, text, headers, encoding, data, shell) {
336
+ /* A page whose pane the server may draw is sent up to the pane at once —
337
+ its head, its preloads, its chrome — and the rest once the answers are
338
+ in and the pane is drawn from them. */
339
+ const at = shell?.pane ? text.search(PANE) : text.search(/<\/body>/i);
340
+ const [before, after] = at < 0 ? [text, ''] : [text.slice(0, at), text.slice(at)];
341
+ const coder = encoding === 'br'
342
+ ? createBrotliCompress({ params: { [zlib.BROTLI_PARAM_QUALITY]: 4, [zlib.BROTLI_PARAM_MODE]: zlib.BROTLI_MODE_TEXT } })
343
+ : encoding === 'gzip'
344
+ ? createGzip({ level: 6 })
345
+ : undefined;
346
+ const finished = new Promise((resolve) => {
347
+ const done = () => {
348
+ res.off('finish', done);
349
+ res.off('close', done);
350
+ resolve();
351
+ };
352
+ res.once('finish', done);
353
+ res.once('close', done);
354
+ });
355
+ res.writeHead(200, { ...headers, ...(encoding ? { 'content-encoding': encoding } : {}) });
356
+ const out = coder ?? res;
357
+ if (coder) {
358
+ coder.pipe(res);
359
+ coder.on('error', () => res.destroy());
360
+ }
361
+ out.write(before);
362
+ coder?.flush();
363
+ let block;
364
+ try {
365
+ block = res.destroyed ? undefined : await data();
366
+ }
367
+ catch {
368
+ block = undefined;
369
+ }
370
+ if (res.destroyed) {
371
+ coder?.destroy();
372
+ return;
373
+ }
374
+ if (shell?.pane && at >= 0) {
375
+ const pane = await drawnPane(shell, block);
376
+ if (res.destroyed) {
377
+ coder?.destroy();
378
+ return;
379
+ }
380
+ out.end(withData(withPane(after, pane), block));
381
+ await finished;
382
+ return;
383
+ }
384
+ out.end(`${block ? `${block.block}\n ` : ''}${after}`);
385
+ await finished;
386
+ }
387
+ export async function serveClient(files, req, res, shell) {
388
+ const head = req.method === 'HEAD';
389
+ if (req.method !== 'GET' && !head) {
390
+ res.writeHead(405, { allow: 'GET, HEAD' }).end('Method not allowed');
391
+ return;
392
+ }
393
+ if (res.destroyed || res.writableEnded)
394
+ return;
395
+ if (SOURCE_CLIENT) {
396
+ const base = shell?.mount?.base ?? '';
397
+ const vite = await devClient(files, base);
398
+ if (res.destroyed || res.writableEnded)
399
+ return;
400
+ // App routing already removed its base. Vite's native base middleware
401
+ // expects the external address and removes it itself when serving files.
402
+ const sourceURL = `${base}${req.url ?? '/'}`;
403
+ req.url = sourceURL;
404
+ // Middleware owns module/style responses; unmatched paths render the SPA.
405
+ // Hold the request through completion, including an in-flight HTML fallback
406
+ // after disconnect, so a retiring host does not release its owner early.
407
+ await new Promise((resolve, reject) => {
408
+ let fallback;
409
+ const clean = () => {
410
+ res.off('finish', complete);
411
+ res.off('close', complete);
412
+ res.off('error', fail);
413
+ };
414
+ const done = () => {
415
+ clean();
416
+ resolve();
417
+ };
418
+ const fail = (error) => {
419
+ clean();
420
+ reject(error);
421
+ };
422
+ const complete = () => {
423
+ if (fallback)
424
+ void fallback.then(done, fail);
425
+ else
426
+ done();
427
+ };
428
+ res.once('finish', complete);
429
+ res.once('close', complete);
430
+ res.once('error', fail);
431
+ try {
432
+ vite.middlewares(req, res, (error) => {
433
+ fallback = Promise.resolve().then(async () => {
434
+ if (res.destroyed || res.writableEnded)
435
+ return;
436
+ if (error) {
437
+ res.writeHead(500).end(head ? undefined : String(error));
438
+ return;
439
+ }
440
+ try {
441
+ const raw = await readFile(join(files.source, 'index.html'), 'utf8');
442
+ const data = await pageData(shell, head);
443
+ const pane = head ? undefined : await drawnPane(shell, data);
444
+ /* No built files to preload from source; an App theme's own faces are the App's, and are said as in a build. */
445
+ const html = withData(withPane(withHead(withLooks(await vite.transformIndexHtml(sourceURL, raw), shell, []), shell), pane), data);
446
+ if (res.destroyed || res.writableEnded)
447
+ return;
448
+ res.writeHead(200, {
449
+ 'content-type': MIME['.html'],
450
+ 'cache-control': pageCache(data, shell),
451
+ ...(data || shell?.branding?.private ? { vary: 'Cookie' } : {}),
452
+ 'x-content-type-options': 'nosniff',
453
+ 'content-security-policy': pagePolicy(shellPolicy(html, { fromSource: true, socket: vite.socket }), shell),
454
+ });
455
+ res.end(head ? undefined : html);
456
+ }
457
+ catch {
458
+ if (!res.destroyed && !res.writableEnded)
459
+ res.writeHead(404).end(head ? undefined : 'Not found');
460
+ }
461
+ });
462
+ void fallback.then(() => {
463
+ if (res.destroyed || res.writableFinished)
464
+ complete();
465
+ }, fail);
466
+ });
467
+ }
468
+ catch (error) {
469
+ fail(error);
470
+ }
471
+ });
472
+ return;
473
+ }
474
+ await fromBuild(files.built)(req, res, head, shell);
475
+ }
476
+ /** Named for their content (vite.config.ts): a changed file is a new name, never new bytes under an old one. */
477
+ const IMMUTABLE = 'public, max-age=31536000, immutable';
478
+ /** A source map is named after its script, not its own content, so it is asked about each time. */
479
+ const hashed = (rel) => rel.startsWith('assets/') && !rel.endsWith('.map');
480
+ const COMPRESSED = [
481
+ ['.br', 'br'],
482
+ ['.gz', 'gzip'],
483
+ ];
484
+ /** A strong ETag: the hash of the bytes sent, so two servers behind one balancer agree. */
485
+ const strongTag = (data) => `"${createHash('sha256').update(data).digest('base64url').slice(0, 27)}"`;
486
+ /**
487
+ * Every file in the directory, read once and kept. dist does not change
488
+ * while the process runs — a new build is a new install and a restart — so
489
+ * each variant's strong ETag is the hash of its bytes, taken on the first
490
+ * request, and every request after it is a map lookup. The hash is of the
491
+ * content rather than a timestamp so two servers behind one balancer agree.
492
+ */
493
+ async function inventory(dir) {
494
+ const names = (await readdir(dir, { recursive: true, withFileTypes: true }))
495
+ .filter((entry) => entry.isFile())
496
+ .map((entry) => relative(dir, join(entry.parentPath, entry.name)).split(sep).join('/'));
497
+ const present = new Set(names);
498
+ const tag = async (file) => {
499
+ const data = await readFile(file);
500
+ return { size: data.length, etag: strongTag(data) };
501
+ };
502
+ const assets = new Map();
503
+ await Promise.all(names
504
+ .filter((rel) => !COMPRESSED.some(([suffix]) => rel.endsWith(suffix) && present.has(rel.slice(0, -suffix.length))))
505
+ .map(async (rel) => {
506
+ const file = join(dir, rel);
507
+ const variants = [];
508
+ for (const [suffix, encoding] of COMPRESSED) {
509
+ if (present.has(rel + suffix))
510
+ variants.push({ file: file + suffix, encoding, ...(await tag(file + suffix)) });
511
+ }
512
+ variants.push({ file, ...(await tag(file)) });
513
+ /* A page carries its policy, read from the page itself once (shellPolicy). */
514
+ const policy = extname(rel) === '.html' ? shellPolicy(await readFile(file, 'utf8')) : undefined;
515
+ assets.set(rel, {
516
+ type: MIME[extname(rel)] ?? 'application/octet-stream',
517
+ cache: hashed(rel) ? IMMUTABLE : 'no-cache',
518
+ variants,
519
+ ...(policy ? { policy } : {}),
520
+ });
521
+ }));
522
+ return assets;
523
+ }
524
+ /**
525
+ * The codings a request will take (RFC 9110 §12.5.3). A coding named with
526
+ * `q=0` is refused, `*` answers for every coding not named, and a request
527
+ * that names none gets the file as it is. The server's order decides among
528
+ * the acceptable ones — brotli is smaller than gzip for the same text — so
529
+ * only a zero weight counts, not how two nonzero weights compare.
530
+ */
531
+ function acceptable(header) {
532
+ const weights = new Map();
533
+ for (const part of (Array.isArray(header) ? header.join(',') : (header ?? '')).split(',')) {
534
+ const [name = '', ...params] = part.split(';').map((piece) => piece.trim().toLowerCase());
535
+ if (!name)
536
+ continue;
537
+ const q = params.map((param) => /^q\s*=\s*([\d.]+)$/.exec(param)?.[1]).find((value) => value !== undefined);
538
+ weights.set(name, q === undefined ? 1 : Number(q) || 0);
539
+ }
540
+ return (encoding) => (weights.get(encoding) ?? (encoding === 'gzip' ? weights.get('x-gzip') : undefined) ?? weights.get('*') ?? 0) > 0;
541
+ }
542
+ /** A page with its own head, compressed as it is sent: brotli at quality 4 or
543
+ * gzip at 6, as API replies are (http/reply.ts). The shell is a few kilobytes,
544
+ * well under a millisecond either way. */
545
+ function compressPage(page, encoding) {
546
+ return encoding === 'br'
547
+ ? brotliCompressSync(page, {
548
+ params: {
549
+ [zlib.BROTLI_PARAM_QUALITY]: 4,
550
+ [zlib.BROTLI_PARAM_SIZE_HINT]: page.length,
551
+ [zlib.BROTLI_PARAM_MODE]: zlib.BROTLI_MODE_TEXT,
552
+ },
553
+ })
554
+ : gzipSync(page, { level: 6 });
555
+ }
556
+ /** If-None-Match names this representation, by the weak comparison the header is defined with. */
557
+ function unchanged(header, etag) {
558
+ if (!header)
559
+ return false;
560
+ return header.split(',').some((tag) => {
561
+ const t = tag.trim();
562
+ return t === '*' || t.replace(/^W\//, '') === etag;
563
+ });
564
+ }
565
+ /** Serves a built client directory: the one the package ships, or a test's. */
566
+ export function builtClient(dir) {
567
+ const root = dir.endsWith(sep) ? dir : dir + sep;
568
+ let files;
569
+ return async (req, res, head, shell) => {
570
+ const path = new URL(req.url ?? '/', 'http://localhost').pathname;
571
+ // Normalize before joining so .. cannot walk out of the client directory.
572
+ const rel = normalize(path).replace(/^(\.\.[/\\])+/, '');
573
+ const file = join(root, rel);
574
+ if (!file.startsWith(root)) {
575
+ res.writeHead(403).end(head ? undefined : 'Forbidden');
576
+ return;
577
+ }
578
+ let assets;
579
+ try {
580
+ assets = await (files ??= inventory(root));
581
+ }
582
+ catch (error) {
583
+ files = undefined;
584
+ throw error;
585
+ }
586
+ /* Unknown paths are SPA routes, not missing files: the page for the
587
+ surface the address will draw, which preloads that part (clientSurface.ts).
588
+ A build without per-surface pages (a test's) has index.html alone.
589
+ The root is a route like any other, not the file index.html, which is
590
+ an App's shell page: the database browser's landing is at `/`, and its
591
+ page preloads its own main, not the App's chrome. */
592
+ const asset = (path === '/' ? undefined : assets.get(relative(root, file).split(sep).join('/'))) ??
593
+ assets.get(SURFACE_PAGES[shell?.workbench ? 'workbench' : surfaceFor(shell?.path ?? path)]) ??
594
+ assets.get('index.html');
595
+ if (!asset) {
596
+ if (!res.destroyed && !res.writableEnded)
597
+ res.writeHead(404).end(head ? undefined : 'Not found');
598
+ return;
599
+ }
600
+ /* A public page's own head (withHead): the shell's bytes with it written
601
+ in, sent as they are. It names one record, so it is never the shared
602
+ file's ETag and never a cached copy of another page's: its ETag is the
603
+ hash of these bytes, so a revisit is still a 304 until the head — a
604
+ record's name, the App's — or the shell under it changes. Without one
605
+ every public page was downloaded whole on every visit.
606
+ It is compressed as it is sent, as the shared page's copies were at
607
+ build time: the public page is the one a stranger's first visit and
608
+ every link preview fetches, and it went out at its full size while the
609
+ signed-in shell went as brotli. The tag is of the bytes sent, so each
610
+ coding has its own, as the static copies do. */
611
+ const isPage = asset.type === MIME['.html'];
612
+ if (isPage && shell?.data) {
613
+ const plain = asset.variants.find((v) => !v.encoding);
614
+ const text = withHead(withLooks(await readFile(plain.file, 'utf8'), shell, assets.keys()), shell);
615
+ if (res.destroyed || res.writableEnded)
616
+ return;
617
+ const accepts = acceptable(req.headers['accept-encoding']);
618
+ const encoding = asset.variants.some((v) => v.encoding) ? COMPRESSED.map(([, e]) => e).find(accepts) : undefined;
619
+ const headers = {
620
+ 'cache-control': PERSONAL,
621
+ 'x-content-type-options': 'nosniff',
622
+ 'content-type': asset.type,
623
+ vary: asset.variants.length > 1 ? 'Accept-Encoding, Cookie' : 'Cookie',
624
+ ...(asset.policy ? { 'content-security-policy': pagePolicy(shell.mount?.base ? shellPolicy(text) : asset.policy, shell) } : {}),
625
+ };
626
+ if (head) {
627
+ res.writeHead(200, headers).end();
628
+ return;
629
+ }
630
+ await streamPage(res, text, headers, encoding, shell.data, shell);
631
+ return;
632
+ }
633
+ if (isPage && writesHead(shell)) {
634
+ const plain = asset.variants.find((v) => !v.encoding);
635
+ const pane = head ? undefined : await drawnPane(shell, undefined);
636
+ const text = withPane(withHead(withLooks(await readFile(plain.file, 'utf8'), shell, assets.keys()), shell), pane);
637
+ const page = Buffer.from(text, 'utf8');
638
+ if (res.destroyed || res.writableEnded)
639
+ return;
640
+ const accepts = acceptable(req.headers['accept-encoding']);
641
+ const encoding = asset.variants.some((v) => v.encoding) ? COMPRESSED.map(([, e]) => e).find(accepts) : undefined;
642
+ const body = encoding ? compressPage(page, encoding) : page;
643
+ const privately = shell?.branding?.private;
644
+ const headers = {
645
+ 'cache-control': privately ? PERSONAL : 'no-cache',
646
+ ...(!privately ? { etag: strongTag(body) } : {}),
647
+ 'x-content-type-options': 'nosniff',
648
+ ...(asset.policy ? { 'content-security-policy': pagePolicy(shell?.mount?.base ? shellPolicy(text) : asset.policy, shell) } : {}),
649
+ ...(asset.variants.length > 1 || privately
650
+ ? { vary: [asset.variants.length > 1 ? 'Accept-Encoding' : '', privately ? 'Cookie' : ''].filter(Boolean).join(', ') }
651
+ : {}),
652
+ };
653
+ if (!privately && unchanged(req.headers['if-none-match'], headers.etag)) {
654
+ res.writeHead(304, headers).end();
655
+ return;
656
+ }
657
+ res.writeHead(200, {
658
+ ...headers,
659
+ 'content-type': asset.type,
660
+ 'content-length': body.length,
661
+ ...(encoding ? { 'content-encoding': encoding } : {}),
662
+ });
663
+ res.end(head ? undefined : body);
664
+ return;
665
+ }
666
+ const accepts = acceptable(req.headers['accept-encoding']);
667
+ const variant = asset.variants.find((v) => !v.encoding || accepts(v.encoding));
668
+ const headers = {
669
+ 'cache-control': asset.cache,
670
+ etag: variant.etag,
671
+ 'x-content-type-options': 'nosniff',
672
+ ...(asset.policy ? { 'content-security-policy': pagePolicy(asset.policy, shell) } : {}),
673
+ };
674
+ if (asset.variants.length > 1)
675
+ headers.vary = 'Accept-Encoding';
676
+ if (unchanged(req.headers['if-none-match'], variant.etag)) {
677
+ if (!res.destroyed && !res.writableEnded)
678
+ res.writeHead(304, headers).end();
679
+ return;
680
+ }
681
+ const bytes = head ? undefined : await readFile(variant.file);
682
+ if (res.destroyed || res.writableEnded)
683
+ return;
684
+ res.writeHead(200, {
685
+ ...headers,
686
+ 'content-type': asset.type,
687
+ 'content-length': variant.size,
688
+ ...(variant.encoding ? { 'content-encoding': variant.encoding } : {}),
689
+ });
690
+ res.end(bytes);
691
+ };
692
+ }
693
+ /* One server per built page, made on its first request: a process serves one page, but a test may serve its own. */
694
+ const built = new Map();
695
+ const fromBuild = (dir) => {
696
+ let serve = built.get(dir);
697
+ if (!serve)
698
+ built.set(dir, (serve = builtClient(dir)));
699
+ return serve;
700
+ };