@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.
- package/LICENSE +21 -0
- package/README.md +17 -2
- package/dist/adapters/adapter.d.ts +693 -0
- package/dist/adapters/adapter.js +444 -0
- package/dist/adapters/cache/cacheStore.d.ts +75 -0
- package/dist/adapters/cache/cacheStore.js +160 -0
- package/dist/adapters/cache/resp.d.ts +52 -0
- package/dist/adapters/cache/resp.js +237 -0
- package/dist/adapters/commands/canonicalJson.d.ts +19 -0
- package/dist/adapters/commands/canonicalJson.js +154 -0
- package/dist/adapters/connect.d.ts +29 -0
- package/dist/adapters/connect.js +40 -0
- package/dist/adapters/connectionBudget.d.ts +101 -0
- package/dist/adapters/connectionBudget.js +128 -0
- package/dist/adapters/dbLatency.d.ts +35 -0
- package/dist/adapters/dbLatency.js +79 -0
- package/dist/adapters/epochCache.d.ts +50 -0
- package/dist/adapters/epochCache.js +85 -0
- package/dist/adapters/http/egress.d.ts +48 -0
- package/dist/adapters/http/egress.js +175 -0
- package/dist/adapters/http/httpAdapter.d.ts +71 -0
- package/dist/adapters/http/httpAdapter.js +512 -0
- package/dist/adapters/http/httpDescription.d.ts +32 -0
- package/dist/adapters/http/httpDescription.js +246 -0
- package/dist/adapters/http/openapi.d.ts +98 -0
- package/dist/adapters/http/openapi.js +487 -0
- package/dist/adapters/layoutRefusal.d.ts +24 -0
- package/dist/adapters/layoutRefusal.js +35 -0
- package/dist/adapters/net/networkPolicy.d.ts +44 -0
- package/dist/adapters/net/networkPolicy.js +123 -0
- package/dist/adapters/net/untrustedDatabase.d.ts +18 -0
- package/dist/adapters/net/untrustedDatabase.js +120 -0
- package/dist/adapters/poolAdmission.d.ts +43 -0
- package/dist/adapters/poolAdmission.js +184 -0
- package/dist/adapters/poolMetrics.d.ts +121 -0
- package/dist/adapters/poolMetrics.js +185 -0
- package/dist/adapters/postgres.d.ts +436 -0
- package/dist/adapters/postgres.js +1890 -0
- package/dist/adapters/postgresCatalog.d.ts +96 -0
- package/dist/adapters/postgresCatalog.js +387 -0
- package/dist/adapters/postgresCatalogDigest.d.ts +30 -0
- package/dist/adapters/postgresCatalogDigest.js +87 -0
- package/dist/adapters/postgresCatalogRows.d.ts +62 -0
- package/dist/adapters/postgresCatalogRows.js +37 -0
- package/dist/adapters/postgresDates.d.ts +1 -0
- package/dist/adapters/postgresDates.js +39 -0
- package/dist/adapters/postgresMaintenance.d.ts +33 -0
- package/dist/adapters/postgresMaintenance.js +179 -0
- package/dist/adapters/postgresPool.d.ts +255 -0
- package/dist/adapters/postgresPool.js +838 -0
- package/dist/adapters/postgresPooler.d.ts +28 -0
- package/dist/adapters/postgresPooler.js +267 -0
- package/dist/adapters/postgresReadCatalog.d.ts +31 -0
- package/dist/adapters/postgresReadCatalog.js +226 -0
- package/dist/adapters/postgresReadSnapshot.d.ts +46 -0
- package/dist/adapters/postgresReadSnapshot.js +133 -0
- package/dist/adapters/postgresSchemaEpoch.d.ts +24 -0
- package/dist/adapters/postgresSchemaEpoch.js +149 -0
- package/dist/adapters/postgresTransactionHandle.d.ts +173 -0
- package/dist/adapters/postgresTransactionHandle.js +524 -0
- package/dist/adapters/postgresValues.d.ts +30 -0
- package/dist/adapters/postgresValues.js +75 -0
- package/dist/adapters/replicas.d.ts +70 -0
- package/dist/adapters/replicas.js +208 -0
- package/dist/adapters/reservedSql.d.ts +38 -0
- package/dist/adapters/reservedSql.js +264 -0
- package/dist/adapters/rolePrivileges.d.ts +17 -0
- package/dist/adapters/rolePrivileges.js +22 -0
- package/dist/adapters/scoped/keyRows.d.ts +65 -0
- package/dist/adapters/scoped/keyRows.js +173 -0
- package/dist/adapters/scoped/postgresScopeCatalog.d.ts +16 -0
- package/dist/adapters/scoped/postgresScopeCatalog.js +117 -0
- package/dist/adapters/scoped/scopedCommandOperations.d.ts +5 -0
- package/dist/adapters/scoped/scopedCommandOperations.js +48 -0
- package/dist/adapters/scoped/scopedReads.d.ts +20 -0
- package/dist/adapters/scoped/scopedReads.js +174 -0
- package/dist/adapters/scoped/scopedTransaction.d.ts +89 -0
- package/dist/adapters/scoped/scopedTransaction.js +303 -0
- package/dist/adapters/scoped/sqliteScopeCatalog.d.ts +16 -0
- package/dist/adapters/scoped/sqliteScopeCatalog.js +241 -0
- package/dist/adapters/scoped/updateGuard.d.ts +3 -0
- package/dist/adapters/scoped/updateGuard.js +40 -0
- package/dist/adapters/serverSettings.d.ts +45 -0
- package/dist/adapters/serverSettings.js +46 -0
- package/dist/adapters/sqlite.d.ts +262 -0
- package/dist/adapters/sqlite.js +1434 -0
- package/dist/adapters/sqliteCostlyReads.d.ts +33 -0
- package/dist/adapters/sqliteCostlyReads.js +49 -0
- package/dist/adapters/sqliteDecimals.d.ts +22 -0
- package/dist/adapters/sqliteDecimals.js +57 -0
- package/dist/adapters/sqliteHandles.d.ts +43 -0
- package/dist/adapters/sqliteHandles.js +143 -0
- package/dist/adapters/sqliteStatementProcess.d.ts +29 -0
- package/dist/adapters/sqliteStatementProcess.js +131 -0
- package/dist/adapters/statementControl.d.ts +34 -0
- package/dist/adapters/statementControl.js +90 -0
- package/dist/adapters/storeHost.d.ts +130 -0
- package/dist/adapters/storeHost.js +13 -0
- package/dist/adapters/telemetry/drivers.d.ts +21 -0
- package/dist/adapters/telemetry/drivers.js +321 -0
- package/dist/adapters/telemetry/metrics.d.ts +63 -0
- package/dist/adapters/telemetry/metrics.js +122 -0
- package/dist/adapters/telemetry/otlp.d.ts +12 -0
- package/dist/adapters/telemetry/otlp.js +320 -0
- package/dist/adapters/telemetry/otlpEncode.d.ts +48 -0
- package/dist/adapters/telemetry/otlpEncode.js +366 -0
- package/dist/adapters/telemetry/otlpEnv.d.ts +1 -0
- package/dist/adapters/telemetry/otlpEnv.js +12 -0
- package/dist/adapters/telemetry/serverTiming.d.ts +83 -0
- package/dist/adapters/telemetry/serverTiming.js +503 -0
- package/dist/adapters/telemetry/start.d.ts +10 -0
- package/dist/adapters/telemetry/start.js +25 -0
- package/dist/adapters/telemetry/statement.d.ts +16 -0
- package/dist/adapters/telemetry/statement.js +134 -0
- package/dist/adapters/telemetry/trace.d.ts +127 -0
- package/dist/adapters/telemetry/trace.js +295 -0
- package/dist/adapters/writeAhead.d.ts +27 -0
- package/dist/adapters/writeAhead.js +46 -0
- package/dist/adapters/writeAttribution.d.ts +18 -0
- package/dist/adapters/writeAttribution.js +23 -0
- package/dist/adapters/writeCapture.d.ts +73 -0
- package/dist/adapters/writeCapture.js +20 -0
- package/dist/adapters/writeLanes.d.ts +94 -0
- package/dist/adapters/writeLanes.js +232 -0
- package/dist/engine.d.ts +15 -0
- package/dist/engine.js +13 -0
- package/dist/server/auth/credentials.d.ts +61 -0
- package/dist/server/auth/credentials.js +260 -0
- package/dist/server/cacheService.d.ts +50 -0
- package/dist/server/cacheService.js +110 -0
- package/dist/server/cli/args.d.ts +176 -0
- package/dist/server/cli/args.js +342 -0
- package/dist/server/cli/bin.d.ts +5 -0
- package/dist/server/cli/bin.js +66 -0
- package/dist/server/cli/browser.d.ts +15 -0
- package/dist/server/cli/browser.js +37 -0
- package/dist/server/cli/config.d.ts +50 -0
- package/dist/server/cli/config.js +206 -0
- package/dist/server/cli/startup.d.ts +36 -0
- package/dist/server/cli/startup.js +128 -0
- package/dist/server/cli/startupOptions.d.ts +63 -0
- package/dist/server/cli/startupOptions.js +143 -0
- package/dist/server/cli/subcommand.d.ts +28 -0
- package/dist/server/cli/subcommand.js +32 -0
- package/dist/server/cli/usage.d.ts +13 -0
- package/dist/server/cli/usage.js +31 -0
- package/dist/server/clientHttp.d.ts +184 -0
- package/dist/server/clientHttp.js +700 -0
- package/dist/server/clientSurface.d.ts +128 -0
- package/dist/server/clientSurface.js +182 -0
- package/dist/server/columnGrants.d.ts +103 -0
- package/dist/server/columnGrants.js +730 -0
- package/dist/server/compileCache.d.ts +1 -0
- package/dist/server/compileCache.js +30 -0
- package/dist/server/config/locations.d.ts +1 -0
- package/dist/server/config/locations.js +15 -0
- package/dist/server/configPaths.d.ts +7 -0
- package/dist/server/configPaths.js +34 -0
- package/dist/server/configSections.d.ts +64 -0
- package/dist/server/configSections.js +72 -0
- package/dist/server/connectionRedaction.d.ts +30 -0
- package/dist/server/connectionRedaction.js +77 -0
- package/dist/server/connections.d.ts +353 -0
- package/dist/server/connections.js +978 -0
- package/dist/server/constraints.d.ts +82 -0
- package/dist/server/constraints.js +169 -0
- package/dist/server/demo.d.ts +9 -0
- package/dist/server/demo.js +554 -0
- package/dist/server/devclient.d.ts +108 -0
- package/dist/server/devclient.js +361 -0
- package/dist/server/evidence.d.ts +55 -0
- package/dist/server/evidence.js +323 -0
- package/dist/server/hiddenColumns.d.ts +32 -0
- package/dist/server/hiddenColumns.js +238 -0
- package/dist/server/http/baselineHeaders.d.ts +24 -0
- package/dist/server/http/baselineHeaders.js +12 -0
- package/dist/server/http/captured.d.ts +35 -0
- package/dist/server/http/captured.js +73 -0
- package/dist/server/http/clock.d.ts +1 -0
- package/dist/server/http/clock.js +14 -0
- package/dist/server/http/connectionSource.d.ts +4 -0
- package/dist/server/http/connectionSource.js +48 -0
- package/dist/server/http/context.d.ts +189 -0
- package/dist/server/http/context.js +11 -0
- package/dist/server/http/crawlerText.d.ts +15 -0
- package/dist/server/http/crawlerText.js +32 -0
- package/dist/server/http/dataRoutes.d.ts +88 -0
- package/dist/server/http/dataRoutes.js +137 -0
- package/dist/server/http/door.d.ts +57 -0
- package/dist/server/http/door.js +39 -0
- package/dist/server/http/exportRoute.d.ts +15 -0
- package/dist/server/http/exportRoute.js +320 -0
- package/dist/server/http/firstPaint.d.ts +108 -0
- package/dist/server/http/firstPaint.js +262 -0
- package/dist/server/http/httpOperationRoutes.d.ts +11 -0
- package/dist/server/http/httpOperationRoutes.js +50 -0
- package/dist/server/http/pageReads.d.ts +20 -0
- package/dist/server/http/pageReads.js +205 -0
- package/dist/server/http/pageRoutes.d.ts +39 -0
- package/dist/server/http/pageRoutes.js +291 -0
- package/dist/server/http/probes.d.ts +22 -0
- package/dist/server/http/probes.js +27 -0
- package/dist/server/http/rateLimit.d.ts +131 -0
- package/dist/server/http/rateLimit.js +351 -0
- package/dist/server/http/readRoutes.d.ts +9 -0
- package/dist/server/http/readRoutes.js +131 -0
- package/dist/server/http/readRouting.d.ts +20 -0
- package/dist/server/http/readRouting.js +80 -0
- package/dist/server/http/recordCompose.d.ts +67 -0
- package/dist/server/http/recordCompose.js +167 -0
- package/dist/server/http/recordWrites.d.ts +89 -0
- package/dist/server/http/recordWrites.js +298 -0
- package/dist/server/http/refusalReport.d.ts +38 -0
- package/dist/server/http/refusalReport.js +63 -0
- package/dist/server/http/reply.d.ts +130 -0
- package/dist/server/http/reply.js +394 -0
- package/dist/server/http/requestOrigin.d.ts +11 -0
- package/dist/server/http/requestOrigin.js +8 -0
- package/dist/server/http/router.d.ts +45 -0
- package/dist/server/http/router.js +22 -0
- package/dist/server/http/serverCore.d.ts +68 -0
- package/dist/server/http/serverCore.js +177 -0
- package/dist/server/http/traceRequest.d.ts +30 -0
- package/dist/server/http/traceRequest.js +224 -0
- package/dist/server/http/trust.d.ts +261 -0
- package/dist/server/http/trust.js +472 -0
- package/dist/server/http/writeRefusal.d.ts +33 -0
- package/dist/server/http/writeRefusal.js +24 -0
- package/dist/server/httpConnection.d.ts +49 -0
- package/dist/server/httpConnection.js +170 -0
- package/dist/server/impact.d.ts +55 -0
- package/dist/server/impact.js +47 -0
- package/dist/server/journal.d.ts +134 -0
- package/dist/server/journal.js +398 -0
- package/dist/server/keysetReadHttp.d.ts +52 -0
- package/dist/server/keysetReadHttp.js +85 -0
- package/dist/server/layouts.d.ts +49 -0
- package/dist/server/layouts.js +192 -0
- package/dist/server/migrate/cli.d.ts +55 -0
- package/dist/server/migrate/cli.js +517 -0
- package/dist/server/migrate/database.d.ts +37 -0
- package/dist/server/migrate/database.js +247 -0
- package/dist/server/migrate/desired.d.ts +76 -0
- package/dist/server/migrate/desired.js +292 -0
- package/dist/server/migrate/files.d.ts +34 -0
- package/dist/server/migrate/files.js +141 -0
- package/dist/server/migrate/flyway.d.ts +7 -0
- package/dist/server/migrate/flyway.js +69 -0
- package/dist/server/migrate/history.d.ts +70 -0
- package/dist/server/migrate/history.js +211 -0
- package/dist/server/migrate/runner.d.ts +100 -0
- package/dist/server/migrate/runner.js +409 -0
- package/dist/server/migrate/snapshot.d.ts +30 -0
- package/dist/server/migrate/snapshot.js +239 -0
- package/dist/server/migrate/target.d.ts +33 -0
- package/dist/server/migrate/target.js +82 -0
- package/dist/server/openapiDraft.d.ts +25 -0
- package/dist/server/openapiDraft.js +171 -0
- package/dist/server/operations/diagnostics.d.ts +101 -0
- package/dist/server/operations/diagnostics.js +284 -0
- package/dist/server/operations/requestMetrics.d.ts +33 -0
- package/dist/server/operations/requestMetrics.js +94 -0
- package/dist/server/packageVersion.d.ts +1 -0
- package/dist/server/packageVersion.js +11 -0
- package/dist/server/poolConfig.d.ts +34 -0
- package/dist/server/poolConfig.js +114 -0
- package/dist/server/product.d.ts +20 -0
- package/dist/server/product.js +12 -0
- package/dist/server/recordHistoryOperations.d.ts +39 -0
- package/dist/server/recordHistoryOperations.js +43 -0
- package/dist/server/recordWriteOperations.d.ts +111 -0
- package/dist/server/recordWriteOperations.js +329 -0
- package/dist/server/resourceReadHttp.d.ts +81 -0
- package/dist/server/resourceReadHttp.js +606 -0
- package/dist/server/resourceReadOperations.d.ts +147 -0
- package/dist/server/resourceReadOperations.js +452 -0
- package/dist/server/scaffoldMachine.d.ts +54 -0
- package/dist/server/scaffoldMachine.js +184 -0
- package/dist/server/seed/cli.d.ts +20 -0
- package/dist/server/seed/cli.js +164 -0
- package/dist/server/seed/lexicon.d.ts +26 -0
- package/dist/server/seed/lexicon.js +585 -0
- package/dist/server/seed/seed.d.ts +70 -0
- package/dist/server/seed/seed.js +779 -0
- package/dist/server/seed/words.d.ts +21 -0
- package/dist/server/seed/words.js +164 -0
- package/dist/server/serverRequests.d.ts +6 -0
- package/dist/server/serverRequests.js +33 -0
- package/dist/server/serverTimeouts.d.ts +33 -0
- package/dist/server/serverTimeouts.js +32 -0
- package/dist/server/shapeonly.d.ts +32 -0
- package/dist/server/shapeonly.js +110 -0
- package/dist/server/startupWarnings.d.ts +32 -0
- package/dist/server/startupWarnings.js +92 -0
- package/dist/shared/addressParams.d.ts +28 -0
- package/dist/shared/addressParams.js +47 -0
- package/dist/shared/appCards.d.ts +123 -0
- package/dist/shared/appCards.js +385 -0
- package/dist/shared/appComponents.d.ts +177 -0
- package/dist/shared/appComponents.js +422 -0
- package/dist/shared/appDocuments.d.ts +43 -0
- package/dist/shared/appDocuments.js +131 -0
- package/dist/shared/appEmbeds.d.ts +21 -0
- package/dist/shared/appEmbeds.js +24 -0
- package/dist/shared/appIcons.d.ts +28 -0
- package/dist/shared/appIcons.js +223 -0
- package/dist/shared/appLinks.d.ts +17 -0
- package/dist/shared/appLinks.js +124 -0
- package/dist/shared/appListColumns.d.ts +3 -0
- package/dist/shared/appListColumns.js +66 -0
- package/dist/shared/appLocale.d.ts +36 -0
- package/dist/shared/appLocale.js +86 -0
- package/dist/shared/appMessages.d.ts +44 -0
- package/dist/shared/appMessages.js +78 -0
- package/dist/shared/appNoun.d.ts +21 -0
- package/dist/shared/appNoun.js +32 -0
- package/dist/shared/autoBucket.d.ts +98 -0
- package/dist/shared/autoBucket.js +305 -0
- package/dist/shared/autoValues.d.ts +25 -0
- package/dist/shared/autoValues.js +25 -0
- package/dist/shared/breakdown.d.ts +228 -0
- package/dist/shared/breakdown.js +557 -0
- package/dist/shared/breakdowntext.d.ts +41 -0
- package/dist/shared/breakdowntext.js +400 -0
- package/dist/shared/builtInThemes.d.ts +2 -0
- package/dist/shared/builtInThemes.js +771 -0
- package/dist/shared/chartSeparation.d.ts +11 -0
- package/dist/shared/chartSeparation.js +58 -0
- package/dist/shared/clauses.d.ts +22 -0
- package/dist/shared/clauses.js +97 -0
- package/dist/shared/columnCaption.d.ts +16 -0
- package/dist/shared/columnCaption.js +90 -0
- package/dist/shared/commandFieldPath.d.ts +2 -0
- package/dist/shared/commandFieldPath.js +7 -0
- package/dist/shared/commandWire.d.ts +26 -0
- package/dist/shared/commandWire.js +41 -0
- package/dist/shared/computed.d.ts +161 -0
- package/dist/shared/computed.js +378 -0
- package/dist/shared/computedParse.d.ts +13 -0
- package/dist/shared/computedParse.js +278 -0
- package/dist/shared/computedValue.d.ts +47 -0
- package/dist/shared/computedValue.js +191 -0
- package/dist/shared/connection.d.ts +30 -0
- package/dist/shared/connection.js +1 -0
- package/dist/shared/csv.d.ts +20 -0
- package/dist/shared/csv.js +63 -0
- package/dist/shared/dashLayout.d.ts +30 -0
- package/dist/shared/dashLayout.js +132 -0
- package/dist/shared/dashboardAsks.d.ts +93 -0
- package/dist/shared/dashboardAsks.js +129 -0
- package/dist/shared/dashboardTrend.d.ts +20 -0
- package/dist/shared/dashboardTrend.js +50 -0
- package/dist/shared/declaredReferences.d.ts +50 -0
- package/dist/shared/declaredReferences.js +202 -0
- package/dist/shared/definedFields.d.ts +63 -0
- package/dist/shared/definedFields.js +103 -0
- package/dist/shared/definedValues.d.ts +63 -0
- package/dist/shared/definedValues.js +184 -0
- package/dist/shared/displayDefaults.d.ts +135 -0
- package/dist/shared/displayDefaults.js +529 -0
- package/dist/shared/dueDate.d.ts +6 -0
- package/dist/shared/dueDate.js +6 -0
- package/dist/shared/duration.d.ts +4 -0
- package/dist/shared/duration.js +23 -0
- package/dist/shared/fileBounds.d.ts +9 -0
- package/dist/shared/fileBounds.js +9 -0
- package/dist/shared/filter.d.ts +217 -0
- package/dist/shared/filter.js +305 -0
- package/dist/shared/firstPaint.d.ts +24 -0
- package/dist/shared/firstPaint.js +33 -0
- package/dist/shared/form.d.ts +21 -0
- package/dist/shared/form.js +25 -0
- package/dist/shared/formValues.d.ts +104 -0
- package/dist/shared/formValues.js +352 -0
- package/dist/shared/funnel.d.ts +45 -0
- package/dist/shared/funnel.js +108 -0
- package/dist/shared/httpOperations.d.ts +48 -0
- package/dist/shared/httpOperations.js +9 -0
- package/dist/shared/iconGlyphs.d.ts +4 -0
- package/dist/shared/iconGlyphs.js +151 -0
- package/dist/shared/iconWeights.d.ts +3 -0
- package/dist/shared/iconWeights.js +162 -0
- package/dist/shared/imageWidths.d.ts +32 -0
- package/dist/shared/imageWidths.js +38 -0
- package/dist/shared/keysetPage.d.ts +64 -0
- package/dist/shared/keysetPage.js +161 -0
- package/dist/shared/like.d.ts +20 -0
- package/dist/shared/like.js +29 -0
- package/dist/shared/listEmpty.d.ts +12 -0
- package/dist/shared/listEmpty.js +36 -0
- package/dist/shared/listFilters.d.ts +28 -0
- package/dist/shared/listFilters.js +84 -0
- package/dist/shared/listPresentations.d.ts +199 -0
- package/dist/shared/listPresentations.js +7 -0
- package/dist/shared/listQuestion.d.ts +52 -0
- package/dist/shared/listQuestion.js +137 -0
- package/dist/shared/lookPalettes.d.ts +62 -0
- package/dist/shared/lookPalettes.js +306 -0
- package/dist/shared/maskQuoted.d.ts +24 -0
- package/dist/shared/maskQuoted.js +48 -0
- package/dist/shared/mentionLabel.d.ts +19 -0
- package/dist/shared/mentionLabel.js +38 -0
- package/dist/shared/mentionLookup.d.ts +17 -0
- package/dist/shared/mentionLookup.js +64 -0
- package/dist/shared/menuCounts.d.ts +16 -0
- package/dist/shared/menuCounts.js +74 -0
- package/dist/shared/model.d.ts +79 -0
- package/dist/shared/model.js +153 -0
- package/dist/shared/money.d.ts +44 -0
- package/dist/shared/money.js +81 -0
- package/dist/shared/moneyEntry.d.ts +7 -0
- package/dist/shared/moneyEntry.js +27 -0
- package/dist/shared/mount.d.ts +118 -0
- package/dist/shared/mount.js +248 -0
- package/dist/shared/niceTicks.d.ts +26 -0
- package/dist/shared/niceTicks.js +50 -0
- package/dist/shared/order.d.ts +59 -0
- package/dist/shared/order.js +133 -0
- package/dist/shared/page.d.ts +135 -0
- package/dist/shared/page.js +1187 -0
- package/dist/shared/pageAnatomy.d.ts +99 -0
- package/dist/shared/pageAnatomy.js +370 -0
- package/dist/shared/pageConfig.d.ts +25 -0
- package/dist/shared/pageConfig.js +1308 -0
- package/dist/shared/pageEmptyActions.d.ts +12 -0
- package/dist/shared/pageEmptyActions.js +20 -0
- package/dist/shared/pageLayouts.d.ts +72 -0
- package/dist/shared/pageLayouts.js +205 -0
- package/dist/shared/pageModel.d.ts +785 -0
- package/dist/shared/pageModel.js +121 -0
- package/dist/shared/pagePaths.d.ts +180 -0
- package/dist/shared/pagePaths.js +869 -0
- package/dist/shared/pagePlans.d.ts +52 -0
- package/dist/shared/pagePlans.js +108 -0
- package/dist/shared/pageRoutes.d.ts +9 -0
- package/dist/shared/pageRoutes.js +9 -0
- package/dist/shared/query.d.ts +166 -0
- package/dist/shared/query.js +1302 -0
- package/dist/shared/queryDates.d.ts +12 -0
- package/dist/shared/queryDates.js +101 -0
- package/dist/shared/queryOperands.d.ts +99 -0
- package/dist/shared/queryOperands.js +131 -0
- package/dist/shared/reads.d.ts +103 -0
- package/dist/shared/reads.js +154 -0
- package/dist/shared/recordLabel.d.ts +51 -0
- package/dist/shared/recordLabel.js +123 -0
- package/dist/shared/recordReadKeys.d.ts +30 -0
- package/dist/shared/recordReadKeys.js +51 -0
- package/dist/shared/recordReads.d.ts +268 -0
- package/dist/shared/recordReads.js +368 -0
- package/dist/shared/recordview.d.ts +198 -0
- package/dist/shared/recordview.js +356 -0
- package/dist/shared/referenceModel.d.ts +58 -0
- package/dist/shared/referenceModel.js +194 -0
- package/dist/shared/refusal.d.ts +64 -0
- package/dist/shared/refusal.js +144 -0
- package/dist/shared/relatedCreate.d.ts +30 -0
- package/dist/shared/relatedCreate.js +162 -0
- package/dist/shared/resourceHttp.d.ts +464 -0
- package/dist/shared/resourceHttp.js +1 -0
- package/dist/shared/richText.d.ts +85 -0
- package/dist/shared/richText.js +305 -0
- package/dist/shared/rollups.d.ts +143 -0
- package/dist/shared/rollups.js +64 -0
- package/dist/shared/rowScope.d.ts +72 -0
- package/dist/shared/rowScope.js +376 -0
- package/dist/shared/runtimeTables.d.ts +44 -0
- package/dist/shared/runtimeTables.js +79 -0
- package/dist/shared/schema.d.ts +523 -0
- package/dist/shared/schema.js +627 -0
- package/dist/shared/schematext.d.ts +38 -0
- package/dist/shared/schematext.js +101 -0
- package/dist/shared/scopeCatalog.d.ts +29 -0
- package/dist/shared/scopeCatalog.js +468 -0
- package/dist/shared/servedApp.d.ts +681 -0
- package/dist/shared/servedApp.js +45 -0
- package/dist/shared/sessionLease.d.ts +34 -0
- package/dist/shared/sessionLease.js +3 -0
- package/dist/shared/shape.d.ts +55 -0
- package/dist/shared/shape.js +168 -0
- package/dist/shared/slug.d.ts +1 -0
- package/dist/shared/slug.js +12 -0
- package/dist/shared/sortText.d.ts +14 -0
- package/dist/shared/sortText.js +26 -0
- package/dist/shared/sqlRelation.d.ts +4 -0
- package/dist/shared/sqlRelation.js +8 -0
- package/dist/shared/sqlsaved.d.ts +44 -0
- package/dist/shared/sqlsaved.js +63 -0
- package/dist/shared/stitchedPaths.d.ts +27 -0
- package/dist/shared/stitchedPaths.js +38 -0
- package/dist/shared/structuredFilter.d.ts +22 -0
- package/dist/shared/structuredFilter.js +1 -0
- package/dist/shared/subtitlePath.d.ts +20 -0
- package/dist/shared/subtitlePath.js +24 -0
- package/dist/shared/suggest.d.ts +18 -0
- package/dist/shared/suggest.js +59 -0
- package/dist/shared/tableSizing.d.ts +4 -0
- package/dist/shared/tableSizing.js +9 -0
- package/dist/shared/tagLists.d.ts +57 -0
- package/dist/shared/tagLists.js +34 -0
- package/dist/shared/textRules.d.ts +54 -0
- package/dist/shared/textRules.js +133 -0
- package/dist/shared/theme.d.ts +94 -0
- package/dist/shared/theme.js +800 -0
- package/dist/shared/themeColor.d.ts +34 -0
- package/dist/shared/themeColor.js +109 -0
- package/dist/shared/themeFaces.d.ts +30 -0
- package/dist/shared/themeFaces.js +42 -0
- package/dist/shared/themeInk.d.ts +20 -0
- package/dist/shared/themeInk.js +52 -0
- package/dist/shared/themeLooks.d.ts +9 -0
- package/dist/shared/themeLooks.js +572 -0
- package/dist/shared/themeParts.d.ts +26 -0
- package/dist/shared/themeParts.js +71 -0
- package/dist/shared/themePartsCheck.d.ts +21 -0
- package/dist/shared/themePartsCheck.js +91 -0
- package/dist/shared/themePresets.d.ts +85 -0
- package/dist/shared/themePresets.js +139 -0
- package/dist/shared/themeRecipeWords.d.ts +156 -0
- package/dist/shared/themeRecipeWords.js +156 -0
- package/dist/shared/themeRecipes.d.ts +213 -0
- package/dist/shared/themeRecipes.js +234 -0
- package/dist/shared/themeResolve.d.ts +55 -0
- package/dist/shared/themeResolve.js +52 -0
- package/dist/shared/themeTokens.d.ts +107 -0
- package/dist/shared/themeTokens.js +116 -0
- package/dist/shared/themeType.d.ts +38 -0
- package/dist/shared/themeType.js +205 -0
- package/dist/shared/unitWord.d.ts +4 -0
- package/dist/shared/unitWord.js +37 -0
- package/dist/shared/view.d.ts +195 -0
- package/dist/shared/view.js +987 -0
- package/dist/shared/viewLabels.d.ts +47 -0
- package/dist/shared/viewLabels.js +459 -0
- package/dist/shared/viewPaths.d.ts +248 -0
- package/dist/shared/viewPaths.js +294 -0
- package/dist/shared/viewtext.d.ts +57 -0
- package/dist/shared/viewtext.js +282 -0
- package/dist/shared/vocabulary.d.ts +71 -0
- package/dist/shared/vocabulary.js +249 -0
- package/dist/shared/weekStart.d.ts +7 -0
- package/dist/shared/weekStart.js +36 -0
- package/mark.svg +1 -0
- package/package.json +261 -4
- package/schema/model.d.ts +298 -0
- package/schema/theme.d.ts +587 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The door a dispatcher holds every request to before any route reads it,
|
|
3
|
+
* in one order: the Host, the proxy's identity, the product's session, then
|
|
4
|
+
* a write's Origin and body (trust.ts `doorRefusal`). The order is the
|
|
5
|
+
* defence, so it is kept here once rather than spelled in each dispatcher:
|
|
6
|
+
*
|
|
7
|
+
* - the Host first, on every request, read or write, page or endpoint. The
|
|
8
|
+
* name tablewalk was reached by is the one thing a rebinding attack
|
|
9
|
+
* cannot fake, so it is checked before anything is served — including
|
|
10
|
+
* index.html, so the attempt fails at the door rather than at the first
|
|
11
|
+
* fetch;
|
|
12
|
+
* - the proxy's identity (`--auth-proxy-header`), unless the product says
|
|
13
|
+
* the request names no one whatever its headers carry;
|
|
14
|
+
* - the product's session (`SessionDoor`): an App's sign-in, its public
|
|
15
|
+
* forms and pages, a host's bearer on another origin. The database
|
|
16
|
+
* browser has none;
|
|
17
|
+
* - a write's Origin and JSON body last, because the session part decides
|
|
18
|
+
* whether an Origin is vouched for (embed/crossOrigin.ts `embedDoor`).
|
|
19
|
+
*
|
|
20
|
+
* Returns who is asking and what the session established, or `undefined`
|
|
21
|
+
* when the door already answered — in which case the caller is done.
|
|
22
|
+
*/
|
|
23
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
24
|
+
import { type Bound } from './trust.js';
|
|
25
|
+
import type { Identity } from './context.js';
|
|
26
|
+
/** Which step refused: a dispatcher answers each in its own shape (a command's, the API's, a page's). */
|
|
27
|
+
type DoorCheck = 'host' | 'identity' | 'origin';
|
|
28
|
+
interface DoorAsk {
|
|
29
|
+
readonly req: IncomingMessage;
|
|
30
|
+
readonly res: ServerResponse;
|
|
31
|
+
readonly bound: Bound;
|
|
32
|
+
/** Answer a refusal, in the dispatcher's own shape. */
|
|
33
|
+
readonly refuse: (check: DoorCheck, status: 401 | 403, error: string) => void;
|
|
34
|
+
}
|
|
35
|
+
/** What a request arriving at the session part is, once the Host has passed. */
|
|
36
|
+
interface Arrival {
|
|
37
|
+
/** The session part answered it already: a preflight from a host on another origin. */
|
|
38
|
+
readonly answered?: boolean;
|
|
39
|
+
/** It names no one, whatever its headers say: a public storefront's request (http/tenantHosts.ts). */
|
|
40
|
+
readonly anonymous?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** A product's part of the door, between the proxy's identity and a write's Origin. */
|
|
43
|
+
interface SessionDoor<S> {
|
|
44
|
+
/** After the Host, before the proxy identity is read. */
|
|
45
|
+
arrive?(): Arrival | Promise<Arrival>;
|
|
46
|
+
/**
|
|
47
|
+
* The session over the proxy's identity, which it completes in place (the
|
|
48
|
+
* account, its roles and name): what it established, or `undefined` when it
|
|
49
|
+
* answered the request.
|
|
50
|
+
*/
|
|
51
|
+
admit(identity: Identity): Promise<S | undefined>;
|
|
52
|
+
}
|
|
53
|
+
export declare function door<S>(ask: DoorAsk, session: SessionDoor<S>): Promise<{
|
|
54
|
+
identity: Identity;
|
|
55
|
+
session: S;
|
|
56
|
+
} | undefined>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { doorRefusal, identityFor, writes } from './trust.js';
|
|
2
|
+
import { admitAs } from '../../adapters/poolAdmission.js';
|
|
3
|
+
export async function door(ask, session) {
|
|
4
|
+
const { req, bound, refuse } = ask;
|
|
5
|
+
/* A write's Origin and body are the door's second asking, below: the
|
|
6
|
+
session part decides first whether its Origin is vouched for. */
|
|
7
|
+
const wrongHost = doorRefusal(req, bound, { writing: false })?.error;
|
|
8
|
+
if (wrongHost) {
|
|
9
|
+
refuse('host', 403, wrongHost);
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const arrival = (await session.arrive?.()) ?? {};
|
|
13
|
+
if (arrival.answered)
|
|
14
|
+
return undefined;
|
|
15
|
+
const identity = arrival.anonymous ? {} : identityFor(req, bound);
|
|
16
|
+
if (identity.refusal) {
|
|
17
|
+
refuse('identity', 401, identity.refusal);
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const admitted = await session.admit(identity);
|
|
21
|
+
if (admitted === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
/* Signed in, its pool checkouts wait their turn as the account's, not its
|
|
24
|
+
address's (adapters/poolAdmission.ts): one person's tabs on two networks
|
|
25
|
+
are one share of the line, and an office behind one address is many. */
|
|
26
|
+
admitAs(identity.id ?? identity.who);
|
|
27
|
+
/* Every request that can change something is checked before it is read, so
|
|
28
|
+
a refusal costs nothing and happens before any work. Admitted on a bearer
|
|
29
|
+
(embedDoor), the Origin was checked against the one the bearer was issued
|
|
30
|
+
to; the Host and the JSON body still are. */
|
|
31
|
+
if (writes(req)) {
|
|
32
|
+
const refusal = doorRefusal(req, bound, { writing: true })?.error;
|
|
33
|
+
if (refusal) {
|
|
34
|
+
refuse('origin', 403, refusal);
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { identity, session: admitted };
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { parseQuery } from '../../shared/query.js';
|
|
2
|
+
import type { PostContext } from './context.js';
|
|
3
|
+
/** Who `me` is in a question, where its words name `me` (parseQuery's `me`). */
|
|
4
|
+
type Person = NonNullable<Parameters<typeof parseQuery>[1]>['me'];
|
|
5
|
+
/** What a product decides of an export. */
|
|
6
|
+
export interface ExportHooks {
|
|
7
|
+
/** Whether this request's person may export a table (`''`: any table); `/api/run` bounds its reads by the same answer. */
|
|
8
|
+
may(post: PostContext): (tableId: string) => boolean;
|
|
9
|
+
/** Who `me` is in the question `text`, read only where its words name `me`. */
|
|
10
|
+
person?(post: PostContext, text: string): Promise<Person | undefined>;
|
|
11
|
+
/** A row as a CSV says it: an amount kept in minor units as the figure it is, a value as its component's word. */
|
|
12
|
+
amounts?(post: PostContext, tableId: string): ((row: Record<string, unknown>) => Record<string, unknown>) | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function exportRoute(post: PostContext, hooks: ExportHooks): Promise<boolean>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { createBrotliCompress, createGzip, constants as zlib } from 'node:zlib';
|
|
2
|
+
import { MAX_LIMIT, clampLimit } from '../../shared/reads.js';
|
|
3
|
+
import { parseQuery } from '../../shared/query.js';
|
|
4
|
+
import { textToView } from '../../shared/viewtext.js';
|
|
5
|
+
import { findTable, primaryKey, resolveOrder } from '../../shared/schema.js';
|
|
6
|
+
import { backrefsTo, resolveAggregate, tryResolvePath } from '../../shared/viewPaths.js';
|
|
7
|
+
import { CRLF, csvField, csvRecord, jsonRecord } from '../../shared/csv.js';
|
|
8
|
+
import { readRecords, readView } from '../resourceReadOperations.js';
|
|
9
|
+
import { acceptedEncoding, httpRead, send } from './reply.js';
|
|
10
|
+
import { rollupReads } from '../../shared/rollups.js';
|
|
11
|
+
const EXPORT_PATH = '/api/export';
|
|
12
|
+
/** Rows read per statement: large enough that a 100,000-row file is a hundred
|
|
13
|
+
* reads, small enough that one batch is never a memory event. */
|
|
14
|
+
const BATCH = 1000;
|
|
15
|
+
const FORMATS = {
|
|
16
|
+
csv: { type: 'text/csv', extension: 'csv' },
|
|
17
|
+
json: { type: 'application/json', extension: 'json' },
|
|
18
|
+
ndjson: { type: 'application/x-ndjson', extension: 'ndjson' },
|
|
19
|
+
};
|
|
20
|
+
export async function exportRoute(post, hooks) {
|
|
21
|
+
const { res, path, body, adapter, schema, appNow } = post;
|
|
22
|
+
if (path !== EXPORT_PATH)
|
|
23
|
+
return false;
|
|
24
|
+
/* An App that grants by role says who exports which table (appExportable); the file is refused where the Export menu is not offered. */
|
|
25
|
+
const may = hooks.may(post);
|
|
26
|
+
if (!may('')) {
|
|
27
|
+
send(res, 403, { error: 'Export is not available to this person.' });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// Never reached in one (httpRowPolicyAllows), and refused here as well: a policy reply cannot stream.
|
|
31
|
+
if (post.rowPolicy) {
|
|
32
|
+
send(res, 403, {
|
|
33
|
+
error: 'This operation is unavailable in a row-policy application.',
|
|
34
|
+
});
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
const format = body.format ?? 'csv';
|
|
38
|
+
if (typeof format !== 'string' || !Object.hasOwn(FORMATS, format)) {
|
|
39
|
+
send(res, 400, { error: 'format must be "csv", "json" or "ndjson".' });
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (body.columns !== undefined && (!Array.isArray(body.columns) || body.columns.some((column) => typeof column !== 'string'))) {
|
|
43
|
+
send(res, 400, { error: 'columns must be a list of column names.' });
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
const text = String(body.q ?? '');
|
|
47
|
+
const me = await hooks.person?.(post, text);
|
|
48
|
+
const person = me === undefined ? {} : { me };
|
|
49
|
+
const parsed = parseQuery(text, { schema, now: appNow(), ...person });
|
|
50
|
+
/* A question only a view can answer (a path through a reference) exports
|
|
51
|
+
as a view, paged by offset: its rows have no single key to resume from. */
|
|
52
|
+
if ((!parsed.query || parsed.errors.length) && adapter.runView) {
|
|
53
|
+
const asView = textToView(schema, text, {
|
|
54
|
+
id: 'export',
|
|
55
|
+
name: '',
|
|
56
|
+
now: appNow(),
|
|
57
|
+
...person,
|
|
58
|
+
});
|
|
59
|
+
if (asView.view && !asView.errors.length) {
|
|
60
|
+
const view = asView.view;
|
|
61
|
+
/* Every table the view reaches, not only its base: a column through a reference, an aggregate or a filter on one reads another table's rows into the file. */
|
|
62
|
+
for (const reached of viewTables(schema, view))
|
|
63
|
+
if (!may(reached))
|
|
64
|
+
return refuseTable(res, reached === UNKNOWN_TABLE ? view.base : reached);
|
|
65
|
+
const total = clampLimit(view.limit ?? MAX_LIMIT);
|
|
66
|
+
const read = (offset) => httpRead(() => readView(adapter, schema, view, { limit: Math.min(BATCH, total - offset), offset }, 'none')).then(({ result }) => result);
|
|
67
|
+
await stream(res, format, view.base, total, read, requested(body) ?? undefined, hooks.amounts?.(post, view.base));
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!parsed.query) {
|
|
72
|
+
send(res, 200, { errors: parsed.errors });
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (parsed.errors.length) {
|
|
76
|
+
send(res, 200, { errors: parsed.errors });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const query = parsed.query;
|
|
80
|
+
const table = findTable(schema, query.table);
|
|
81
|
+
if (!table) {
|
|
82
|
+
send(res, 404, { error: `Unknown table "${query.table}"` });
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (!may(table.id))
|
|
86
|
+
return refuseTable(res, table.id);
|
|
87
|
+
const wanted = requested(body) ?? (query.columns?.length ? query.columns : undefined);
|
|
88
|
+
for (const reached of queryTables(schema, table, query, wanted))
|
|
89
|
+
if (!may(reached))
|
|
90
|
+
return refuseTable(res, reached === UNKNOWN_TABLE ? table.id : reached);
|
|
91
|
+
const total = clampLimit(query.limit ?? MAX_LIMIT);
|
|
92
|
+
const order = resolveOrder(table, query.orderBy).order;
|
|
93
|
+
const keyset = keysetOrder(table, order, schema.dialect);
|
|
94
|
+
/* The key is read even when the file does not show it: it is where the
|
|
95
|
+
next batch starts. It never reaches the file (`wanted` is the file's). */
|
|
96
|
+
const reading = wanted && keyset ? [...new Set([...wanted, ...keyset.map((o) => o.column)])] : wanted;
|
|
97
|
+
let after;
|
|
98
|
+
const read = async (offset) => {
|
|
99
|
+
const { result } = await httpRead(() => readRecords(adapter, schema, {
|
|
100
|
+
...query,
|
|
101
|
+
...(reading ? { columns: reading } : {}),
|
|
102
|
+
orderBy: order,
|
|
103
|
+
filter: keyset && after ? beyond(query.filter, keyset, after) : query.filter,
|
|
104
|
+
limit: Math.min(BATCH, total - offset),
|
|
105
|
+
offset: keyset ? 0 : offset,
|
|
106
|
+
}, 'none'));
|
|
107
|
+
after = result.rows.at(-1);
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
110
|
+
await stream(res, format, table.id, total, read, wanted, hooks.amounts?.(post, table.id));
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
function refuseTable(res, tableId) {
|
|
114
|
+
send(res, 403, {
|
|
115
|
+
error: `Export of "${tableId}" is not available to this person.`,
|
|
116
|
+
});
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/** Stands for a table a view reaches that cannot be named (a many-valued condition it cannot resolve): never exportable. */
|
|
120
|
+
const UNKNOWN_TABLE = '\u0000unknown';
|
|
121
|
+
/** Every table a view reads from: its base, each table along a reference path in its columns, filter and order, and the rows its aggregates and `any` conditions read. */
|
|
122
|
+
function viewTables(schema, view) {
|
|
123
|
+
const tables = new Set([view.base]);
|
|
124
|
+
const path = pathReach(schema, view.base, tables);
|
|
125
|
+
for (const column of view.columns)
|
|
126
|
+
path(column.path);
|
|
127
|
+
for (const order of view.orderBy ?? [])
|
|
128
|
+
if (!order.alias)
|
|
129
|
+
path(order.path);
|
|
130
|
+
for (const group of view.filter?.groups ?? []) {
|
|
131
|
+
for (const condition of group) {
|
|
132
|
+
if (condition.any) {
|
|
133
|
+
const child = backrefsTo(schema, view.base).find((b) => b.name === condition.any.via);
|
|
134
|
+
tables.add(child ? child.child : UNKNOWN_TABLE);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
path(condition.path);
|
|
138
|
+
if (condition.other)
|
|
139
|
+
path(condition.other);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// The ones pinned to the view already (viewLabels.ts withViewComputed), as a read pins them.
|
|
143
|
+
for (const rollup of Object.values(view.computed ?? {}))
|
|
144
|
+
for (const { table } of rollupReads(rollup))
|
|
145
|
+
tables.add(table);
|
|
146
|
+
for (const expressed of Object.values(view.expressions ?? {}))
|
|
147
|
+
for (const read of expressed.reads)
|
|
148
|
+
path(expressed.on ? `${expressed.on}.${read}` : read);
|
|
149
|
+
for (const aggregate of view.aggregates ?? []) {
|
|
150
|
+
try {
|
|
151
|
+
const resolved = resolveAggregate(schema, view.base, aggregate);
|
|
152
|
+
tables.add(resolved.child.id);
|
|
153
|
+
tables.add(resolved.parent.id);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
tables.add(UNKNOWN_TABLE);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return tables;
|
|
160
|
+
}
|
|
161
|
+
/** Every table a single-table query's file reads: its own, and those its computed columns and rollups read. */
|
|
162
|
+
function queryTables(schema, table, query, wanted) {
|
|
163
|
+
const tables = new Set([table.id]);
|
|
164
|
+
const path = pathReach(schema, table.id, tables);
|
|
165
|
+
// A stored column is the table's own; an unknown one the read refuses by name.
|
|
166
|
+
const derived = (name) => Object.hasOwn(table.rollups ?? {}, name) || Object.hasOwn(table.computed ?? {}, name);
|
|
167
|
+
const names = [
|
|
168
|
+
...(wanted ?? table.columns.map((each) => each.name)),
|
|
169
|
+
...(query.orderBy ?? []).map((order) => order.column),
|
|
170
|
+
...(query.filter?.groups ?? []).flatMap((group) => group.flatMap((condition) => [condition.column, ...(condition.other ? [condition.other] : [])])),
|
|
171
|
+
];
|
|
172
|
+
for (const name of new Set(names))
|
|
173
|
+
if (derived(name))
|
|
174
|
+
path(name);
|
|
175
|
+
return tables;
|
|
176
|
+
}
|
|
177
|
+
/* Adds to `tables` every table a path from `base` reads. */
|
|
178
|
+
function pathReach(schema, base, tables) {
|
|
179
|
+
const seen = new Set();
|
|
180
|
+
const path = (text) => {
|
|
181
|
+
const { resolved } = tryResolvePath(schema, base, text);
|
|
182
|
+
if (!resolved) {
|
|
183
|
+
tables.add(UNKNOWN_TABLE);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
for (const hop of resolved.hops)
|
|
187
|
+
tables.add(hop.to.table);
|
|
188
|
+
tables.add(resolved.table.id);
|
|
189
|
+
/* A rollup is a figure of another table's rows, and a computed column is
|
|
190
|
+
worked out of the columns it reads: either carries those tables into
|
|
191
|
+
the file as surely as a column through a reference does. */
|
|
192
|
+
if (resolved.rollup)
|
|
193
|
+
for (const { table } of rollupReads(resolved.rollup))
|
|
194
|
+
tables.add(table);
|
|
195
|
+
if (resolved.computed && !seen.has(text)) {
|
|
196
|
+
seen.add(text);
|
|
197
|
+
const on = text.includes('.') ? text.slice(0, text.lastIndexOf('.') + 1) : '';
|
|
198
|
+
for (const read of resolved.computed.reads)
|
|
199
|
+
path(`${on}${read}`);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
return path;
|
|
203
|
+
}
|
|
204
|
+
function requested(body) {
|
|
205
|
+
return Array.isArray(body.columns) && body.columns.length ? body.columns : undefined;
|
|
206
|
+
}
|
|
207
|
+
/* Types whose values come back exactly as stored on Postgres. */
|
|
208
|
+
const EXACT_TYPE = /^(tiny|small|medium|big)?int(eger)?\d*\b|^(big|small)?serial|char|text|uuid/i;
|
|
209
|
+
/**
|
|
210
|
+
* The order a keyset can resume, or undefined. Only the key, and only
|
|
211
|
+
* columns whose value comes back exactly as it is stored: an integer or text
|
|
212
|
+
* on Postgres — a timestamp comes back to the millisecond and a
|
|
213
|
+
* float rounded, and resuming "after" a rounded value repeats or skips rows —
|
|
214
|
+
* and anything on SQLite, which hands back what it holds.
|
|
215
|
+
*/
|
|
216
|
+
function keysetOrder(table, order, dialect) {
|
|
217
|
+
const key = primaryKey(table);
|
|
218
|
+
if (!key.length || order.length !== key.length || order.some((o, i) => o.column !== key[i]))
|
|
219
|
+
return undefined;
|
|
220
|
+
if (dialect === 'http')
|
|
221
|
+
return undefined;
|
|
222
|
+
const exact = order.every((o) => {
|
|
223
|
+
const column = table.columns.find((c) => c.name === o.column);
|
|
224
|
+
if (!column || column.nullable)
|
|
225
|
+
return false;
|
|
226
|
+
return dialect === 'sqlite' || EXACT_TYPE.test(column.type);
|
|
227
|
+
});
|
|
228
|
+
return exact ? order : undefined;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The rows after `last` in `order`, within the question's own filter: for a
|
|
232
|
+
* key (a, b) ascending, `a > x OR (a = x AND b > y)`, crossed with each of the
|
|
233
|
+
* filter's OR-groups so every group keeps all of its own conditions. Values
|
|
234
|
+
* are bound like any other condition's.
|
|
235
|
+
*/
|
|
236
|
+
function beyond(filter, order, last) {
|
|
237
|
+
const steps = order.map((o, i) => [
|
|
238
|
+
...order.slice(0, i).map((earlier) => ({
|
|
239
|
+
column: earlier.column,
|
|
240
|
+
op: '=',
|
|
241
|
+
value: last[earlier.column],
|
|
242
|
+
})),
|
|
243
|
+
{
|
|
244
|
+
column: o.column,
|
|
245
|
+
op: o.direction === 'desc' ? '<' : '>',
|
|
246
|
+
value: last[o.column],
|
|
247
|
+
},
|
|
248
|
+
]);
|
|
249
|
+
const groups = filter?.groups?.length ? filter.groups : [[]];
|
|
250
|
+
return {
|
|
251
|
+
groups: groups.flatMap((group) => steps.map((step) => [...group, ...step])),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
async function stream(res, format, table, total, read, wanted, amounts) {
|
|
255
|
+
/* The first batch is read before a byte is written: a refusal, a column
|
|
256
|
+
that does not exist, a database that is down all still answer as the
|
|
257
|
+
ordinary error they are, through the handler's own mapping. */
|
|
258
|
+
let batch = await read(0);
|
|
259
|
+
const columns = wanted ?? batch.columns;
|
|
260
|
+
const spec = FORMATS[format];
|
|
261
|
+
const encoding = acceptedEncoding(res);
|
|
262
|
+
res.writeHead(200, {
|
|
263
|
+
'content-type': `${spec.type}; charset=utf-8`,
|
|
264
|
+
'content-disposition': `attachment; filename="${table.replace(/[^\w.-]+/g, '_')}.${spec.extension}"`,
|
|
265
|
+
'cache-control': 'private, no-store',
|
|
266
|
+
'x-content-type-options': 'nosniff',
|
|
267
|
+
vary: 'Accept-Encoding',
|
|
268
|
+
...(encoding ? { 'content-encoding': encoding } : {}),
|
|
269
|
+
});
|
|
270
|
+
const out = encoding === 'br'
|
|
271
|
+
? createBrotliCompress({
|
|
272
|
+
params: {
|
|
273
|
+
[zlib.BROTLI_PARAM_QUALITY]: 4,
|
|
274
|
+
[zlib.BROTLI_PARAM_MODE]: zlib.BROTLI_MODE_TEXT,
|
|
275
|
+
},
|
|
276
|
+
})
|
|
277
|
+
: encoding === 'gzip'
|
|
278
|
+
? createGzip({ level: 6 })
|
|
279
|
+
: res;
|
|
280
|
+
if (out !== res)
|
|
281
|
+
out.pipe(res);
|
|
282
|
+
const write = (chunk) => new Promise((resolve, reject) => {
|
|
283
|
+
if (res.destroyed)
|
|
284
|
+
return reject(new Error('The export was abandoned.'));
|
|
285
|
+
if (out.write(chunk))
|
|
286
|
+
resolve();
|
|
287
|
+
else
|
|
288
|
+
out.once('drain', resolve);
|
|
289
|
+
});
|
|
290
|
+
try {
|
|
291
|
+
/* A spreadsheet opens a UTF-8 CSV without a byte-order mark in the local
|
|
292
|
+
codepage; the browser's own export writes one too (export.js). */
|
|
293
|
+
if (format === 'csv')
|
|
294
|
+
await write(`${columns.map(csvField).join(',')}${CRLF}`);
|
|
295
|
+
let written = 0;
|
|
296
|
+
for (;;) {
|
|
297
|
+
const lines = batch.rows.map((row, i) => format === 'csv'
|
|
298
|
+
? `${csvRecord(columns, amounts ? amounts(row) : row)}${CRLF}`
|
|
299
|
+
: format === 'ndjson'
|
|
300
|
+
? `${JSON.stringify(jsonRecord(columns, row))}\n`
|
|
301
|
+
: // A JSON array as export.js's toJson writes one: two-space indent, one record per element.
|
|
302
|
+
`${written + i === 0 ? '[\n' : ',\n'}${JSON.stringify(jsonRecord(columns, row), null, 2).replace(/^/gm, ' ')}`);
|
|
303
|
+
if (lines.length)
|
|
304
|
+
await write(lines.join(''));
|
|
305
|
+
written += batch.rows.length;
|
|
306
|
+
if (batch.rows.length < BATCH || written >= total)
|
|
307
|
+
break;
|
|
308
|
+
batch = await read(written);
|
|
309
|
+
}
|
|
310
|
+
if (format === 'json')
|
|
311
|
+
await write(written ? '\n]\n' : '[]\n');
|
|
312
|
+
out.end();
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
/* Past the first byte a status cannot change: the connection is cut, so
|
|
316
|
+
the browser reports a failed download rather than saving half a file
|
|
317
|
+
that looks whole. */
|
|
318
|
+
res.destroy();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
import { type FirstPaintItemKind } from '../../shared/firstPaint.js';
|
|
3
|
+
/** For tests on a busy machine: how long a page waits for its answers. */
|
|
4
|
+
export declare function setFirstPaintBudget(ms: number): void;
|
|
5
|
+
/** One route's reply, as the dispatcher answered a request the server asked itself. */
|
|
6
|
+
export interface LoopAnswer {
|
|
7
|
+
status: number;
|
|
8
|
+
body: unknown;
|
|
9
|
+
/** `x-mistri-account`: who the reply said it was for. */
|
|
10
|
+
account?: string;
|
|
11
|
+
/** Whether it may be carried: no cookie set, no header the client reads from a reply. */
|
|
12
|
+
carriable: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Ask the dispatcher one request, as this page's reader (handler.ts). */
|
|
15
|
+
export type Loop = (method: 'GET' | 'POST', target: string, body?: Record<string, unknown>, signal?: AbortSignal) => Promise<LoopAnswer | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* The request a fetch from this page would make: the page's own headers —
|
|
18
|
+
* its cookie, its proxy identity, its host — for the page's own origin, as
|
|
19
|
+
* `fetch` sends them (same-origin, JSON), and the body, if any. Enough of
|
|
20
|
+
* IncomingMessage for the gate, the auth store and the body reader.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loopbackRequest(page: IncomingMessage, method: 'GET' | 'POST', target: string, body?: Record<string, unknown>): IncomingMessage;
|
|
23
|
+
declare const BATCH_MOST: {
|
|
24
|
+
readonly '/api/breakdowns': 48;
|
|
25
|
+
readonly '/api/counts': 64;
|
|
26
|
+
};
|
|
27
|
+
/** What the page's data block holds for one address. */
|
|
28
|
+
interface FirstPaintPage {
|
|
29
|
+
json?: string;
|
|
30
|
+
}
|
|
31
|
+
/** One request a room makes, exactly as the client sends it. */
|
|
32
|
+
export interface RoomRead {
|
|
33
|
+
method: 'GET' | 'POST';
|
|
34
|
+
target: string;
|
|
35
|
+
body?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
/** Reads the client carries in a batch, asked here in one; each item is answered under its own key. */
|
|
38
|
+
export interface RoomBatch {
|
|
39
|
+
path: keyof typeof BATCH_MOST;
|
|
40
|
+
kind: FirstPaintItemKind;
|
|
41
|
+
/** What the batch carries beside its items (`countLimit`). */
|
|
42
|
+
body?: Record<string, unknown>;
|
|
43
|
+
/** Each item: the key it is answered under, what the batch sends for it, and its kind where not the batch's (a list's rows among breakdowns). */
|
|
44
|
+
items: Array<{
|
|
45
|
+
key: unknown;
|
|
46
|
+
sent: unknown;
|
|
47
|
+
kind?: FirstPaintItemKind;
|
|
48
|
+
}>;
|
|
49
|
+
/** A batch result as the client takes it for one item, or undefined for none. */
|
|
50
|
+
unwrap?: (result: unknown) => unknown;
|
|
51
|
+
}
|
|
52
|
+
/** What a room asks first: its reads, and its batches. */
|
|
53
|
+
export interface RoomPlan {
|
|
54
|
+
reads: RoomRead[];
|
|
55
|
+
batches: RoomBatch[];
|
|
56
|
+
}
|
|
57
|
+
/** Ask one request as the page's reader, and carry its answer where it may be carried; the answer, or none. */
|
|
58
|
+
type PaintAsk = (method: 'GET' | 'POST', target: string, body?: Record<string, unknown>) => Promise<unknown>;
|
|
59
|
+
/**
|
|
60
|
+
* What a product's first page asks past who-am-I and the runtime: an App's
|
|
61
|
+
* public pages, its App and its first room (the App framework's
|
|
62
|
+
* firstPaintRooms.ts). Without one — the database browser — a page carries
|
|
63
|
+
* who-am-I and the runtime, and its rooms ask for the rest.
|
|
64
|
+
*/
|
|
65
|
+
export interface PaintRooms {
|
|
66
|
+
/** The reads of a page that is all its own reads (an App's public form, its landing), asked before who-am-I; none for any other. */
|
|
67
|
+
alone(path: string): readonly RoomRead[] | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Once who-am-I and the runtime have answered: what the shell asks next,
|
|
70
|
+
* through `ask`, and then the App the page is for and its room's plan, or
|
|
71
|
+
* none where the page draws no room of an App.
|
|
72
|
+
*/
|
|
73
|
+
room(page: {
|
|
74
|
+
path: string;
|
|
75
|
+
search: string;
|
|
76
|
+
/** The page's first segment, decoded: the App its address names, where it names one. */
|
|
77
|
+
requested: string | null;
|
|
78
|
+
me: Record<string, unknown>;
|
|
79
|
+
runtime: Record<string, unknown>;
|
|
80
|
+
ask: PaintAsk;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
app: string;
|
|
83
|
+
plan: RoomPlan;
|
|
84
|
+
} | undefined>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The answers for the page at `path` (its inside form, shared/mount.ts)
|
|
88
|
+
* with `search`: what boot.js asks, in its order, and then what the first
|
|
89
|
+
* room asks (`rooms`, an App's: firstPaintRooms.ts). Each round's requests
|
|
90
|
+
* are asked together.
|
|
91
|
+
*/
|
|
92
|
+
export declare function firstPaint({ path, search, loop: asked, most, budget, rooms, }: {
|
|
93
|
+
path: string;
|
|
94
|
+
search: string;
|
|
95
|
+
loop: Loop;
|
|
96
|
+
most?: number;
|
|
97
|
+
budget?: number;
|
|
98
|
+
/** What the product's page asks past who-am-I and the runtime (PaintRooms), or nothing more. */
|
|
99
|
+
rooms?: PaintRooms;
|
|
100
|
+
}): Promise<FirstPaintPage>;
|
|
101
|
+
/**
|
|
102
|
+
* The data block, as the page carries it: JSON with every `<`, `>` and `&`
|
|
103
|
+
* written as its escape, and the two line separators JavaScript once took
|
|
104
|
+
* for line ends, so no value — a row's text is anybody's — can close the
|
|
105
|
+
* script element, open a comment inside it, or be read as markup.
|
|
106
|
+
*/
|
|
107
|
+
export declare function firstPaintBlock(id: string, json: string): string;
|
|
108
|
+
export {};
|