@cosmicdrift/kumiko-framework 0.387.0 → 0.388.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/AGENTS.md +6 -1
  2. package/agents/examples/anonymous-access.md +1 -1
  3. package/agents/examples/apex-landing.md +204 -0
  4. package/agents/examples/api-worker-split.md +64 -0
  5. package/agents/examples/app-config.md +14 -0
  6. package/agents/examples/auth-mfa.md +115 -0
  7. package/agents/examples/env-composition.md +28 -1
  8. package/agents/examples/legal-pages.md +1 -1
  9. package/agents/examples/prod-boot-options.md +16 -0
  10. package/agents/examples/rate-limiting.md +48 -0
  11. package/agents/examples/record-detail-layout.md +692 -0
  12. package/agents/examples/seed-migration.md +212 -0
  13. package/agents/examples/wizard-form.md +941 -0
  14. package/agents/examples/writeform-section.md +548 -0
  15. package/agents/features.md +19 -2
  16. package/agents/widgets.md +1 -0
  17. package/dist/api/client-error-route.js +8 -2
  18. package/dist/api/index.d.ts +3 -1
  19. package/dist/api/index.js +3 -1
  20. package/dist/api/request-context.d.ts +1 -1
  21. package/dist/api/request-context.js +1 -1
  22. package/dist/api/server-boot-checks.d.ts +10 -0
  23. package/dist/api/server-boot-checks.js +157 -0
  24. package/dist/api/server-event-dispatcher.d.ts +26 -0
  25. package/dist/api/server-event-dispatcher.js +208 -0
  26. package/dist/api/server-extra-routes.d.ts +11 -0
  27. package/dist/api/server-extra-routes.js +203 -0
  28. package/dist/api/server-middleware.d.ts +20 -0
  29. package/dist/api/server-middleware.js +211 -0
  30. package/dist/api/server-routes.d.ts +19 -0
  31. package/dist/api/server-routes.js +293 -0
  32. package/dist/api/server-websocket-routes.d.ts +4 -0
  33. package/dist/api/server-websocket-routes.js +108 -0
  34. package/dist/api/server-wiring.d.ts +32 -0
  35. package/dist/api/server-wiring.js +236 -0
  36. package/dist/api/server.d.ts +10 -15
  37. package/dist/api/server.js +48 -1251
  38. package/dist/api/session-cookies.js +4 -4
  39. package/dist/api/sse-route.js +16 -12
  40. package/dist/crypto/owner-transition-rekey.d.ts +5 -1
  41. package/dist/crypto/owner-transition-rekey.js +1 -1
  42. package/dist/crypto/pii-field-encryption.d.ts +5 -1
  43. package/dist/crypto/pii-field-encryption.js +3 -1
  44. package/dist/db/aggregate-sql.d.ts +21 -0
  45. package/dist/db/aggregate-sql.js +155 -0
  46. package/dist/db/closed-connection.d.ts +9 -0
  47. package/dist/db/closed-connection.js +95 -0
  48. package/dist/db/dialect.js +1 -1
  49. package/dist/db/distinct-on.d.ts +1 -1
  50. package/dist/db/driver-row-coercion.d.ts +2 -0
  51. package/dist/db/driver-row-coercion.js +186 -0
  52. package/dist/db/driver-value-preparation.d.ts +16 -0
  53. package/dist/db/driver-value-preparation.js +99 -0
  54. package/dist/db/entity-field-encryption.d.ts +1 -0
  55. package/dist/db/entity-field-encryption.js +1 -1
  56. package/dist/db/entity-table-meta.js +103 -110
  57. package/dist/db/event-store-executor-context.d.ts +2 -1
  58. package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
  59. package/dist/db/event-store-executor-read-aggregate.js +112 -0
  60. package/dist/db/event-store-executor-read-filter.d.ts +31 -0
  61. package/dist/db/event-store-executor-read-filter.js +203 -0
  62. package/dist/db/event-store-executor-read-paging.d.ts +14 -0
  63. package/dist/db/event-store-executor-read-paging.js +99 -0
  64. package/dist/db/event-store-executor-read-rows.d.ts +6 -0
  65. package/dist/db/event-store-executor-read-rows.js +32 -0
  66. package/dist/db/event-store-executor-read-search.d.ts +28 -0
  67. package/dist/db/event-store-executor-read-search.js +221 -0
  68. package/dist/db/event-store-executor-read-sort.d.ts +41 -0
  69. package/dist/db/event-store-executor-read-sort.js +130 -0
  70. package/dist/db/event-store-executor-read-where.d.ts +24 -0
  71. package/dist/db/event-store-executor-read-where.js +81 -0
  72. package/dist/db/event-store-executor-read.d.ts +2 -9
  73. package/dist/db/event-store-executor-read.js +48 -701
  74. package/dist/db/event-store-executor-write-steps.d.ts +20 -0
  75. package/dist/db/event-store-executor-write-steps.js +100 -0
  76. package/dist/db/event-store-executor-write.js +395 -499
  77. package/dist/db/index.d.ts +6 -2
  78. package/dist/db/index.js +5 -1
  79. package/dist/db/list-aggregate-labels.d.ts +14 -0
  80. package/dist/db/list-aggregate-labels.js +26 -0
  81. package/dist/db/migrate-generator.js +71 -86
  82. package/dist/db/migrate-runner.js +4 -1
  83. package/dist/db/query.d.ts +2 -15
  84. package/dist/db/query.js +8 -761
  85. package/dist/db/reference-data.js +6 -1
  86. package/dist/db/table-builder.js +113 -166
  87. package/dist/db/table-info.d.ts +10 -0
  88. package/dist/db/table-info.js +45 -0
  89. package/dist/db/temporal-value-guards.d.ts +6 -0
  90. package/dist/db/temporal-value-guards.js +15 -0
  91. package/dist/db/tenant-db-runner.d.ts +1 -0
  92. package/dist/db/tenant-db-runner.js +3 -0
  93. package/dist/db/tenant-db.js +39 -9
  94. package/dist/db/where-clause.d.ts +6 -0
  95. package/dist/db/where-clause.js +236 -0
  96. package/dist/derivatives/delete-stored-file.js +2 -1
  97. package/dist/engine/boot-validator/boot-check.js +1 -1
  98. package/dist/engine/boot-validator/detail-screens.js +2 -2
  99. package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
  100. package/dist/engine/boot-validator/entity-handler.js +17 -0
  101. package/dist/engine/boot-validator/form-derivations.js +35 -1
  102. package/dist/engine/boot-validator/i18n-keys.js +5 -3
  103. package/dist/engine/boot-validator/index.js +2 -0
  104. package/dist/engine/boot-validator/pii-retention.js +233 -155
  105. package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
  106. package/dist/engine/boot-validator/screens-actions.js +8 -1
  107. package/dist/engine/boot-validator/screens-dashboard.js +2 -5
  108. package/dist/engine/boot-validator/screens-forms.js +2 -6
  109. package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
  110. package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
  111. package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
  112. package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
  113. package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
  114. package/dist/engine/boot-validator/screens-kind-entity-list.js +228 -0
  115. package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
  116. package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
  117. package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
  118. package/dist/engine/boot-validator/screens-kind-projection-list.js +52 -0
  119. package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
  120. package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
  121. package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
  122. package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
  123. package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
  124. package/dist/engine/boot-validator/screens-lists.js +12 -9
  125. package/dist/engine/boot-validator/screens.d.ts +0 -2
  126. package/dist/engine/boot-validator/screens.js +99 -860
  127. package/dist/engine/build-app-schema.js +56 -96
  128. package/dist/engine/define-feature.js +9 -2
  129. package/dist/engine/define-handler.js +1 -0
  130. package/dist/engine/entity-handlers.d.ts +13 -0
  131. package/dist/engine/entity-handlers.js +10 -21
  132. package/dist/engine/entity-list-runtime-options.d.ts +8 -0
  133. package/dist/engine/entity-list-runtime-options.js +18 -0
  134. package/dist/engine/feature-ast/extractors/handlers.js +1 -0
  135. package/dist/engine/feature-ast/extractors/round2.js +25 -6
  136. package/dist/engine/feature-ast/patch.js +4 -182
  137. package/dist/engine/feature-ast/pattern-change-schema.d.ts +3 -0
  138. package/dist/engine/feature-ast/pattern-change-schema.js +1 -0
  139. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
  140. package/dist/engine/feature-ast/pattern-id-matchers.js +210 -0
  141. package/dist/engine/feature-ast/patterns.d.ts +9 -0
  142. package/dist/engine/feature-ast/patterns.js +43 -51
  143. package/dist/engine/feature-ast/render.js +48 -87
  144. package/dist/engine/feature-entity-handlers.js +3 -0
  145. package/dist/engine/form-derivations.js +18 -7
  146. package/dist/engine/handler-field-references.js +1 -1
  147. package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
  148. package/dist/engine/project-app-schema-for-roles.js +6 -4
  149. package/dist/engine/registry-ingest.js +1 -1
  150. package/dist/engine/schema-builder.js +228 -212
  151. package/dist/engine/screen-helpers.js +1 -1
  152. package/dist/engine/screen-kind.d.ts +7 -0
  153. package/dist/engine/screen-kind.js +1 -0
  154. package/dist/engine/strip-disabled-features-from-app-schema.js +51 -14
  155. package/dist/engine/validate-projection-allowlist.js +2 -1
  156. package/dist/entrypoint/index.d.ts +4 -1
  157. package/dist/entrypoint/index.js +7 -1
  158. package/dist/errors/docs-url.d.ts +1 -1
  159. package/dist/errors/docs-url.js +22 -2
  160. package/dist/es-ops/context.js +1 -1
  161. package/dist/event-store/admin-api.js +1 -1
  162. package/dist/event-store/event-store.js +10 -4
  163. package/dist/files/bind-pending-file-refs.js +3 -3
  164. package/dist/files/create-file-ref-from-bytes.js +4 -1
  165. package/dist/files/file-handle.js +2 -3
  166. package/dist/files/file-routes.js +11 -8
  167. package/dist/files/resolve-content-type.js +43 -0
  168. package/dist/files/upload-ledger.js +7 -0
  169. package/dist/i18n/required-surface-keys.js +182 -206
  170. package/dist/internal/stack-support.d.ts +2 -1
  171. package/dist/internal/stack-support.js +1 -1
  172. package/dist/jobs/job-runner-context.d.ts +32 -0
  173. package/dist/jobs/job-runner-context.js +305 -0
  174. package/dist/jobs/job-runner-execution.d.ts +7 -0
  175. package/dist/jobs/job-runner-execution.js +160 -0
  176. package/dist/jobs/job-runner-gates.d.ts +19 -0
  177. package/dist/jobs/job-runner-gates.js +198 -0
  178. package/dist/jobs/job-runner-helpers.d.ts +17 -3
  179. package/dist/jobs/job-runner-helpers.js +61 -2
  180. package/dist/jobs/job-runner-scope.d.ts +44 -0
  181. package/dist/jobs/job-runner-scope.js +102 -0
  182. package/dist/jobs/job-runner-types.d.ts +12 -0
  183. package/dist/jobs/job-runner.d.ts +0 -1
  184. package/dist/jobs/job-runner.js +47 -657
  185. package/dist/observability/escape-hatch-report.d.ts +3 -0
  186. package/dist/observability/escape-hatch-report.js +12 -1
  187. package/dist/pipeline/cascade-handler.js +165 -138
  188. package/dist/pipeline/dispatch-query.js +10 -3
  189. package/dist/pipeline/dispatch-shared.d.ts +13 -3
  190. package/dist/pipeline/dispatch-shared.js +58 -710
  191. package/dist/pipeline/dispatch-write.js +296 -189
  192. package/dist/pipeline/event-dispatcher-admin.js +2 -1
  193. package/dist/pipeline/event-dispatcher-delivery.js +3 -5
  194. package/dist/pipeline/handler-context-auth.d.ts +9 -0
  195. package/dist/pipeline/handler-context-auth.js +54 -0
  196. package/dist/pipeline/handler-context-config.d.ts +14 -0
  197. package/dist/pipeline/handler-context-config.js +113 -0
  198. package/dist/pipeline/handler-context-db.d.ts +24 -0
  199. package/dist/pipeline/handler-context-db.js +149 -0
  200. package/dist/pipeline/handler-context-dispatch.d.ts +21 -0
  201. package/dist/pipeline/handler-context-dispatch.js +89 -0
  202. package/dist/pipeline/handler-context-events.d.ts +43 -0
  203. package/dist/pipeline/handler-context-events.js +237 -0
  204. package/dist/pipeline/handler-context-notify.d.ts +12 -0
  205. package/dist/pipeline/handler-context-notify.js +55 -0
  206. package/dist/pipeline/handler-context-observability.d.ts +7 -0
  207. package/dist/pipeline/handler-context-observability.js +21 -0
  208. package/dist/pipeline/handler-context-scope.d.ts +48 -0
  209. package/dist/pipeline/handler-context-scope.js +88 -0
  210. package/dist/pipeline/notify-scope.js +12 -1
  211. package/dist/pipeline/pre-handler-gates.js +20 -4
  212. package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
  213. package/dist/pipeline/pre-transaction-reservations.js +9 -3
  214. package/dist/pipeline/projection-rebuild.js +2 -1
  215. package/dist/schema-cli/apply-command.d.ts +2 -0
  216. package/dist/schema-cli/apply-command.js +97 -0
  217. package/dist/schema-cli/baseline-command.d.ts +2 -0
  218. package/dist/schema-cli/baseline-command.js +33 -0
  219. package/dist/schema-cli/generate-command.d.ts +2 -0
  220. package/dist/schema-cli/generate-command.js +90 -0
  221. package/dist/schema-cli/shared.d.ts +39 -0
  222. package/dist/schema-cli/shared.js +95 -0
  223. package/dist/schema-cli/status-command.d.ts +2 -0
  224. package/dist/schema-cli/status-command.js +73 -0
  225. package/dist/schema-cli/validate-boot-input.d.ts +5 -0
  226. package/dist/schema-cli/validate-boot-input.js +130 -0
  227. package/dist/schema-cli/validate-command.d.ts +2 -0
  228. package/dist/schema-cli/validate-command.js +130 -0
  229. package/dist/schema-cli.d.ts +2 -18
  230. package/dist/schema-cli.js +47 -604
  231. package/dist/search/meilisearch-adapter.js +2 -1
  232. package/dist/upgrade-cli.js +149 -121
  233. package/package.json +4 -4
  234. package/src/changes.json +310 -0
  235. package/src/scripts/codemod/feature-layout.ts +10 -2
  236. package/src/scripts/codemod/object-form.ts +41 -4
  237. package/src/scripts/codemod/package-merge.ts +58 -8
  238. package/src/scripts/codemod/pii-personal-migration.ts +175 -145
  239. package/src/scripts/codemod/testing-injection.ts +122 -42
  240. package/src/scripts/codemod/testing-move.ts +29 -7
@@ -1,3 +1,4 @@
1
+ export { isTimestamptzType } from "./aggregate-sql.ts";
1
2
  export { applyEntityEvent } from "./apply-entity-event.ts";
2
3
  export { assertExistsIn } from "./assert-exists-in.ts";
3
4
  export { nullBlindIndexesForSubject, recordEventsOwnedExclusivelyByTenant, recordRowExistsInTenant, recordRowOwningTenantId, subjectRowExistsInTenant, } from "./blind-index-cleanup.ts";
@@ -10,6 +11,7 @@ export type { CursorQueryOptions, CursorResult, DecodedKeysetCursor } from "./cu
10
11
  export { decodeCursor, decodeKeysetCursor, encodeCursor, encodeKeysetCursor } from "./cursor.ts";
11
12
  export type { SchemaTable, SelectQuery, TableColumns } from "./dialect.ts";
12
13
  export { bigint, bigserial, boolean, extractTableName, index, instant, instantToDriver, integer, jsonb, moneyAmount, numeric, primaryKey, serial, sql, table, text, timestamp, uniqueIndex, uuid, } from "./dialect.ts";
14
+ export { instantToTimestamptzParam } from "./driver-value-preparation.ts";
13
15
  export type { EagerLoadEntityResolver, EagerLoadViewer, EagerloadedRow } from "./eagerload.ts";
14
16
  export { collectReferenceFields, enrichRowWithReferences, enrichWithReferences, } from "./eagerload.ts";
15
17
  export { collectEncryptedFieldNames, configuredEntityFieldEncryption, configureEntityFieldEncryption, decryptEntityFieldValues, encryptEntityFieldValues, } from "./entity-field-encryption.ts";
@@ -19,6 +21,7 @@ export { defineUnmanagedTable, deriveEntityTableMeta, } from "./entity-table-met
19
21
  export type { EntityLifecycleVerb, EventStoreExecutor, EventStoreExecutorOptions, LockGuardOption, WritePurpose, } from "./event-store-executor.ts";
20
22
  export { createEventStoreExecutor, entityEventName, WritePurposes, } from "./event-store-executor.ts";
21
23
  export { enumerateFeatureTableSources, type FeatureTableSource, } from "./feature-table-sources.ts";
24
+ export { answerListAggregate, labelListAggregateGroups } from "./list-aggregate-labels.ts";
22
25
  export { flattenLocatedTimestamp, type LocatedTimestampRead, rehydrateLocatedTimestamp, } from "./located-timestamp.ts";
23
26
  export { assertUniqueTableNames, assertValidMigrationName, diffSnapshots, type GenerateMigrationInput, type GenerateMigrationOutput, generateMigration, loadSnapshotJson, renderMigrationSql, type SchemaDiff, type Snapshot, snapshotFromMetas, writeSnapshotJson, } from "./migrate-generator.ts";
24
27
  export { type AppliedMigration, type ApplyResult, type BaselineResult, baselineMigrations, fetchAppliedMigrations, loadMigrationsFromDir, type Migration, MigrationChecksumMismatchError, readMigrationSqlTexts, runMigrations, runMigrationsFromDir, splitSqlStatements, } from "./migrate-runner.ts";
@@ -28,8 +31,8 @@ export { acquireNamespacedAdvisoryLock } from "./queries/advisory-lock.ts";
28
31
  export { readDatabaseNow } from "./queries/database-now.ts";
29
32
  export { toPostgresArrayLiteral } from "./queries/postgres-array-literal.ts";
30
33
  export { executeRawQuery, executeRawQueryRead } from "./queries/raw-sql.ts";
31
- export type { DeleteManyBatchedOptions, DeleteManyBatchedResult, IncrementCounterOptions, InnerJoinRow, InnerJoinSpec, InsertOnConflictDoNothingOptions, JoinColumnPair, JsonTextMatch, SelectOptions, TableInfo, UpsertOnConflictOptions, WhereObject, WhereOperator, WhereValue, } from "./query.ts";
32
- export { aggregateWhere, asEntityTableMeta, asRawClient, countWhere, deleteMany, deleteManyBatched, extractTableInfo, fetchOne, incrementCounter, insertMany, insertOnConflictDoNothing, insertOne, instantToTimestamptzParam, isTimestamptzType, requireEntityTableMeta, runInSavepoint, runInSavepointIfSupported, runnerCanBeginTransaction, selectInnerJoin, selectMany, transaction, unsafeReadRetrying, updateMany, upsertByPk, upsertOnConflict, } from "./query.ts";
34
+ export type { DeleteManyBatchedOptions, DeleteManyBatchedResult, IncrementCounterOptions, InnerJoinRow, InnerJoinSpec, InsertOnConflictDoNothingOptions, JoinColumnPair, JsonTextMatch, SelectOptions, UpsertOnConflictOptions, WhereObject, WhereOperator, WhereValue, } from "./query.ts";
35
+ export { aggregateWhere, asEntityTableMeta, asRawClient, countWhere, deleteMany, deleteManyBatched, fetchOne, incrementCounter, insertMany, insertOnConflictDoNothing, insertOne, requireEntityTableMeta, runInSavepoint, runInSavepointIfSupported, runnerCanBeginTransaction, selectInnerJoin, selectMany, transaction, unsafeReadRetrying, updateMany, upsertByPk, upsertOnConflict, } from "./query.ts";
33
36
  export { readRebuildMarker, rebuildTablesFromDiff, writeRebuildMarker, } from "./rebuild-marker.ts";
34
37
  export { seedReferenceData } from "./reference-data.ts";
35
38
  export { renderTableDdl, renderTablesDdl } from "./render-ddl.ts";
@@ -38,5 +41,6 @@ export { findCommentedDropTables, isRetiredFrameworkTable, type RetiredFramework
38
41
  export { tableExists } from "./schema-inspection.ts";
39
42
  export { withoutStatementTimeout } from "./statement-timeout.ts";
40
43
  export { buildBaseColumns, buildEntityTable, declareGlobalTenancy, type EntityRow, type EntityTable, type ExecutorManagedRunner, type ExecutorManagedWriteCapability, physicalColumnName, toSnakeCase, toTableName, type Writable, type WritableSchemaTable, type WritableTable, } from "./table-builder.ts";
44
+ export { extractTableInfo, type TableInfo } from "./table-info.ts";
41
45
  export type { CreateTenantDbOptions, ExecutorManagedTenantDb, OutsideTransactionContext, TenantDb, TenantDbGrants, TenantDbMode, UncheckedSystemDb, } from "./tenant-db.ts";
42
46
  export { castTenantRows, createSystemDbView, createTenantDataDestroyDb, createTenantDb, hasOutsideTransactionDb, requireOutsideTransactionDb, runInOwnTransaction, SYSTEM_SCOPE_CHECK_BRAND, scopeTenantDbToTenant, } from "./tenant-db.ts";
package/dist/db/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { isTimestamptzType } from "./aggregate-sql.js";
1
2
  export { applyEntityEvent } from "./apply-entity-event.js";
2
3
  export { assertExistsIn } from "./assert-exists-in.js";
3
4
  export { nullBlindIndexesForSubject, recordEventsOwnedExclusivelyByTenant, recordRowExistsInTenant, recordRowOwningTenantId, subjectRowExistsInTenant, } from "./blind-index-cleanup.js";
@@ -7,12 +8,14 @@ export { seedConfigValues } from "./config-seed.js";
7
8
  export { createDbConnection, DEFAULT_OUTSIDE_TRANSACTION_POOL_MAX, dbConnectionOptionsFromEnv, outsideTransactionPoolOptionsFromEnv, serverTimeoutOptionsFromEnv, } from "./connection.js";
8
9
  export { decodeCursor, decodeKeysetCursor, encodeCursor, encodeKeysetCursor } from "./cursor.js";
9
10
  export { bigint, bigserial, boolean, extractTableName, index, instant, instantToDriver, integer, jsonb, moneyAmount, numeric, primaryKey, serial, sql, table, text, timestamp, uniqueIndex, uuid, } from "./dialect.js";
11
+ export { instantToTimestamptzParam } from "./driver-value-preparation.js";
10
12
  export { collectReferenceFields, enrichRowWithReferences, enrichWithReferences, } from "./eagerload.js";
11
13
  export { collectEncryptedFieldNames, configuredEntityFieldEncryption, configureEntityFieldEncryption, decryptEntityFieldValues, encryptEntityFieldValues, } from "./entity-field-encryption.js";
12
14
  export { entityTableFromRegistry } from "./entity-table-from-registry.js";
13
15
  export { defineUnmanagedTable, deriveEntityTableMeta, } from "./entity-table-meta.js";
14
16
  export { createEventStoreExecutor, entityEventName, WritePurposes, } from "./event-store-executor.js";
15
17
  export { enumerateFeatureTableSources, } from "./feature-table-sources.js";
18
+ export { answerListAggregate, labelListAggregateGroups } from "./list-aggregate-labels.js";
16
19
  export { flattenLocatedTimestamp, rehydrateLocatedTimestamp, } from "./located-timestamp.js";
17
20
  export { assertUniqueTableNames, assertValidMigrationName, diffSnapshots, generateMigration, loadSnapshotJson, renderMigrationSql, snapshotFromMetas, writeSnapshotJson, } from "./migrate-generator.js";
18
21
  export { baselineMigrations, fetchAppliedMigrations, loadMigrationsFromDir, MigrationChecksumMismatchError, readMigrationSqlTexts, runMigrations, runMigrationsFromDir, splitSqlStatements, } from "./migrate-runner.js";
@@ -22,7 +25,7 @@ export { acquireNamespacedAdvisoryLock } from "./queries/advisory-lock.js";
22
25
  export { readDatabaseNow } from "./queries/database-now.js";
23
26
  export { toPostgresArrayLiteral } from "./queries/postgres-array-literal.js";
24
27
  export { executeRawQuery, executeRawQueryRead } from "./queries/raw-sql.js";
25
- export { aggregateWhere, asEntityTableMeta, asRawClient, countWhere, deleteMany, deleteManyBatched, extractTableInfo, fetchOne, incrementCounter, insertMany, insertOnConflictDoNothing, insertOne, instantToTimestamptzParam, isTimestamptzType, requireEntityTableMeta, runInSavepoint, runInSavepointIfSupported, runnerCanBeginTransaction, selectInnerJoin, selectMany, transaction, unsafeReadRetrying, updateMany, upsertByPk, upsertOnConflict, } from "./query.js";
28
+ export { aggregateWhere, asEntityTableMeta, asRawClient, countWhere, deleteMany, deleteManyBatched, fetchOne, incrementCounter, insertMany, insertOnConflictDoNothing, insertOne, requireEntityTableMeta, runInSavepoint, runInSavepointIfSupported, runnerCanBeginTransaction, selectInnerJoin, selectMany, transaction, unsafeReadRetrying, updateMany, upsertByPk, upsertOnConflict, } from "./query.js";
26
29
  export { readRebuildMarker, rebuildTablesFromDiff, writeRebuildMarker, } from "./rebuild-marker.js";
27
30
  export { seedReferenceData } from "./reference-data.js";
28
31
  export { renderTableDdl, renderTablesDdl } from "./render-ddl.js";
@@ -31,4 +34,5 @@ export { findCommentedDropTables, isRetiredFrameworkTable, retiredFrameworkTable
31
34
  export { tableExists } from "./schema-inspection.js";
32
35
  export { withoutStatementTimeout } from "./statement-timeout.js";
33
36
  export { buildBaseColumns, buildEntityTable, declareGlobalTenancy, physicalColumnName, toSnakeCase, toTableName, } from "./table-builder.js";
37
+ export { extractTableInfo } from "./table-info.js";
34
38
  export { castTenantRows, createSystemDbView, createTenantDataDestroyDb, createTenantDb, hasOutsideTransactionDb, requireOutsideTransactionDb, runInOwnTransaction, SYSTEM_SCOPE_CHECK_BRAND, scopeTenantDbToTenant, } from "./tenant-db.js";
@@ -0,0 +1,14 @@
1
+ import type { ListAggregateResult } from "@cosmicdrift/kumiko-types/list-aggregate-types";
2
+ import type { EntityDefinition } from "../engine/types/index.ts";
3
+ import type { EagerLoadEntityResolver, EagerLoadViewer } from "./eagerload.ts";
4
+ import type { EventStoreExecutor } from "./event-store-executor.ts";
5
+ import type { TenantDb } from "./tenant-db.ts";
6
+ type LabelDeps = {
7
+ readonly entity: EntityDefinition;
8
+ readonly resolveEntity: EagerLoadEntityResolver;
9
+ readonly viewer: EagerLoadViewer;
10
+ };
11
+ export declare function labelListAggregateGroups(result: ListAggregateResult, groupByField: string | undefined, deps: LabelDeps, db: TenantDb): Promise<ListAggregateResult>;
12
+ type AggregateRequest = Parameters<EventStoreExecutor["aggregate"]>[0];
13
+ export declare function answerListAggregate(executor: Pick<EventStoreExecutor, "aggregate">, request: AggregateRequest, user: Parameters<EventStoreExecutor["aggregate"]>[1], db: TenantDb, runtimeOptions: Parameters<EventStoreExecutor["aggregate"]>[3], labelDeps: LabelDeps): Promise<ListAggregateResult>;
14
+ export {};
@@ -0,0 +1,26 @@
1
+ import { enrichWithReferences } from "./eagerload.js";
2
+ function labelOf(ref, labelField) {
3
+ if (typeof ref !== "object" || ref === null || Array.isArray(ref))
4
+ return null;
5
+ const value = Reflect.get(ref, labelField);
6
+ return typeof value === "string" ? value : null;
7
+ }
8
+ // Labels come from the same eager-load path as list rows, so they carry its
9
+ // ownership and field-read gating instead of a second label query.
10
+ export async function labelListAggregateGroups(result, groupByField, deps, db) {
11
+ if (groupByField === undefined || result.groups.length === 0)
12
+ return result;
13
+ const def = deps.entity.fields[groupByField];
14
+ if (def?.type !== "reference" || def.multiple === true)
15
+ return result;
16
+ const enriched = await enrichWithReferences(result.groups.map((g) => ({ [groupByField]: g.key })), deps.entity, deps.resolveEntity, db, deps.viewer);
17
+ const groups = result.groups.map((group, i) => {
18
+ const ref = Reflect.get(enriched[i]?.["_refs"] ?? {}, groupByField);
19
+ return { ...group, label: labelOf(ref, def.labelField ?? "id") };
20
+ });
21
+ return { ...result, groups };
22
+ }
23
+ export async function answerListAggregate(executor, request, user, db, runtimeOptions, labelDeps) {
24
+ const result = await executor.aggregate(request, user, db, runtimeOptions);
25
+ return labelListAggregateGroups(result, request.aggregate.groupBy, labelDeps, db);
26
+ }
@@ -79,100 +79,85 @@ function indexesByName(meta) {
79
79
  m.set(indexMetaKey(i), i);
80
80
  return m;
81
81
  }
82
- function diffOneTable(prev, next) {
83
- const prevCols = columnsByName(prev);
84
- const nextCols = columnsByName(next);
85
- const newColumns = [];
86
- const droppedColumns = [];
87
- const changedColumns = [];
88
- for (const [name, nextCol] of nextCols) {
89
- const prevCol = prevCols.get(name);
90
- if (!prevCol) {
91
- newColumns.push(nextCol);
92
- continue;
93
- }
94
- const change = { name };
95
- if (prevCol.notNull !== nextCol.notNull) {
96
- Object.assign(change, {
97
- nullabilityChanged: { from: prevCol.notNull, to: nextCol.notNull },
98
- });
99
- }
100
- if (prevCol.defaultSql !== nextCol.defaultSql) {
101
- Object.assign(change, {
102
- defaultChanged: { from: prevCol.defaultSql, to: nextCol.defaultSql },
103
- });
104
- }
105
- if (prevCol.pgType !== nextCol.pgType) {
106
- Object.assign(change, {
107
- typeChanged: { from: prevCol.pgType, to: nextCol.pgType },
108
- });
109
- }
110
- if (change.nullabilityChanged || change.defaultChanged || change.typeChanged) {
111
- changedColumns.push(change);
112
- }
113
- }
114
- for (const name of prevCols.keys()) {
115
- if (!nextCols.has(name))
116
- droppedColumns.push(name);
117
- }
118
- const prevIdx = indexesByName(prev);
119
- const nextIdx = indexesByName(next);
120
- const newIndexes = [];
121
- const droppedIndexes = [];
122
- const changedIndexes = [];
123
- for (const [name, idx] of nextIdx) {
124
- const prevI = prevIdx.get(name);
125
- if (!prevI) {
126
- newIndexes.push(idx);
82
+ function strictEqual(a, b) {
83
+ return a === b;
84
+ }
85
+ function fromToWhenDifferent(from, to, isEqual = strictEqual) {
86
+ return isEqual(from, to) ? undefined : { from, to };
87
+ }
88
+ // added and changed follow next's order, dropped follows prev's order; the
89
+ // rendered migration depends on both.
90
+ function diffByName(prev, next, compare) {
91
+ const added = [];
92
+ const changed = [];
93
+ for (const [name, nextItem] of next) {
94
+ const prevItem = prev.get(name);
95
+ if (prevItem === undefined) {
96
+ added.push(nextItem);
127
97
  continue;
128
98
  }
129
- const columnsChanged = indexColumnsEqual(prevI.columns, idx.columns)
130
- ? undefined
131
- : { from: prevI.columns, to: idx.columns };
132
- const uniqueChanged = (prevI.unique ?? false) === (idx.unique ?? false)
133
- ? undefined
134
- : { from: prevI.unique ?? false, to: idx.unique ?? false };
135
- // Whitespace-only re-rendering of the predicate must not drop and rebuild a large index.
136
- const whereSqlChanged = whereSqlEqual(prevI.whereSql, idx.whereSql)
137
- ? undefined
138
- : { from: prevI.whereSql, to: idx.whereSql };
139
- const needsManualWhereChanged = (prevI.needsManualWhere ?? false) === (idx.needsManualWhere ?? false)
140
- ? undefined
141
- : { from: prevI.needsManualWhere ?? false, to: idx.needsManualWhere ?? false };
142
- if (columnsChanged || uniqueChanged || whereSqlChanged || needsManualWhereChanged) {
143
- // Single literal typed as IndexChange so a misspelled key fails to compile instead of silently dropping the change.
144
- const change = {
145
- name,
146
- ...(columnsChanged && { columnsChanged }),
147
- ...(uniqueChanged && { uniqueChanged }),
148
- ...(whereSqlChanged && { whereSqlChanged }),
149
- ...(needsManualWhereChanged && { needsManualWhereChanged }),
150
- };
151
- changedIndexes.push(change);
152
- }
99
+ const change = compare(name, prevItem, nextItem);
100
+ if (change !== undefined)
101
+ changed.push(change);
153
102
  }
154
- for (const name of prevIdx.keys()) {
155
- if (!nextIdx.has(name))
156
- droppedIndexes.push(name);
103
+ const dropped = [...prev.keys()].filter((name) => !next.has(name));
104
+ return { added, dropped, changed };
105
+ }
106
+ function compareColumns(name, prevCol, nextCol) {
107
+ const nullabilityChanged = fromToWhenDifferent(prevCol.notNull, nextCol.notNull);
108
+ const defaultChanged = fromToWhenDifferent(prevCol.defaultSql, nextCol.defaultSql);
109
+ const typeChanged = fromToWhenDifferent(prevCol.pgType, nextCol.pgType);
110
+ if (!nullabilityChanged && !defaultChanged && !typeChanged)
111
+ return undefined;
112
+ return {
113
+ name,
114
+ ...(nullabilityChanged && { nullabilityChanged }),
115
+ ...(defaultChanged && { defaultChanged }),
116
+ ...(typeChanged && { typeChanged }),
117
+ };
118
+ }
119
+ function compareIndexes(name, prevIndex, nextIndex) {
120
+ const columnsChanged = fromToWhenDifferent(prevIndex.columns, nextIndex.columns, indexColumnsEqual);
121
+ const uniqueChanged = fromToWhenDifferent(prevIndex.unique ?? false, nextIndex.unique ?? false);
122
+ // Whitespace-only re-rendering of the predicate must not drop and rebuild a large index.
123
+ const whereSqlChanged = fromToWhenDifferent(prevIndex.whereSql, nextIndex.whereSql, whereSqlEqual);
124
+ const needsManualWhereChanged = fromToWhenDifferent(prevIndex.needsManualWhere ?? false, nextIndex.needsManualWhere ?? false);
125
+ if (!columnsChanged && !uniqueChanged && !whereSqlChanged && !needsManualWhereChanged) {
126
+ return undefined;
157
127
  }
158
- const isEmpty = newColumns.length === 0 &&
159
- droppedColumns.length === 0 &&
160
- changedColumns.length === 0 &&
161
- newIndexes.length === 0 &&
162
- droppedIndexes.length === 0 &&
163
- changedIndexes.length === 0;
164
- if (isEmpty)
165
- return null;
128
+ // Single literal typed as IndexChange so a misspelled key fails to compile instead of silently dropping the change.
166
129
  return {
130
+ name,
131
+ ...(columnsChanged && { columnsChanged }),
132
+ ...(uniqueChanged && { uniqueChanged }),
133
+ ...(whereSqlChanged && { whereSqlChanged }),
134
+ ...(needsManualWhereChanged && { needsManualWhereChanged }),
135
+ };
136
+ }
137
+ function hasNoTableChanges(diff) {
138
+ return [
139
+ diff.newColumns,
140
+ diff.droppedColumns,
141
+ diff.changedColumns,
142
+ diff.newIndexes,
143
+ diff.droppedIndexes,
144
+ diff.changedIndexes,
145
+ ].every((list) => list.length === 0);
146
+ }
147
+ function diffOneTable(prev, next) {
148
+ const columns = diffByName(columnsByName(prev), columnsByName(next), compareColumns);
149
+ const indexes = diffByName(indexesByName(prev), indexesByName(next), compareIndexes);
150
+ const diff = {
167
151
  tableName: prev.tableName,
168
- newColumns,
169
- droppedColumns,
170
- changedColumns,
171
- newIndexes,
172
- droppedIndexes,
173
- changedIndexes,
152
+ newColumns: columns.added,
153
+ droppedColumns: columns.dropped,
154
+ changedColumns: columns.changed,
155
+ newIndexes: indexes.added,
156
+ droppedIndexes: indexes.dropped,
157
+ changedIndexes: indexes.changed,
174
158
  nextMeta: next,
175
159
  };
160
+ return hasNoTableChanges(diff) ? null : diff;
176
161
  }
177
162
  export function diffSnapshots(prev, next) {
178
163
  const prevByName = new Map();
@@ -280,7 +280,10 @@ export async function runMigrations(db, migrations) {
280
280
  return { applied: appliedIds, skipped: skippedIds };
281
281
  }
282
282
  finally {
283
- await conn.unsafe(`SELECT pg_advisory_unlock(${MIGRATION_ADVISORY_LOCK_KEY})`);
283
+ // A dropped session already released its lock; failing here would mask the migration error.
284
+ await conn
285
+ .unsafe(`SELECT pg_advisory_unlock(${MIGRATION_ADVISORY_LOCK_KEY})`)
286
+ .catch(() => undefined);
284
287
  }
285
288
  }
286
289
  finally {
@@ -1,9 +1,9 @@
1
1
  import type { AggregateRow, AggregateSpec } from "@cosmicdrift/kumiko-types/aggregate-types";
2
2
  import type { DbRunner, DbTx } from "@cosmicdrift/kumiko-types/db-connection";
3
3
  import type { ExecutorManagedRunner, ExecutorManagedWriteCapability, WritableTable } from "@cosmicdrift/kumiko-types/executor-brand";
4
- import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
5
4
  import type { SelectOptions, WhereObject } from "@cosmicdrift/kumiko-types/where-clause-types";
6
5
  import type { EntityTableMeta } from "./entity-table-meta.ts";
6
+ import { type TableInfo } from "./table-info.ts";
7
7
  import { asEntityTableMeta, requireEntityTableMeta } from "./table-introspection.ts";
8
8
  export { asEntityTableMeta, requireEntityTableMeta };
9
9
  export type ReservedClient = {
@@ -30,20 +30,8 @@ export declare function runInSavepointIfSupported<T>(db: unknown, fn: (sp: DbRun
30
30
  export type AnyDb = DbRunner | unknown;
31
31
  type AnyRow = any;
32
32
  export type { JsonTextMatch, OrderByClause, SelectOptions, WhereObject, WhereOperator, WhereValue, } from "@cosmicdrift/kumiko-types/where-clause-types";
33
- type TableLike = EntityTableMeta | any;
34
- export type TableInfo = {
35
- readonly name: string;
36
- readonly columnOf: (field: string) => string;
37
- readonly pgTypeOf: (column: string) => string | undefined;
38
- readonly bigintJsModeOf: (column: string) => "number" | "bigint" | undefined;
39
- readonly fieldOf: (column: string) => string;
40
- readonly hasColumn: (fieldOrColumn: string) => boolean;
41
- };
42
- export declare function extractTableInfo(table: TableLike): TableInfo;
33
+ export type TableLike = EntityTableMeta | any;
43
34
  export declare function coerceRow<TOut = Record<string, unknown>>(row: Record<string, unknown>, info: TableInfo): TOut;
44
- export declare function instantToTimestamptzParam(instant: Temporal.Instant): string;
45
- export declare function isClosedConnectionError(err: unknown): boolean;
46
- export declare function describeClosedConnectionFailure(raw: unknown, err: unknown, attempts: number): Record<string, unknown> | undefined;
47
35
  export declare function unsafeReadRetrying<TRow>(db: AnyDb, sqlText: string, params: readonly unknown[]): Promise<readonly TRow[]>;
48
36
  export declare function selectMany<TRow = AnyRow>(db: AnyDb, table: TableLike, where?: WhereObject, options?: SelectOptions): Promise<readonly TRow[]>;
49
37
  export declare function fetchOne<TRow = AnyRow>(db: AnyDb, table: TableLike, where: WhereObject): Promise<TRow | undefined>;
@@ -92,7 +80,6 @@ export type DeleteManyBatchedResult = {
92
80
  readonly batches: number;
93
81
  };
94
82
  export declare function countWhere(db: AnyDb, table: TableLike, where?: WhereObject): Promise<number>;
95
- export declare function isTimestamptzType(pgType: string | undefined): boolean;
96
83
  export declare function aggregateWhere(db: AnyDb, table: TableLike, spec: AggregateSpec, where?: WhereObject): Promise<readonly AggregateRow[]>;
97
84
  export declare function upsertOnConflict<TRow = AnyRow>(db: AnyDb, table: WritableTable, values: Record<string, unknown>, options: UpsertOnConflictOptions): Promise<TRow | undefined>;
98
85
  export declare function upsertOnConflict<TRow = AnyRow>(db: ExecutorManagedWriteCapability, table: EntityTableMeta, values: Record<string, unknown>, options: UpsertOnConflictOptions): Promise<TRow | undefined>;