@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,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL introspection: the catalog queries that describe a database, and
|
|
3
|
+
* the one reading of the rows they return.
|
|
4
|
+
*
|
|
5
|
+
* It sits apart from the adapter because describing a database is a different
|
|
6
|
+
* job from connecting to one, querying it or writing to it — and because it is
|
|
7
|
+
* the half that carries an invariant of its own. Every query here has an
|
|
8
|
+
* explicit ORDER BY: the catalog promises no order, so without them the same
|
|
9
|
+
* server may hand back a table's two foreign keys either way round, its
|
|
10
|
+
* indexed columns in any order and its checks in any order, and a description
|
|
11
|
+
* taken twice then differs with nothing changed underneath it. The ordering is
|
|
12
|
+
* the point of this module rather than decoration, and `test/postgres.test.ts`
|
|
13
|
+
* ("two reads of one database describe it identically") is what holds it.
|
|
14
|
+
*
|
|
15
|
+
* Where SQLite hands you a per-table PRAGMA, Postgres hands you a catalog you
|
|
16
|
+
* can query in one shot. That difference is worth exploiting: introspection
|
|
17
|
+
* here is a fixed handful of queries regardless of how many tables exist, which
|
|
18
|
+
* matters the first time someone points this at a schema with four hundred of
|
|
19
|
+
* them.
|
|
20
|
+
*
|
|
21
|
+
* The queries below read `information_schema` for columns and `pg_catalog` for
|
|
22
|
+
* keys, checks and row estimates. `information_schema` is the portable half but
|
|
23
|
+
* it has no cheap row count and describes composite keys awkwardly;
|
|
24
|
+
* `pg_catalog` carries both, at the cost of being Postgres-specific. Since we
|
|
25
|
+
* are already inside the Postgres adapter, that cost is zero.
|
|
26
|
+
*/
|
|
27
|
+
import { type DatabaseSchema } from '../shared/schema.js';
|
|
28
|
+
import type { EpochCache } from './epochCache.js';
|
|
29
|
+
import type { PgQuery } from './postgresPool.js';
|
|
30
|
+
import { type SqlStyle } from '../shared/filter.js';
|
|
31
|
+
/** The style row-scoped reads compile with on this server: POSTGRES_INLINE_STYLE
|
|
32
|
+
* from 12, where `AS NOT MATERIALIZED` exists; before it, every CTE is
|
|
33
|
+
* materialized anyway and the words would be a syntax error. */
|
|
34
|
+
export declare function postgresScopeStyle(db: PgQuery): Promise<SqlStyle>;
|
|
35
|
+
/** Schemas that are the server's own business, not the user's data. */
|
|
36
|
+
export declare const SYSTEM_SCHEMAS: string[];
|
|
37
|
+
/**
|
|
38
|
+
* A relation that belongs to an extension is the extension's, not the App's:
|
|
39
|
+
* PlanetScale preinstalls hypopg (its views, in `pscale_extensions`) in every
|
|
40
|
+
* database and PostGIS brings `spatial_ref_sys` to Neon and Supabase, none of
|
|
41
|
+
* which the App declared and a tenant policy can name no owner for. Extension
|
|
42
|
+
* membership is a `pg_depend` row with `deptype = 'e'` on `pg_extension`; the
|
|
43
|
+
* description and the catalog digest both leave such relations out, so they
|
|
44
|
+
* agree. `alias` is the `pg_class` row's alias in the caller's query.
|
|
45
|
+
*/
|
|
46
|
+
export declare function notExtensionMember(alias: string): string;
|
|
47
|
+
/** The adapter as its own description names it: the schemas it was pointed at,
|
|
48
|
+
* and what it calls itself. Passed per description rather than captured, so the
|
|
49
|
+
* leased writer inside a scoped transaction describes the same reach as the
|
|
50
|
+
* reader does on connect. */
|
|
51
|
+
interface CatalogSource {
|
|
52
|
+
readonly schemas: readonly string[];
|
|
53
|
+
readonly label: string;
|
|
54
|
+
readonly dialect: 'postgres';
|
|
55
|
+
}
|
|
56
|
+
export declare function describePostgresCatalog(db: PgQuery, source: CatalogSource): Promise<DatabaseSchema>;
|
|
57
|
+
/** Where a table is, and whether writing to it makes sense. */
|
|
58
|
+
export interface Located {
|
|
59
|
+
kind: string;
|
|
60
|
+
schema: string;
|
|
61
|
+
name: string;
|
|
62
|
+
isView: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** One column, as the write path needs it: name, type, null-ness, key-ness. */
|
|
65
|
+
export interface PgColumnRow {
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
notnull: boolean;
|
|
69
|
+
is_pk: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The write path, on its own handle.
|
|
73
|
+
*
|
|
74
|
+
* Every reader carries `default_transaction_read_only = on`. A separate
|
|
75
|
+
* writer pool is opened on the first edit: a connection that can write
|
|
76
|
+
* should exist because somebody wrote, not because somebody connected.
|
|
77
|
+
*
|
|
78
|
+
* Every guard below is the SQLite adapter's, one for one. An edit refused on
|
|
79
|
+
* SQLite and allowed on Postgres would mean the safety of a cell editor
|
|
80
|
+
* depended on which database it was pointed at.
|
|
81
|
+
*
|
|
82
|
+
* A table's columns as the catalog has them now, not as they were on connect.
|
|
83
|
+
*
|
|
84
|
+
* `information_schema` would do for the names and types, but not for the
|
|
85
|
+
* primary key — it describes a composite one across two more views — and
|
|
86
|
+
* the key is the whole safety argument for a write. `pg_catalog` answers
|
|
87
|
+
* both in one query, and this is the Postgres adapter, so being
|
|
88
|
+
* Postgres-specific costs nothing.
|
|
89
|
+
*
|
|
90
|
+
* Read per write rather than from the cached schema: a column added since
|
|
91
|
+
* the connection opened is a column the editor should be able to write, and
|
|
92
|
+
* one dropped since is one it must not.
|
|
93
|
+
*/
|
|
94
|
+
export declare function postgresColumnsOf(schema: string, name: string, db: PgQuery | undefined, epoch: string | undefined, cache: EpochCache<unknown>, connect: () => Promise<PgQuery>): Promise<PgColumnRow[]>;
|
|
95
|
+
export declare function assertPostgresTable(id: string, db: PgQuery | undefined, epoch: string | undefined, cache: EpochCache<unknown>, connect: () => Promise<PgQuery>): Promise<Located>;
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL introspection: the catalog queries that describe a database, and
|
|
3
|
+
* the one reading of the rows they return.
|
|
4
|
+
*
|
|
5
|
+
* It sits apart from the adapter because describing a database is a different
|
|
6
|
+
* job from connecting to one, querying it or writing to it — and because it is
|
|
7
|
+
* the half that carries an invariant of its own. Every query here has an
|
|
8
|
+
* explicit ORDER BY: the catalog promises no order, so without them the same
|
|
9
|
+
* server may hand back a table's two foreign keys either way round, its
|
|
10
|
+
* indexed columns in any order and its checks in any order, and a description
|
|
11
|
+
* taken twice then differs with nothing changed underneath it. The ordering is
|
|
12
|
+
* the point of this module rather than decoration, and `test/postgres.test.ts`
|
|
13
|
+
* ("two reads of one database describe it identically") is what holds it.
|
|
14
|
+
*
|
|
15
|
+
* Where SQLite hands you a per-table PRAGMA, Postgres hands you a catalog you
|
|
16
|
+
* can query in one shot. That difference is worth exploiting: introspection
|
|
17
|
+
* here is a fixed handful of queries regardless of how many tables exist, which
|
|
18
|
+
* matters the first time someone points this at a schema with four hundred of
|
|
19
|
+
* them.
|
|
20
|
+
*
|
|
21
|
+
* The queries below read `information_schema` for columns and `pg_catalog` for
|
|
22
|
+
* keys, checks and row estimates. `information_schema` is the portable half but
|
|
23
|
+
* it has no cheap row count and describes composite keys awkwardly;
|
|
24
|
+
* `pg_catalog` carries both, at the cost of being Postgres-specific. Since we
|
|
25
|
+
* are already inside the Postgres adapter, that cost is zero.
|
|
26
|
+
*/
|
|
27
|
+
import { chooseColumnReference, columnKind, deleteRuleOf, } from '../shared/schema.js';
|
|
28
|
+
import { checkFlag, checksIn } from '../shared/vocabulary.js';
|
|
29
|
+
import { catalogTextRule } from '../shared/textRules.js';
|
|
30
|
+
import { checkedText, firstVocabulary, postgresRowEstimate, } from './postgresCatalogRows.js';
|
|
31
|
+
import { Refusal } from './adapter.js';
|
|
32
|
+
import { RESERVED_SCHEMAS } from './reservedSql.js';
|
|
33
|
+
import { POSTGRES_INLINE_STYLE, POSTGRES_STYLE } from '../shared/filter.js';
|
|
34
|
+
/** The style row-scoped reads compile with on this server: POSTGRES_INLINE_STYLE
|
|
35
|
+
* from 12, where `AS NOT MATERIALIZED` exists; before it, every CTE is
|
|
36
|
+
* materialized anyway and the words would be a syntax error. */
|
|
37
|
+
export async function postgresScopeStyle(db) {
|
|
38
|
+
const result = await db.query(`SELECT current_setting('server_version_num')::int AS version`);
|
|
39
|
+
return Number(result.rows[0]?.version) >= 120_000 ? POSTGRES_INLINE_STYLE : POSTGRES_STYLE;
|
|
40
|
+
}
|
|
41
|
+
/** Schemas that are the server's own business, not the user's data. */
|
|
42
|
+
export const SYSTEM_SCHEMAS = ['pg_catalog', 'information_schema', 'pg_toast'];
|
|
43
|
+
/**
|
|
44
|
+
* A relation that belongs to an extension is the extension's, not the App's:
|
|
45
|
+
* PlanetScale preinstalls hypopg (its views, in `pscale_extensions`) in every
|
|
46
|
+
* database and PostGIS brings `spatial_ref_sys` to Neon and Supabase, none of
|
|
47
|
+
* which the App declared and a tenant policy can name no owner for. Extension
|
|
48
|
+
* membership is a `pg_depend` row with `deptype = 'e'` on `pg_extension`; the
|
|
49
|
+
* description and the catalog digest both leave such relations out, so they
|
|
50
|
+
* agree. `alias` is the `pg_class` row's alias in the caller's query.
|
|
51
|
+
*/
|
|
52
|
+
export function notExtensionMember(alias) {
|
|
53
|
+
return `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend ext
|
|
54
|
+
WHERE ext.classid = 'pg_catalog.pg_class'::regclass AND ext.objid = ${alias}.oid
|
|
55
|
+
AND ext.refclassid = 'pg_catalog.pg_extension'::regclass AND ext.deptype = 'e')`;
|
|
56
|
+
}
|
|
57
|
+
export async function describePostgresCatalog(db, source) {
|
|
58
|
+
const filterSchemas = source.schemas.length ? `AND n.nspname = ANY($1)` : `AND n.nspname <> ALL($1)`;
|
|
59
|
+
const schemaParam = source.schemas.length
|
|
60
|
+
? source.schemas.filter((schema) => !RESERVED_SCHEMAS.includes(schema))
|
|
61
|
+
: [...SYSTEM_SCHEMAS, ...RESERVED_SCHEMAS];
|
|
62
|
+
/* 1. Relations, with the planner's row estimate.
|
|
63
|
+
`reltuples` is an estimate, not a count, and is labelled as such in
|
|
64
|
+
the UI. An exact count on a large table is a sequential scan, which
|
|
65
|
+
is a strange thing for a schema browser to do on connect. */
|
|
66
|
+
const rels = await db.query(`SELECT n.nspname AS table_schema,
|
|
67
|
+
c.relname AS table_name,
|
|
68
|
+
c.relkind AS kind,
|
|
69
|
+
CASE WHEN c.reltuples < 0 THEN NULL ELSE c.reltuples END AS approx_rows,
|
|
70
|
+
obj_description(c.oid) AS comment
|
|
71
|
+
FROM pg_class c
|
|
72
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
73
|
+
WHERE c.relkind IN ('r','v','m','p','f')
|
|
74
|
+
AND ${notExtensionMember('c')}
|
|
75
|
+
${filterSchemas}
|
|
76
|
+
/* Temporary tables belong to one session. Another session's show
|
|
77
|
+
in pg_class but not in information_schema, so they would arrive
|
|
78
|
+
with no columns, and none of them is anything to browse. */
|
|
79
|
+
AND n.nspname !~ '^pg_(toast_)?temp_'
|
|
80
|
+
ORDER BY n.nspname, c.relname`, [schemaParam]);
|
|
81
|
+
const relRows = rels.rows;
|
|
82
|
+
const wanted = new Set(relRows.map((r) => `${r.table_schema}.${r.table_name}`));
|
|
83
|
+
/* 2. Columns, in one pass over information_schema. */
|
|
84
|
+
const cols = await db.query(
|
|
85
|
+
/* `col_description` joined on rather than left out.
|
|
86
|
+
|
|
87
|
+
A column comment is the table's own documentation — the one place a
|
|
88
|
+
schema explains itself — and SQLite has none to read. It lives in `pg_description` rather
|
|
89
|
+
than `information_schema`, which is why it needs the join. */
|
|
90
|
+
`SELECT c.table_schema, c.table_name, c.column_name, c.data_type,
|
|
91
|
+
c.is_nullable, c.column_default, c.ordinal_position, c.is_identity, c.identity_generation, c.is_generated,
|
|
92
|
+
c.character_maximum_length,
|
|
93
|
+
col_description(pc.oid, c.ordinal_position::int) AS comment,
|
|
94
|
+
/* Cast to text before aggregating: enumlabel has type "name",
|
|
95
|
+
and the driver hands a name[] back as the literal string
|
|
96
|
+
'{open,held,closed}' rather than an array — the same value,
|
|
97
|
+
typed as something no caller can use. */
|
|
98
|
+
(SELECT array_agg(e.enumlabel::text ORDER BY e.enumsortorder)
|
|
99
|
+
FROM pg_enum e
|
|
100
|
+
JOIN pg_type t ON t.oid = e.enumtypid
|
|
101
|
+
JOIN pg_namespace tn ON tn.oid = t.typnamespace
|
|
102
|
+
WHERE t.typname = c.udt_name AND tn.nspname = c.udt_schema) AS enum_labels
|
|
103
|
+
FROM information_schema.columns c
|
|
104
|
+
LEFT JOIN pg_namespace pn ON pn.nspname = c.table_schema
|
|
105
|
+
LEFT JOIN pg_class pc ON pc.relname = c.table_name AND pc.relnamespace = pn.oid
|
|
106
|
+
WHERE c.table_schema ${source.schemas.length ? '= ANY($1)' : '<> ALL($1)'}
|
|
107
|
+
ORDER BY c.table_schema, c.table_name, c.ordinal_position`, [schemaParam]);
|
|
108
|
+
/* Checks, for the other half of the vocabulary. A `status text CHECK
|
|
109
|
+
(status IN (...))` is far commoner in the wild than a real enum type,
|
|
110
|
+
and to anything reading the catalog it is an untyped text column unless
|
|
111
|
+
the constraint is read too. Postgres stores what it rewrote rather than
|
|
112
|
+
what was written, which `checkVocabulary` knows about. */
|
|
113
|
+
const checks = await db.query(`SELECT n.nspname AS table_schema, cl.relname AS table_name,
|
|
114
|
+
pg_get_constraintdef(co.oid) AS expression
|
|
115
|
+
FROM pg_constraint co
|
|
116
|
+
JOIN pg_class cl ON cl.oid = co.conrelid
|
|
117
|
+
JOIN pg_namespace n ON n.oid = cl.relnamespace
|
|
118
|
+
WHERE co.contype = 'c'
|
|
119
|
+
AND n.nspname ${source.schemas.length ? '= ANY($1)' : '<> ALL($1)'}
|
|
120
|
+
ORDER BY n.nspname, cl.relname, co.conname`, [schemaParam]);
|
|
121
|
+
const checksByTable = new Map();
|
|
122
|
+
for (const row of checks.rows) {
|
|
123
|
+
const id = `${row.table_schema}.${row.table_name}`;
|
|
124
|
+
const list = checksByTable.get(id) ?? [];
|
|
125
|
+
/* `pg_get_constraintdef` returns `CHECK ((expr))`; the parser wants the
|
|
126
|
+
expression, and `checksIn` is the same unwrapping SQLite needs. */
|
|
127
|
+
list.push(...checksIn(row.expression));
|
|
128
|
+
checksByTable.set(id, list);
|
|
129
|
+
}
|
|
130
|
+
/* 3. Keys. `unnest ... WITH ORDINALITY` keeps composite key columns in
|
|
131
|
+
their declared order, which a plain array_agg over conkey would not
|
|
132
|
+
guarantee and which matters for a two-column join.
|
|
133
|
+
|
|
134
|
+
`attname` is of type `name`, not `text`, so aggregating it yields
|
|
135
|
+
`name[]` — an array OID the driver has no parser for, which arrives
|
|
136
|
+
as the raw string "{a,b}" rather than an array. The ::text casts are
|
|
137
|
+
what make these come back as JavaScript arrays. */
|
|
138
|
+
const keys = await db.query(`SELECT con.conname AS constraint_name,
|
|
139
|
+
fn.nspname AS from_schema,
|
|
140
|
+
f.relname AS from_table,
|
|
141
|
+
(SELECT array_agg(a.attname::text ORDER BY k.ord)
|
|
142
|
+
FROM unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord)
|
|
143
|
+
JOIN pg_attribute a ON a.attrelid = f.oid AND a.attnum = k.attnum) AS from_columns,
|
|
144
|
+
tn.nspname AS to_schema,
|
|
145
|
+
t.relname AS to_table,
|
|
146
|
+
(SELECT array_agg(a.attname::text ORDER BY k.ord)
|
|
147
|
+
FROM unnest(con.confkey) WITH ORDINALITY AS k(attnum, ord)
|
|
148
|
+
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum) AS to_columns,
|
|
149
|
+
con.confdeltype AS delete_rule
|
|
150
|
+
FROM pg_constraint con
|
|
151
|
+
JOIN pg_class f ON f.oid = con.conrelid
|
|
152
|
+
JOIN pg_namespace fn ON fn.oid = f.relnamespace
|
|
153
|
+
JOIN pg_class t ON t.oid = con.confrelid
|
|
154
|
+
JOIN pg_namespace tn ON tn.oid = t.relnamespace
|
|
155
|
+
WHERE con.contype = 'f'
|
|
156
|
+
ORDER BY fn.nspname, f.relname, con.conname`);
|
|
157
|
+
const pks = await db.query(`SELECT n.nspname AS table_schema,
|
|
158
|
+
c.relname AS table_name,
|
|
159
|
+
(SELECT array_agg(a.attname::text ORDER BY k.ord)
|
|
160
|
+
FROM unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord)
|
|
161
|
+
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = k.attnum) AS columns
|
|
162
|
+
FROM pg_constraint con
|
|
163
|
+
JOIN pg_class c ON c.oid = con.conrelid
|
|
164
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
165
|
+
WHERE con.contype = 'p'
|
|
166
|
+
ORDER BY n.nspname, c.relname, con.conname`);
|
|
167
|
+
const pkByTable = new Map();
|
|
168
|
+
for (const row of pks.rows) {
|
|
169
|
+
pkByTable.set(`${row.table_schema}.${row.table_name}`, row.columns ?? []);
|
|
170
|
+
}
|
|
171
|
+
/* Only the leading column of each index.
|
|
172
|
+
|
|
173
|
+
`indkey[0]` is the first key column, and it is the only one an ORDER BY
|
|
174
|
+
can be satisfied by — an index on (customer_id, opened_at) makes
|
|
175
|
+
`ORDER BY customer_id` free and `ORDER BY opened_at` a full sort. An
|
|
176
|
+
expression index has attnum 0 and joins to nothing, which drops it, as
|
|
177
|
+
it should: there is no bare column to sort by. */
|
|
178
|
+
const indexes = await db.query(`SELECT n.nspname AS table_schema,
|
|
179
|
+
c.relname AS table_name,
|
|
180
|
+
a.attname::text AS column_name,
|
|
181
|
+
-- Unique by itself (an App's natural-key address): one column, the whole table, no expression.
|
|
182
|
+
(i.indisunique AND i.indnatts = 1 AND i.indpred IS NULL AND i.indexprs IS NULL) AS sole_unique,
|
|
183
|
+
-- Unique as a pair (a natural key within a tenant): two key columns and nothing included.
|
|
184
|
+
CASE WHEN i.indisunique AND i.indnatts = 2 AND i.indpred IS NULL AND i.indexprs IS NULL THEN
|
|
185
|
+
(SELECT array_agg(pa.attname::text ORDER BY k.ord)
|
|
186
|
+
FROM unnest(i.indkey::int2[]) WITH ORDINALITY AS k(attnum, ord)
|
|
187
|
+
JOIN pg_attribute pa ON pa.attrelid = c.oid AND pa.attnum = k.attnum) END AS unique_pair,
|
|
188
|
+
-- The key columns a pg_trgm operator class indexes, at any position: what
|
|
189
|
+
-- serves a contains (ILIKE '%x%') search, which a B-tree never does.
|
|
190
|
+
(SELECT coalesce(array_agg(ta.attname::text), '{}')
|
|
191
|
+
FROM unnest(i.indkey::int2[], i.indclass::oid[]) AS k(attnum, opclass)
|
|
192
|
+
JOIN pg_opclass oc ON oc.oid = k.opclass
|
|
193
|
+
JOIN pg_attribute ta ON ta.attrelid = c.oid AND ta.attnum = k.attnum
|
|
194
|
+
WHERE oc.opcname IN ('gin_trgm_ops', 'gist_trgm_ops')) AS trigram_columns
|
|
195
|
+
FROM pg_index i
|
|
196
|
+
JOIN pg_class c ON c.oid = i.indrelid
|
|
197
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
198
|
+
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = i.indkey[0]
|
|
199
|
+
WHERE i.indisvalid
|
|
200
|
+
ORDER BY n.nspname, c.relname, a.attname`);
|
|
201
|
+
const indexedByTable = new Map();
|
|
202
|
+
const uniqueByTable = new Map();
|
|
203
|
+
const pairsByTable = new Map();
|
|
204
|
+
const trigramByTable = new Map();
|
|
205
|
+
for (const row of indexes.rows) {
|
|
206
|
+
const id = `${row.table_schema}.${row.table_name}`;
|
|
207
|
+
const set = indexedByTable.get(id) ?? new Set();
|
|
208
|
+
set.add(row.column_name);
|
|
209
|
+
indexedByTable.set(id, set);
|
|
210
|
+
if (row.sole_unique)
|
|
211
|
+
uniqueByTable.set(id, (uniqueByTable.get(id) ?? new Set()).add(row.column_name));
|
|
212
|
+
if (row.unique_pair?.length === 2)
|
|
213
|
+
pairsByTable.set(id, [...(pairsByTable.get(id) ?? []), [row.unique_pair[0], row.unique_pair[1]]]);
|
|
214
|
+
for (const column of row.trigram_columns ?? [])
|
|
215
|
+
trigramByTable.set(id, (trigramByTable.get(id) ?? new Set()).add(column));
|
|
216
|
+
}
|
|
217
|
+
const foreignKeys = [];
|
|
218
|
+
/* A column-level reference map, so the table view can show "this column
|
|
219
|
+
points there" without searching the whole key list per cell. A column
|
|
220
|
+
can sit in several keys — a tenant table's ownership column carries its
|
|
221
|
+
own reference to the tenancy profile and its part in each composite
|
|
222
|
+
tenant key — so every candidate is gathered and the link a reader
|
|
223
|
+
follows is chosen by the one shared rule the SQLite catalog applies. */
|
|
224
|
+
const refCandidates = new Map();
|
|
225
|
+
for (const row of keys.rows) {
|
|
226
|
+
const from = `${row.from_schema}.${row.from_table}`;
|
|
227
|
+
const to = `${row.to_schema}.${row.to_table}`;
|
|
228
|
+
// Keys can point out of the browsed schema set; those edges lead
|
|
229
|
+
// nowhere the user can click, so they are dropped rather than shown broken.
|
|
230
|
+
if (!wanted.has(from) || !wanted.has(to))
|
|
231
|
+
continue;
|
|
232
|
+
foreignKeys.push({
|
|
233
|
+
name: row.constraint_name,
|
|
234
|
+
from: { table: from, columns: row.from_columns ?? [] },
|
|
235
|
+
to: { table: to, columns: row.to_columns ?? [] },
|
|
236
|
+
onDelete: deleteRuleOf(row.delete_rule),
|
|
237
|
+
});
|
|
238
|
+
(row.from_columns ?? []).forEach((col, i) => {
|
|
239
|
+
const at = `${from}.${col}`;
|
|
240
|
+
const listed = refCandidates.get(at) ?? [];
|
|
241
|
+
listed.push({
|
|
242
|
+
reference: { table: to, column: row.to_columns?.[i] ?? row.to_columns?.[0] ?? '' },
|
|
243
|
+
composite: (row.from_columns ?? []).length > 1,
|
|
244
|
+
});
|
|
245
|
+
refCandidates.set(at, listed);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
const refByColumn = new Map();
|
|
249
|
+
for (const [at, listed] of refCandidates) {
|
|
250
|
+
/* Describing a database this tool did not design: a column whose keys
|
|
251
|
+
name no single link simply shows none. The scoped catalogs, which
|
|
252
|
+
attest a write boundary, are the ones that refuse a contradiction. */
|
|
253
|
+
const chosen = chooseColumnReference(listed);
|
|
254
|
+
if (chosen.kind === 'one')
|
|
255
|
+
refByColumn.set(at, chosen.reference);
|
|
256
|
+
}
|
|
257
|
+
const columnsByTable = new Map();
|
|
258
|
+
for (const row of cols.rows) {
|
|
259
|
+
const id = `${row.table_schema}.${row.table_name}`;
|
|
260
|
+
if (!wanted.has(id))
|
|
261
|
+
continue;
|
|
262
|
+
const list = columnsByTable.get(id) ?? [];
|
|
263
|
+
list.push(row);
|
|
264
|
+
columnsByTable.set(id, list);
|
|
265
|
+
}
|
|
266
|
+
const tables = relRows.map((r) => {
|
|
267
|
+
const id = `${r.table_schema}.${r.table_name}`;
|
|
268
|
+
const pk = new Set(pkByTable.get(id) ?? []);
|
|
269
|
+
const tableChecks = checksByTable.get(id) ?? [];
|
|
270
|
+
const columns = (columnsByTable.get(id) ?? []).map((c) => ({
|
|
271
|
+
name: c.column_name,
|
|
272
|
+
type: c.data_type,
|
|
273
|
+
nullable: c.is_nullable === 'YES',
|
|
274
|
+
primaryKey: pk.has(c.column_name),
|
|
275
|
+
references: refByColumn.get(`${id}.${c.column_name}`),
|
|
276
|
+
default: c.column_default ?? undefined,
|
|
277
|
+
identity: c.is_identity === 'YES' ? (c.identity_generation === 'ALWAYS' ? 'always' : 'by-default') : undefined,
|
|
278
|
+
comment: c.comment ?? undefined,
|
|
279
|
+
// The database computes a generated column; nothing may write it (as sqlite.ts says of its own).
|
|
280
|
+
...(c.is_generated === 'ALWAYS' ? { writable: false } : {}),
|
|
281
|
+
/* The type wins where there is one: an enum's labels are the whole
|
|
282
|
+
truth, while a check is one rule among however many the table has. */
|
|
283
|
+
allowed: c.enum_labels?.length ? c.enum_labels : firstVocabulary(tableChecks, c.column_name),
|
|
284
|
+
/* An integer a check pins to 0 and 1 reads as the boolean it stands for. */
|
|
285
|
+
...(columnKind(c.data_type) === 'number' && tableChecks.some((check) => checkFlag(check, c.column_name))
|
|
286
|
+
? { flag: true }
|
|
287
|
+
: {}),
|
|
288
|
+
/* A text column's length and form, where the type and the checks say them: a form checks them as someone types. */
|
|
289
|
+
...(() => {
|
|
290
|
+
if (columnKind(c.data_type) !== 'text' || c.enum_labels?.length)
|
|
291
|
+
return {};
|
|
292
|
+
const text = catalogTextRule({
|
|
293
|
+
max: c.character_maximum_length === null ? null : Number(c.character_maximum_length),
|
|
294
|
+
...checkedText(tableChecks, c.column_name),
|
|
295
|
+
});
|
|
296
|
+
return text ? { text } : {};
|
|
297
|
+
})(),
|
|
298
|
+
}));
|
|
299
|
+
return {
|
|
300
|
+
name: r.table_name,
|
|
301
|
+
schema: r.table_schema,
|
|
302
|
+
id,
|
|
303
|
+
columns,
|
|
304
|
+
approxRows: postgresRowEstimate(r.approx_rows),
|
|
305
|
+
comment: r.comment ?? undefined,
|
|
306
|
+
// Views and materialised views are read-only; foreign tables are
|
|
307
|
+
// remote. All three are worth flagging rather than silently listing.
|
|
308
|
+
isView: r.kind === 'v' || r.kind === 'm' || r.kind === 'f',
|
|
309
|
+
indexed: [...(indexedByTable.get(id) ?? [])],
|
|
310
|
+
trigram: [...(trigramByTable.get(id) ?? [])],
|
|
311
|
+
...(uniqueByTable.get(id)?.size ? { unique: [...uniqueByTable.get(id)] } : {}),
|
|
312
|
+
...(pairsByTable.get(id)?.length ? { uniquePairs: pairsByTable.get(id) } : {}),
|
|
313
|
+
};
|
|
314
|
+
});
|
|
315
|
+
return {
|
|
316
|
+
label: source.label,
|
|
317
|
+
dialect: source.dialect,
|
|
318
|
+
tables,
|
|
319
|
+
foreignKeys,
|
|
320
|
+
readAt: new Date().toISOString(),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The write path, on its own handle.
|
|
325
|
+
*
|
|
326
|
+
* Every reader carries `default_transaction_read_only = on`. A separate
|
|
327
|
+
* writer pool is opened on the first edit: a connection that can write
|
|
328
|
+
* should exist because somebody wrote, not because somebody connected.
|
|
329
|
+
*
|
|
330
|
+
* Every guard below is the SQLite adapter's, one for one. An edit refused on
|
|
331
|
+
* SQLite and allowed on Postgres would mean the safety of a cell editor
|
|
332
|
+
* depended on which database it was pointed at.
|
|
333
|
+
*
|
|
334
|
+
* A table's columns as the catalog has them now, not as they were on connect.
|
|
335
|
+
*
|
|
336
|
+
* `information_schema` would do for the names and types, but not for the
|
|
337
|
+
* primary key — it describes a composite one across two more views — and
|
|
338
|
+
* the key is the whole safety argument for a write. `pg_catalog` answers
|
|
339
|
+
* both in one query, and this is the Postgres adapter, so being
|
|
340
|
+
* Postgres-specific costs nothing.
|
|
341
|
+
*
|
|
342
|
+
* Read per write rather than from the cached schema: a column added since
|
|
343
|
+
* the connection opened is a column the editor should be able to write, and
|
|
344
|
+
* one dropped since is one it must not.
|
|
345
|
+
*/
|
|
346
|
+
export async function postgresColumnsOf(schema, name, db, epoch, cache, connect) {
|
|
347
|
+
const kept = cache.get(epoch, `columns:${schema}.${name}`);
|
|
348
|
+
if (kept)
|
|
349
|
+
return kept;
|
|
350
|
+
db ??= await connect();
|
|
351
|
+
const result = await db.query(`SELECT a.attname AS name,
|
|
352
|
+
format_type(a.atttypid, a.atttypmod) AS type,
|
|
353
|
+
a.attnotnull AS notnull,
|
|
354
|
+
COALESCE(k.is_pk, false) AS is_pk
|
|
355
|
+
FROM pg_attribute a
|
|
356
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
357
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
358
|
+
LEFT JOIN LATERAL (
|
|
359
|
+
SELECT true AS is_pk FROM pg_index i
|
|
360
|
+
WHERE i.indrelid = c.oid AND i.indisprimary AND a.attnum = ANY (i.indkey)
|
|
361
|
+
) k ON true
|
|
362
|
+
WHERE n.nspname = $1 AND c.relname = $2
|
|
363
|
+
AND a.attnum > 0 AND NOT a.attisdropped
|
|
364
|
+
ORDER BY a.attnum`, [schema, name]);
|
|
365
|
+
return cache.set(epoch, `columns:${schema}.${name}`, result.rows);
|
|
366
|
+
}
|
|
367
|
+
export async function assertPostgresTable(id, db, epoch, cache, connect) {
|
|
368
|
+
const dot = id.indexOf('.');
|
|
369
|
+
const schema = dot === -1 ? 'public' : id.slice(0, dot);
|
|
370
|
+
const name = dot === -1 ? id : id.slice(dot + 1);
|
|
371
|
+
if (RESERVED_SCHEMAS.includes(schema))
|
|
372
|
+
throw new Refusal('Reserved resources are runtime-only.');
|
|
373
|
+
const kept = cache.get(epoch, `table:${id}`);
|
|
374
|
+
if (kept)
|
|
375
|
+
return kept;
|
|
376
|
+
db ??= await connect();
|
|
377
|
+
const found = await db.query(`SELECT c.relkind AS kind FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
378
|
+
WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind IN ('r','v','m','p','f')`, [schema, name]);
|
|
379
|
+
if (!found.rows.length)
|
|
380
|
+
throw new Error(`No table or view called "${id}" in this database.`);
|
|
381
|
+
/* `v` is a view and `m` a materialised one. Both are read-only as far as
|
|
382
|
+
the write path is concerned — the relkind is asked for here rather than
|
|
383
|
+
re-derived from the cached schema, so a view created since the
|
|
384
|
+
connection opened is still recognised as one. */
|
|
385
|
+
const kind = String(found.rows[0]?.kind ?? 'r');
|
|
386
|
+
return cache.set(epoch, `table:${id}`, { schema, name, kind, isView: kind === 'v' || kind === 'm' });
|
|
387
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One statement that changes whenever anything a full attestation reads
|
|
3
|
+
* changes: the `(oid, xmin)` of every catalog row the whole-catalog
|
|
4
|
+
* description, the pinned relation description and the store attestation
|
|
5
|
+
* depend on, over the same schemas, plus role membership and attributes and
|
|
6
|
+
* the store's meta row. Transactional DDL inserts, updates or deletes those
|
|
7
|
+
* rows, and a changed or removed row changes the digest. What does not change
|
|
8
|
+
* it is what attests nothing: VACUUM and ANALYZE update `pg_class` in place,
|
|
9
|
+
* and comments live elsewhere.
|
|
10
|
+
*
|
|
11
|
+
* A tenant source compares it with the digest of its last full attestation that
|
|
12
|
+
* passed, read in that attestation's own snapshot. Equal, that attestation
|
|
13
|
+
* stands for this snapshot; different, the full one runs again. The digest
|
|
14
|
+
* must be read after the source's LOCK, as the first statement of the
|
|
15
|
+
* snapshot, so DDL cannot land between it and the reads it vouches for.
|
|
16
|
+
*
|
|
17
|
+
* The statement has no parameters, so it can ride in the message that
|
|
18
|
+
* begins the snapshot (PostgresAdapter.readSnapshot's prologue): the schema
|
|
19
|
+
* names are this codebase's constants, spelled as literals. A runtime
|
|
20
|
+
* store's meta row is not in it: stores are attested when they are opened.
|
|
21
|
+
*
|
|
22
|
+
* Not seen: an object in `pg_catalog` renamed by a superuser, which could
|
|
23
|
+
* change the text of a default or index expression. It changes no read, and
|
|
24
|
+
* the attestation already trusts `pg_catalog` as everything else does.
|
|
25
|
+
*/
|
|
26
|
+
export declare function postgresCatalogDigestStatement(excludedSchemas: readonly string[]): string;
|
|
27
|
+
/** The digest a digest statement answered, from its result. */
|
|
28
|
+
export declare function postgresCatalogDigestOf(result: {
|
|
29
|
+
rows: readonly Record<string, unknown>[];
|
|
30
|
+
} | undefined): string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A digest of the PostgreSQL catalog rows a description reads.
|
|
3
|
+
*
|
|
4
|
+
* The tenant sources attest every snapshot against it (tenantPostgresCatalog.ts,
|
|
5
|
+
* tenantReadSource.ts), and a scoped transaction's writer reads it before it
|
|
6
|
+
* describes the catalog (PostgresAdapter), so either describes again only when
|
|
7
|
+
* the digest has moved.
|
|
8
|
+
*/
|
|
9
|
+
import { Refusal } from './adapter.js';
|
|
10
|
+
import { notExtensionMember } from './postgresCatalog.js';
|
|
11
|
+
/**
|
|
12
|
+
* One statement that changes whenever anything a full attestation reads
|
|
13
|
+
* changes: the `(oid, xmin)` of every catalog row the whole-catalog
|
|
14
|
+
* description, the pinned relation description and the store attestation
|
|
15
|
+
* depend on, over the same schemas, plus role membership and attributes and
|
|
16
|
+
* the store's meta row. Transactional DDL inserts, updates or deletes those
|
|
17
|
+
* rows, and a changed or removed row changes the digest. What does not change
|
|
18
|
+
* it is what attests nothing: VACUUM and ANALYZE update `pg_class` in place,
|
|
19
|
+
* and comments live elsewhere.
|
|
20
|
+
*
|
|
21
|
+
* A tenant source compares it with the digest of its last full attestation that
|
|
22
|
+
* passed, read in that attestation's own snapshot. Equal, that attestation
|
|
23
|
+
* stands for this snapshot; different, the full one runs again. The digest
|
|
24
|
+
* must be read after the source's LOCK, as the first statement of the
|
|
25
|
+
* snapshot, so DDL cannot land between it and the reads it vouches for.
|
|
26
|
+
*
|
|
27
|
+
* The statement has no parameters, so it can ride in the message that
|
|
28
|
+
* begins the snapshot (PostgresAdapter.readSnapshot's prologue): the schema
|
|
29
|
+
* names are this codebase's constants, spelled as literals. A runtime
|
|
30
|
+
* store's meta row is not in it: stores are attested when they are opened.
|
|
31
|
+
*
|
|
32
|
+
* Not seen: an object in `pg_catalog` renamed by a superuser, which could
|
|
33
|
+
* change the text of a default or index expression. It changes no read, and
|
|
34
|
+
* the attestation already trusts `pg_catalog` as everything else does.
|
|
35
|
+
*/
|
|
36
|
+
export function postgresCatalogDigestStatement(excludedSchemas) {
|
|
37
|
+
// Constants only: a name that is not a plain identifier is a programming error, never quoted around.
|
|
38
|
+
if (excludedSchemas.some((name) => !/^[a-z_][a-z0-9_]*$/.test(name)))
|
|
39
|
+
throw new Refusal('The catalog digest names only plain identifiers.');
|
|
40
|
+
const excludedLiteral = `ARRAY[${excludedSchemas.map((name) => `'${name}'`).join(', ')}]`;
|
|
41
|
+
return `WITH ns AS (SELECT n.oid, n.xmin FROM pg_catalog.pg_namespace n
|
|
42
|
+
WHERE n.nspname <> ALL(${excludedLiteral}::text[]) AND n.nspname !~ '^pg_(toast_)?temp_'),
|
|
43
|
+
/* An extension's own relations are left out, as the description leaves them out (see notExtensionMember). */
|
|
44
|
+
rel AS (SELECT c.oid, c.xmin FROM pg_catalog.pg_class c JOIN ns ON ns.oid = c.relnamespace WHERE ${notExtensionMember('c')}),
|
|
45
|
+
seen(v) AS (
|
|
46
|
+
SELECT 'n' || ns.oid || ':' || ns.xmin FROM ns
|
|
47
|
+
UNION ALL SELECT 'c' || rel.oid || ':' || rel.xmin FROM rel
|
|
48
|
+
UNION ALL SELECT 'a' || a.attrelid || '.' || a.attnum || ':' || a.xmin
|
|
49
|
+
FROM pg_catalog.pg_attribute a JOIN rel ON rel.oid = a.attrelid
|
|
50
|
+
UNION ALL SELECT 'd' || d.oid || ':' || d.xmin FROM pg_catalog.pg_attrdef d JOIN rel ON rel.oid = d.adrelid
|
|
51
|
+
UNION ALL SELECT 'k' || k.oid || ':' || k.xmin FROM pg_catalog.pg_constraint k
|
|
52
|
+
WHERE k.connamespace IN (SELECT oid FROM ns) OR k.conrelid IN (SELECT oid FROM rel) OR k.confrelid IN (SELECT oid FROM rel)
|
|
53
|
+
UNION ALL SELECT 'i' || i.indexrelid || ':' || i.xmin FROM pg_catalog.pg_index i JOIN rel ON rel.oid = i.indrelid
|
|
54
|
+
UNION ALL SELECT 't' || g.oid || ':' || g.xmin FROM pg_catalog.pg_trigger g JOIN rel ON rel.oid = g.tgrelid
|
|
55
|
+
UNION ALL SELECT 'r' || w.oid || ':' || w.xmin FROM pg_catalog.pg_rewrite w JOIN rel ON rel.oid = w.ev_class
|
|
56
|
+
UNION ALL SELECT 'p' || p.oid || ':' || p.xmin FROM pg_catalog.pg_policy p JOIN rel ON rel.oid = p.polrelid
|
|
57
|
+
UNION ALL SELECT 'y' || y.oid || ':' || y.xmin FROM pg_catalog.pg_type y JOIN ns ON ns.oid = y.typnamespace
|
|
58
|
+
UNION ALL SELECT 'e' || e.oid || ':' || e.xmin FROM pg_catalog.pg_enum e
|
|
59
|
+
JOIN pg_catalog.pg_type y ON y.oid = e.enumtypid JOIN ns ON ns.oid = y.typnamespace
|
|
60
|
+
UNION ALL SELECT 'f' || f.oid || ':' || f.xmin FROM pg_catalog.pg_proc f JOIN ns ON ns.oid = f.pronamespace
|
|
61
|
+
UNION ALL SELECT 'o' || o.oid || ':' || o.xmin FROM pg_catalog.pg_operator o JOIN ns ON ns.oid = o.oprnamespace
|
|
62
|
+
UNION ALL SELECT 'q' || q.oid || ':' || q.xmin FROM pg_catalog.pg_opclass q JOIN ns ON ns.oid = q.opcnamespace
|
|
63
|
+
/* What else a store attestation counts in the runtime schema (postgresRuntimeSchemaProblems): one more
|
|
64
|
+
object there refuses the store, so it moves the digest too. */
|
|
65
|
+
UNION ALL SELECT 'v' || v.oid || ':' || v.xmin FROM pg_catalog.pg_conversion v JOIN ns ON ns.oid = v.connamespace
|
|
66
|
+
UNION ALL SELECT 'F' || o.oid || ':' || o.xmin FROM pg_catalog.pg_opfamily o JOIN ns ON ns.oid = o.opfnamespace
|
|
67
|
+
UNION ALL SELECT 'Tc' || t.oid || ':' || t.xmin FROM pg_catalog.pg_ts_config t JOIN ns ON ns.oid = t.cfgnamespace
|
|
68
|
+
UNION ALL SELECT 'Td' || t.oid || ':' || t.xmin FROM pg_catalog.pg_ts_dict t JOIN ns ON ns.oid = t.dictnamespace
|
|
69
|
+
UNION ALL SELECT 'Tp' || t.oid || ':' || t.xmin FROM pg_catalog.pg_ts_parser t JOIN ns ON ns.oid = t.prsnamespace
|
|
70
|
+
UNION ALL SELECT 'Tt' || t.oid || ':' || t.xmin FROM pg_catalog.pg_ts_template t JOIN ns ON ns.oid = t.tmplnamespace
|
|
71
|
+
UNION ALL SELECT 'x' || x.oid || ':' || x.xmin FROM pg_catalog.pg_statistic_ext x JOIN ns ON ns.oid = x.stxnamespace
|
|
72
|
+
UNION ALL SELECT 'X' || x.oid || ':' || x.xmin FROM pg_catalog.pg_extension x JOIN ns ON ns.oid = x.extnamespace
|
|
73
|
+
UNION ALL SELECT 'l' || l.oid || ':' || l.xmin FROM pg_catalog.pg_collation l
|
|
74
|
+
WHERE l.collnamespace IN (SELECT oid FROM ns)
|
|
75
|
+
OR l.oid IN (SELECT a.attcollation FROM pg_catalog.pg_attribute a JOIN rel ON rel.oid = a.attrelid)
|
|
76
|
+
UNION ALL SELECT 'm' || m.roleid || '.' || m.member || ':' || m.xmin FROM pg_catalog.pg_auth_members m
|
|
77
|
+
UNION ALL SELECT 'u' || r.oid || ':' || r.rolname || ':' || r.rolsuper || ':' || r.rolinherit FROM pg_catalog.pg_roles r
|
|
78
|
+
UNION ALL SELECT 's' || current_user)
|
|
79
|
+
SELECT md5(string_agg(v, ',' ORDER BY v)) AS fingerprint FROM seen`;
|
|
80
|
+
}
|
|
81
|
+
/** The digest a digest statement answered, from its result. */
|
|
82
|
+
export function postgresCatalogDigestOf(result) {
|
|
83
|
+
const value = result?.rows[0]?.fingerprint;
|
|
84
|
+
if (typeof value !== 'string')
|
|
85
|
+
throw new Refusal('The catalog digest could not be read.');
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface ColumnRow {
|
|
2
|
+
table_schema: string;
|
|
3
|
+
table_name: string;
|
|
4
|
+
column_name: string;
|
|
5
|
+
data_type: string;
|
|
6
|
+
is_nullable: string;
|
|
7
|
+
column_default: string | null;
|
|
8
|
+
is_identity: string;
|
|
9
|
+
identity_generation: string | null;
|
|
10
|
+
/** `ALWAYS` for a generated column, `NEVER` otherwise. */
|
|
11
|
+
is_generated?: string;
|
|
12
|
+
ordinal_position: number;
|
|
13
|
+
comment: string | null;
|
|
14
|
+
/** Labels when the column's type is an enum; null otherwise. */
|
|
15
|
+
enum_labels: string[] | null;
|
|
16
|
+
/** A `varchar(n)`'s n; null for any other type. */
|
|
17
|
+
character_maximum_length: number | null;
|
|
18
|
+
}
|
|
19
|
+
/** What the checks say of a text column's length and form (vocabulary.ts checkTextRule), the first of each. */
|
|
20
|
+
export declare function checkedText(checks: string[], column: string): {
|
|
21
|
+
min?: number;
|
|
22
|
+
pattern?: string;
|
|
23
|
+
};
|
|
24
|
+
/** The first check that pins this column's values, if any does. */
|
|
25
|
+
export declare function firstVocabulary(checks: string[], column: string): string[] | undefined;
|
|
26
|
+
export interface CheckRow {
|
|
27
|
+
table_schema: string;
|
|
28
|
+
table_name: string;
|
|
29
|
+
expression: string;
|
|
30
|
+
}
|
|
31
|
+
export interface KeyRow {
|
|
32
|
+
constraint_name: string;
|
|
33
|
+
delete_rule?: string;
|
|
34
|
+
from_schema: string;
|
|
35
|
+
from_table: string;
|
|
36
|
+
from_columns: string[];
|
|
37
|
+
to_schema: string;
|
|
38
|
+
to_table: string;
|
|
39
|
+
to_columns: string[];
|
|
40
|
+
}
|
|
41
|
+
export interface PkRow {
|
|
42
|
+
table_schema: string;
|
|
43
|
+
table_name: string;
|
|
44
|
+
columns: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface IndexRow {
|
|
47
|
+
table_schema: string;
|
|
48
|
+
table_name: string;
|
|
49
|
+
column_name: string;
|
|
50
|
+
sole_unique?: boolean;
|
|
51
|
+
unique_pair?: string[] | null;
|
|
52
|
+
trigram_columns?: string[];
|
|
53
|
+
}
|
|
54
|
+
export interface RelRow {
|
|
55
|
+
table_schema: string;
|
|
56
|
+
table_name: string;
|
|
57
|
+
kind: string;
|
|
58
|
+
approx_rows: string | number | null;
|
|
59
|
+
comment: string | null;
|
|
60
|
+
}
|
|
61
|
+
/** PostgreSQL's negative catalog estimate means unknown, not an empty table. */
|
|
62
|
+
export declare function postgresRowEstimate(value: unknown): number | undefined;
|