sovrium 0.0.2
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/CHANGELOG.md +3497 -0
- package/LICENSE.md +147 -0
- package/LICENSE_EE.md +297 -0
- package/README.md +321 -0
- package/drizzle/0000_melted_kabuki.sql +163 -0
- package/drizzle/meta/0000_snapshot.json +1216 -0
- package/drizzle/meta/_journal.json +13 -0
- package/package.json +167 -0
- package/schemas/0.0.1/app.openapi.json +70 -0
- package/schemas/0.0.1/app.schema.json +7961 -0
- package/schemas/0.0.2/app.openapi.json +80 -0
- package/schemas/0.0.2/app.schema.json +8829 -0
- package/schemas/development/app.openapi.json +70 -0
- package/schemas/development/app.schema.json +7456 -0
- package/src/application/errors/app-validation-error.ts +14 -0
- package/src/application/errors/static-generation-error.ts +16 -0
- package/src/application/metadata/favicon-transformer.ts +127 -0
- package/src/application/models/server.ts +27 -0
- package/src/application/ports/models/user-metadata.ts +36 -0
- package/src/application/ports/models/user-session.ts +34 -0
- package/src/application/ports/repositories/activity-log-repository.ts +68 -0
- package/src/application/ports/repositories/activity-repository.ts +49 -0
- package/src/application/ports/repositories/analytics-repository.ts +164 -0
- package/src/application/ports/repositories/auth-repository.ts +33 -0
- package/src/application/ports/repositories/batch-repository.ts +86 -0
- package/src/application/ports/repositories/comment-repository.ts +150 -0
- package/src/application/ports/repositories/index.ts +41 -0
- package/src/application/ports/repositories/table-repository.ts +139 -0
- package/src/application/ports/services/css-compiler.ts +55 -0
- package/src/application/ports/services/index.ts +16 -0
- package/src/application/ports/services/page-renderer.ts +79 -0
- package/src/application/ports/services/server-factory.ts +80 -0
- package/src/application/ports/services/static-site-generator.ts +82 -0
- package/src/application/use-cases/activity/programs.ts +66 -0
- package/src/application/use-cases/analytics/collect-page-view.ts +114 -0
- package/src/application/use-cases/analytics/purge-old-data.ts +40 -0
- package/src/application/use-cases/analytics/query-campaigns.ts +43 -0
- package/src/application/use-cases/analytics/query-devices.ts +36 -0
- package/src/application/use-cases/analytics/query-overview.ts +50 -0
- package/src/application/use-cases/analytics/query-pages.ts +40 -0
- package/src/application/use-cases/analytics/query-referrers.ts +43 -0
- package/src/application/use-cases/analytics/ua-parser.ts +89 -0
- package/src/application/use-cases/analytics/visitor-hash.ts +77 -0
- package/src/application/use-cases/auth/bootstrap-admin.ts +270 -0
- package/src/application/use-cases/list-activity-logs.ts +123 -0
- package/src/application/use-cases/server/generate-static-helpers.ts +374 -0
- package/src/application/use-cases/server/generate-static.ts +287 -0
- package/src/application/use-cases/server/start-server.ts +118 -0
- package/src/application/use-cases/server/startup-error-handler.ts +69 -0
- package/src/application/use-cases/server/static-content-generators.ts +182 -0
- package/src/application/use-cases/server/static-language-generators.ts +181 -0
- package/src/application/use-cases/server/static-url-rewriter.ts +237 -0
- package/src/application/use-cases/server/translation-replacer.ts +164 -0
- package/src/application/use-cases/tables/activity-programs.ts +93 -0
- package/src/application/use-cases/tables/batch-operations.ts +156 -0
- package/src/application/use-cases/tables/comment-programs.ts +436 -0
- package/src/application/use-cases/tables/permissions/permissions.ts +25 -0
- package/src/application/use-cases/tables/programs.ts +435 -0
- package/src/application/use-cases/tables/table-operations.ts +412 -0
- package/src/application/use-cases/tables/user-role.ts +52 -0
- package/src/application/use-cases/tables/utils/display-formatter.ts +471 -0
- package/src/application/use-cases/tables/utils/field-read-filter.ts +189 -0
- package/src/application/use-cases/tables/utils/list-helpers.ts +122 -0
- package/src/application/use-cases/tables/utils/record-transformer.ts +319 -0
- package/src/cli.ts +370 -0
- package/src/domain/errors/create-tagged-error.ts +36 -0
- package/src/domain/errors/index.ts +78 -0
- package/src/domain/models/api/analytics.ts +179 -0
- package/src/domain/models/api/auth.ts +231 -0
- package/src/domain/models/api/common.ts +60 -0
- package/src/domain/models/api/error.ts +89 -0
- package/src/domain/models/api/health.ts +38 -0
- package/src/domain/models/api/index.ts +42 -0
- package/src/domain/models/api/request.ts +132 -0
- package/src/domain/models/api/tables.ts +444 -0
- package/src/domain/models/app/analytics/index.ts +129 -0
- package/src/domain/models/app/auth/config.ts +116 -0
- package/src/domain/models/app/auth/index.ts +230 -0
- package/src/domain/models/app/auth/methods/email-and-password.ts +67 -0
- package/src/domain/models/app/auth/methods/index.ts +11 -0
- package/src/domain/models/app/auth/methods/magic-link.ts +54 -0
- package/src/domain/models/app/auth/oauth/index.ts +8 -0
- package/src/domain/models/app/auth/oauth/providers.ts +105 -0
- package/src/domain/models/app/auth/plugins/admin.ts +130 -0
- package/src/domain/models/app/auth/plugins/index.ts +74 -0
- package/src/domain/models/app/auth/plugins/two-factor.ts +63 -0
- package/src/domain/models/app/auth/roles.ts +179 -0
- package/src/domain/models/app/auth/strategies.ts +191 -0
- package/src/domain/models/app/auth/validation.ts +127 -0
- package/src/domain/models/app/common/branded-ids.ts +200 -0
- package/src/domain/models/app/common/definitions.ts +187 -0
- package/src/domain/models/app/component/common/component-children.ts +119 -0
- package/src/domain/models/app/component/common/component-props.ts +89 -0
- package/src/domain/models/app/component/common/component-reference.ts +170 -0
- package/src/domain/models/app/component/component.ts +81 -0
- package/src/domain/models/app/components.ts +65 -0
- package/src/domain/models/app/description.ts +83 -0
- package/src/domain/models/app/index.ts +258 -0
- package/src/domain/models/app/language/language-config.ts +200 -0
- package/src/domain/models/app/languages.ts +205 -0
- package/src/domain/models/app/name.ts +66 -0
- package/src/domain/models/app/page/common/interactions/click-interaction.ts +116 -0
- package/src/domain/models/app/page/common/interactions/entrance-animation.ts +84 -0
- package/src/domain/models/app/page/common/interactions/hover-interaction.ts +144 -0
- package/src/domain/models/app/page/common/interactions/interactions.ts +64 -0
- package/src/domain/models/app/page/common/interactions/scroll-interaction.ts +93 -0
- package/src/domain/models/app/page/common/responsive.ts +114 -0
- package/src/domain/models/app/page/common/url.ts +35 -0
- package/src/domain/models/app/page/common/variable-reference.ts +53 -0
- package/src/domain/models/app/page/id.ts +44 -0
- package/src/domain/models/app/page/index.ts +270 -0
- package/src/domain/models/app/page/meta/analytics.ts +248 -0
- package/src/domain/models/app/page/meta/custom-elements.ts +180 -0
- package/src/domain/models/app/page/meta/dns-prefetch.ts +77 -0
- package/src/domain/models/app/page/meta/favicon-set.ts +203 -0
- package/src/domain/models/app/page/meta/favicon.ts +50 -0
- package/src/domain/models/app/page/meta/favicons-config.ts +73 -0
- package/src/domain/models/app/page/meta/index.ts +278 -0
- package/src/domain/models/app/page/meta/open-graph.ts +166 -0
- package/src/domain/models/app/page/meta/preload.ts +190 -0
- package/src/domain/models/app/page/meta/structured-data/article.ts +211 -0
- package/src/domain/models/app/page/meta/structured-data/breadcrumb.ts +115 -0
- package/src/domain/models/app/page/meta/structured-data/common-fields.ts +201 -0
- package/src/domain/models/app/page/meta/structured-data/education-event.ts +256 -0
- package/src/domain/models/app/page/meta/structured-data/faq-page.ts +127 -0
- package/src/domain/models/app/page/meta/structured-data/index.ts +95 -0
- package/src/domain/models/app/page/meta/structured-data/local-business.ts +247 -0
- package/src/domain/models/app/page/meta/structured-data/organization.ts +171 -0
- package/src/domain/models/app/page/meta/structured-data/person.ts +138 -0
- package/src/domain/models/app/page/meta/structured-data/postal-address.ts +106 -0
- package/src/domain/models/app/page/meta/structured-data/product.ts +214 -0
- package/src/domain/models/app/page/meta/twitter-card.ts +217 -0
- package/src/domain/models/app/page/name.ts +38 -0
- package/src/domain/models/app/page/path.ts +21 -0
- package/src/domain/models/app/page/scripts/external-scripts.ts +163 -0
- package/src/domain/models/app/page/scripts/features.ts +135 -0
- package/src/domain/models/app/page/scripts/inline-scripts.ts +114 -0
- package/src/domain/models/app/page/scripts/scripts.ts +102 -0
- package/src/domain/models/app/page/sections.ts +298 -0
- package/src/domain/models/app/pages.ts +61 -0
- package/src/domain/models/app/permissions/index.ts +61 -0
- package/src/domain/models/app/permissions/resource-action.ts +114 -0
- package/src/domain/models/app/permissions/roles.ts +120 -0
- package/src/domain/models/app/table/check-constraints.ts +105 -0
- package/src/domain/models/app/table/cycle-detection.ts +124 -0
- package/src/domain/models/app/table/database-identifier.ts +153 -0
- package/src/domain/models/app/table/field-name.ts +36 -0
- package/src/domain/models/app/table/field-types/advanced/array-field.ts +33 -0
- package/src/domain/models/app/table/field-types/advanced/autonumber-field.ts +54 -0
- package/src/domain/models/app/table/field-types/advanced/button-field.ts +56 -0
- package/src/domain/models/app/table/field-types/advanced/color-field.ts +57 -0
- package/src/domain/models/app/table/field-types/advanced/count-field.ts +54 -0
- package/src/domain/models/app/table/field-types/advanced/formula-field.ts +58 -0
- package/src/domain/models/app/table/field-types/advanced/geolocation-field.ts +49 -0
- package/src/domain/models/app/table/field-types/advanced/index.ts +16 -0
- package/src/domain/models/app/table/field-types/advanced/json-field.ts +25 -0
- package/src/domain/models/app/table/field-types/advanced/unknown-field.ts +85 -0
- package/src/domain/models/app/table/field-types/base-field.ts +42 -0
- package/src/domain/models/app/table/field-types/date-time/created-at-field.ts +49 -0
- package/src/domain/models/app/table/field-types/date-time/date-field.ts +95 -0
- package/src/domain/models/app/table/field-types/date-time/deleted-at-field.ts +56 -0
- package/src/domain/models/app/table/field-types/date-time/duration-field.ts +73 -0
- package/src/domain/models/app/table/field-types/date-time/index.ts +12 -0
- package/src/domain/models/app/table/field-types/date-time/updated-at-field.ts +50 -0
- package/src/domain/models/app/table/field-types/index.ts +19 -0
- package/src/domain/models/app/table/field-types/media/barcode-field.ts +58 -0
- package/src/domain/models/app/table/field-types/media/index.ts +10 -0
- package/src/domain/models/app/table/field-types/media/multiple-attachments-field.ts +80 -0
- package/src/domain/models/app/table/field-types/media/single-attachment-field.ts +81 -0
- package/src/domain/models/app/table/field-types/numeric/currency-field.ts +144 -0
- package/src/domain/models/app/table/field-types/numeric/decimal-field.ts +113 -0
- package/src/domain/models/app/table/field-types/numeric/index.ts +13 -0
- package/src/domain/models/app/table/field-types/numeric/integer-field.ts +98 -0
- package/src/domain/models/app/table/field-types/numeric/percentage-field.ts +115 -0
- package/src/domain/models/app/table/field-types/numeric/progress-field.ts +71 -0
- package/src/domain/models/app/table/field-types/numeric/rating-field.ts +74 -0
- package/src/domain/models/app/table/field-types/relational/index.ts +10 -0
- package/src/domain/models/app/table/field-types/relational/lookup-field.ts +46 -0
- package/src/domain/models/app/table/field-types/relational/relationship-field.ts +112 -0
- package/src/domain/models/app/table/field-types/relational/rollup-field.ts +58 -0
- package/src/domain/models/app/table/field-types/selection/checkbox-field.ts +51 -0
- package/src/domain/models/app/table/field-types/selection/index.ts +11 -0
- package/src/domain/models/app/table/field-types/selection/multi-select-field.ts +68 -0
- package/src/domain/models/app/table/field-types/selection/single-select-field.ts +54 -0
- package/src/domain/models/app/table/field-types/selection/status-field.ts +37 -0
- package/src/domain/models/app/table/field-types/text/email-field.ts +80 -0
- package/src/domain/models/app/table/field-types/text/index.ts +13 -0
- package/src/domain/models/app/table/field-types/text/long-text-field.ts +77 -0
- package/src/domain/models/app/table/field-types/text/phone-number-field.ts +82 -0
- package/src/domain/models/app/table/field-types/text/rich-text-field.ts +66 -0
- package/src/domain/models/app/table/field-types/text/single-line-text-field.ts +79 -0
- package/src/domain/models/app/table/field-types/text/url-field.ts +81 -0
- package/src/domain/models/app/table/field-types/user/created-by-field.ts +50 -0
- package/src/domain/models/app/table/field-types/user/deleted-by-field.ts +57 -0
- package/src/domain/models/app/table/field-types/user/index.ts +11 -0
- package/src/domain/models/app/table/field-types/user/updated-by-field.ts +51 -0
- package/src/domain/models/app/table/field-types/user/user-field.ts +52 -0
- package/src/domain/models/app/table/field-types/validation-utils.ts +166 -0
- package/src/domain/models/app/table/fields.ts +216 -0
- package/src/domain/models/app/table/foreign-keys.ts +111 -0
- package/src/domain/models/app/table/formula-keywords.ts +326 -0
- package/src/domain/models/app/table/id.ts +31 -0
- package/src/domain/models/app/table/index.ts +290 -0
- package/src/domain/models/app/table/indexes.ts +80 -0
- package/src/domain/models/app/table/name.ts +37 -0
- package/src/domain/models/app/table/permissions/field-permission.ts +83 -0
- package/src/domain/models/app/table/permissions/index.ts +167 -0
- package/src/domain/models/app/table/permissions/permission-evaluator.ts +372 -0
- package/src/domain/models/app/table/permissions/permission.ts +49 -0
- package/src/domain/models/app/table/primary-key.ts +62 -0
- package/src/domain/models/app/table/table-formula-validation.ts +168 -0
- package/src/domain/models/app/table/table-indexes-validation.ts +38 -0
- package/src/domain/models/app/table/table-permissions-validation.ts +77 -0
- package/src/domain/models/app/table/table-primary-key-validation.ts +49 -0
- package/src/domain/models/app/table/table-views-validation.ts +408 -0
- package/src/domain/models/app/table/unique-constraints.ts +79 -0
- package/src/domain/models/app/table/views/fields.ts +28 -0
- package/src/domain/models/app/table/views/filters.ts +162 -0
- package/src/domain/models/app/table/views/group-by.ts +32 -0
- package/src/domain/models/app/table/views/id.ts +50 -0
- package/src/domain/models/app/table/views/index.ts +177 -0
- package/src/domain/models/app/table/views/name.ts +32 -0
- package/src/domain/models/app/table/views/permissions.ts +98 -0
- package/src/domain/models/app/table/views/sorts.ts +31 -0
- package/src/domain/models/app/tables.ts +695 -0
- package/src/domain/models/app/theme/animations.ts +208 -0
- package/src/domain/models/app/theme/border-radius.ts +58 -0
- package/src/domain/models/app/theme/breakpoints.ts +62 -0
- package/src/domain/models/app/theme/colors.ts +110 -0
- package/src/domain/models/app/theme/fonts.ts +164 -0
- package/src/domain/models/app/theme/shadows.ts +61 -0
- package/src/domain/models/app/theme/spacing.ts +115 -0
- package/src/domain/models/app/theme.ts +66 -0
- package/src/domain/models/app/version.ts +87 -0
- package/src/domain/models/record-comment.ts +91 -0
- package/src/domain/utils/content-parsing.ts +49 -0
- package/src/domain/utils/format-detection.ts +69 -0
- package/src/domain/utils/index.ts +9 -0
- package/src/domain/utils/route-matcher.ts +184 -0
- package/src/domain/utils/translation-resolver.ts +170 -0
- package/src/index.ts +208 -0
- package/src/infrastructure/analytics/tracking-script.ts +48 -0
- package/src/infrastructure/auth/better-auth/auth.ts +216 -0
- package/src/infrastructure/auth/better-auth/email-handlers.ts +162 -0
- package/src/infrastructure/auth/better-auth/index.ts +16 -0
- package/src/infrastructure/auth/better-auth/layer.ts +97 -0
- package/src/infrastructure/auth/better-auth/plugins/admin.ts +56 -0
- package/src/infrastructure/auth/better-auth/plugins/magic-link.ts +31 -0
- package/src/infrastructure/auth/better-auth/plugins/two-factor.ts +19 -0
- package/src/infrastructure/auth/better-auth/schema.ts +152 -0
- package/src/infrastructure/auth/index.ts +27 -0
- package/src/infrastructure/css/cache/css-cache-service.ts +130 -0
- package/src/infrastructure/css/compiler.ts +210 -0
- package/src/infrastructure/css/css-compiler-live.ts +20 -0
- package/src/infrastructure/css/index.ts +25 -0
- package/src/infrastructure/css/styles/animation-styles-generator.ts +177 -0
- package/src/infrastructure/css/styles/click-animations.ts +147 -0
- package/src/infrastructure/css/styles/component-layer-generators.ts +147 -0
- package/src/infrastructure/css/theme/theme-generators.ts +130 -0
- package/src/infrastructure/css/theme/theme-layer-generators.ts +219 -0
- package/src/infrastructure/css/theme/theme-token-resolver.ts +76 -0
- package/src/infrastructure/database/activity-queries.ts +111 -0
- package/src/infrastructure/database/auth/auth-validation.ts +101 -0
- package/src/infrastructure/database/drizzle/db-bun.ts +17 -0
- package/src/infrastructure/database/drizzle/db.ts +17 -0
- package/src/infrastructure/database/drizzle/index.ts +16 -0
- package/src/infrastructure/database/drizzle/layer.ts +34 -0
- package/src/infrastructure/database/drizzle/migrate.ts +77 -0
- package/src/infrastructure/database/drizzle/schema/activity-log.ts +111 -0
- package/src/infrastructure/database/drizzle/schema/analytics-page-views.ts +116 -0
- package/src/infrastructure/database/drizzle/schema/migration-audit.ts +68 -0
- package/src/infrastructure/database/drizzle/schema/record-comments.ts +79 -0
- package/src/infrastructure/database/drizzle/schema.ts +12 -0
- package/src/infrastructure/database/field-utils.ts +87 -0
- package/src/infrastructure/database/filter-operators.ts +136 -0
- package/src/infrastructure/database/formula/formula-trigger-generators.ts +114 -0
- package/src/infrastructure/database/formula/formula-utils.ts +440 -0
- package/src/infrastructure/database/generators/index-generators.ts +152 -0
- package/src/infrastructure/database/generators/trigger-generators.ts +154 -0
- package/src/infrastructure/database/index.ts +35 -0
- package/src/infrastructure/database/lookup/lookup-expression-generators.ts +356 -0
- package/src/infrastructure/database/lookup/lookup-expressions.ts +116 -0
- package/src/infrastructure/database/lookup/lookup-view-generators.ts +403 -0
- package/src/infrastructure/database/lookup/lookup-view-helpers.ts +65 -0
- package/src/infrastructure/database/lookup/lookup-view-triggers.ts +121 -0
- package/src/infrastructure/database/migration-audit-trail.ts +375 -0
- package/src/infrastructure/database/repositories/activity-log-repository-live.ts +99 -0
- package/src/infrastructure/database/repositories/activity-repository-live.ts +21 -0
- package/src/infrastructure/database/repositories/analytics-repository-live.ts +316 -0
- package/src/infrastructure/database/repositories/auth-repository-live.ts +42 -0
- package/src/infrastructure/database/repositories/batch-repository-live.ts +29 -0
- package/src/infrastructure/database/repositories/comment-repository-live.ts +39 -0
- package/src/infrastructure/database/repositories/table-repository-live.ts +38 -0
- package/src/infrastructure/database/schema/schema-dependency-sorting.ts +142 -0
- package/src/infrastructure/database/schema/schema-initializer.ts +598 -0
- package/src/infrastructure/database/schema-migration/column-detection.ts +286 -0
- package/src/infrastructure/database/schema-migration/constants.ts +31 -0
- package/src/infrastructure/database/schema-migration/constraint-sync.ts +288 -0
- package/src/infrastructure/database/schema-migration/index-sync.ts +108 -0
- package/src/infrastructure/database/schema-migration/index.ts +66 -0
- package/src/infrastructure/database/schema-migration/migration-statements.ts +106 -0
- package/src/infrastructure/database/schema-migration/rename-detection.ts +87 -0
- package/src/infrastructure/database/schema-migration/table-operations.ts +65 -0
- package/src/infrastructure/database/schema-migration/type-utils.ts +98 -0
- package/src/infrastructure/database/schema-migration/types.ts +14 -0
- package/src/infrastructure/database/schema-migration-helpers.ts +53 -0
- package/src/infrastructure/database/session-context.ts +20 -0
- package/src/infrastructure/database/sql/sql-check-constraints.ts +252 -0
- package/src/infrastructure/database/sql/sql-column-generators.ts +174 -0
- package/src/infrastructure/database/sql/sql-execution.ts +245 -0
- package/src/infrastructure/database/sql/sql-field-predicates.ts +81 -0
- package/src/infrastructure/database/sql/sql-generators.ts +91 -0
- package/src/infrastructure/database/sql/sql-junction-tables.ts +79 -0
- package/src/infrastructure/database/sql/sql-key-constraints.ts +210 -0
- package/src/infrastructure/database/sql/sql-type-mappings.ts +106 -0
- package/src/infrastructure/database/sql/sql-utils.ts +53 -0
- package/src/infrastructure/database/table-live-layers.ts +30 -0
- package/src/infrastructure/database/table-operations/column-generators.ts +82 -0
- package/src/infrastructure/database/table-operations/create-table-sql.ts +81 -0
- package/src/infrastructure/database/table-operations/index.ts +55 -0
- package/src/infrastructure/database/table-operations/migration-utils.ts +157 -0
- package/src/infrastructure/database/table-operations/table-effects.ts +234 -0
- package/src/infrastructure/database/table-operations/table-features.ts +96 -0
- package/src/infrastructure/database/table-operations/type-compatibility.ts +58 -0
- package/src/infrastructure/database/table-operations.ts +47 -0
- package/src/infrastructure/database/table-queries/batch/batch-create.ts +80 -0
- package/src/infrastructure/database/table-queries/batch/batch-delete.ts +212 -0
- package/src/infrastructure/database/table-queries/batch/batch-helpers.ts +124 -0
- package/src/infrastructure/database/table-queries/batch/batch-restore.ts +161 -0
- package/src/infrastructure/database/table-queries/batch/batch-update.ts +146 -0
- package/src/infrastructure/database/table-queries/batch/batch-upsert.ts +357 -0
- package/src/infrastructure/database/table-queries/batch/batch.ts +14 -0
- package/src/infrastructure/database/table-queries/crud/crud-read.ts +351 -0
- package/src/infrastructure/database/table-queries/crud/crud-write.ts +399 -0
- package/src/infrastructure/database/table-queries/crud/crud.ts +16 -0
- package/src/infrastructure/database/table-queries/index.ts +11 -0
- package/src/infrastructure/database/table-queries/mutation-helpers/authorship-helpers.ts +152 -0
- package/src/infrastructure/database/table-queries/mutation-helpers/create-record-helpers.ts +90 -0
- package/src/infrastructure/database/table-queries/mutation-helpers/delete-helpers.ts +163 -0
- package/src/infrastructure/database/table-queries/mutation-helpers/record-fetch-helpers.ts +79 -0
- package/src/infrastructure/database/table-queries/mutation-helpers/update-helpers.ts +74 -0
- package/src/infrastructure/database/table-queries/query-helpers/activity-log-helpers.ts +53 -0
- package/src/infrastructure/database/table-queries/query-helpers/activity-queries.ts +106 -0
- package/src/infrastructure/database/table-queries/query-helpers/aggregation-helpers.ts +314 -0
- package/src/infrastructure/database/table-queries/query-helpers/comment-queries.ts +414 -0
- package/src/infrastructure/database/table-queries/query-helpers/record-validation-queries.ts +126 -0
- package/src/infrastructure/database/table-queries/query-helpers/trash-helpers.ts +58 -0
- package/src/infrastructure/database/table-queries/shared/error-handling.ts +47 -0
- package/src/infrastructure/database/table-queries/shared/typed-execute.ts +27 -0
- package/src/infrastructure/database/table-queries/shared/user-join-helpers.ts +38 -0
- package/src/infrastructure/database/table-queries/shared/validation.ts +39 -0
- package/src/infrastructure/database/views/view-generators.ts +258 -0
- package/src/infrastructure/devtools/devtools-layer.ts +43 -0
- package/src/infrastructure/devtools/index.ts +8 -0
- package/src/infrastructure/email/email-config.ts +103 -0
- package/src/infrastructure/email/email-service.ts +152 -0
- package/src/infrastructure/email/index.ts +107 -0
- package/src/infrastructure/email/nodemailer.ts +125 -0
- package/src/infrastructure/email/templates.ts +244 -0
- package/src/infrastructure/errors/auth-config-required-error.ts +21 -0
- package/src/infrastructure/errors/auth-error.ts +16 -0
- package/src/infrastructure/errors/css-compilation-error.ts +14 -0
- package/src/infrastructure/errors/index.ts +26 -0
- package/src/infrastructure/errors/schema-initialization-error.ts +19 -0
- package/src/infrastructure/errors/server-creation-error.ts +14 -0
- package/src/infrastructure/filesystem/copy-directory.ts +136 -0
- package/src/infrastructure/layers/app-layer.ts +61 -0
- package/src/infrastructure/layers/page-renderer-layer.ts +41 -0
- package/src/infrastructure/logging/index.ts +8 -0
- package/src/infrastructure/logging/logger.ts +204 -0
- package/src/infrastructure/schema/file-loader.ts +53 -0
- package/src/infrastructure/schema/index.ts +15 -0
- package/src/infrastructure/schema/remote-loader.ts +48 -0
- package/src/infrastructure/server/index.ts +26 -0
- package/src/infrastructure/server/language-detection.ts +87 -0
- package/src/infrastructure/server/lifecycle.ts +67 -0
- package/src/infrastructure/server/route-setup/api-routes.ts +310 -0
- package/src/infrastructure/server/route-setup/auth-route-utils.ts +399 -0
- package/src/infrastructure/server/route-setup/auth-routes.ts +245 -0
- package/src/infrastructure/server/route-setup/openapi-routes.ts +45 -0
- package/src/infrastructure/server/route-setup/openapi-schema.ts +120 -0
- package/src/infrastructure/server/route-setup/page-routes.ts +219 -0
- package/src/infrastructure/server/route-setup/static-assets.ts +191 -0
- package/src/infrastructure/server/server-factory-live.ts +45 -0
- package/src/infrastructure/server/server.ts +275 -0
- package/src/infrastructure/server/ssg-adapter.ts +196 -0
- package/src/infrastructure/server/static-site-generator-live.ts +20 -0
- package/src/infrastructure/utils/accept-language-parser.ts +106 -0
- package/src/infrastructure/utils/glob-matcher.ts +50 -0
- package/src/presentation/api/client.ts +114 -0
- package/src/presentation/api/middleware/auth.ts +233 -0
- package/src/presentation/api/middleware/table.ts +155 -0
- package/src/presentation/api/middleware/validation.ts +88 -0
- package/src/presentation/api/routes/activity/get-activity-by-id-handler.ts +77 -0
- package/src/presentation/api/routes/activity/index.ts +28 -0
- package/src/presentation/api/routes/activity.ts +339 -0
- package/src/presentation/api/routes/analytics.ts +328 -0
- package/src/presentation/api/routes/auth.ts +169 -0
- package/src/presentation/api/routes/index.ts +11 -0
- package/src/presentation/api/routes/tables/activity-handlers.ts +57 -0
- package/src/presentation/api/routes/tables/batch-permission-helpers.ts +163 -0
- package/src/presentation/api/routes/tables/batch-routes.ts +355 -0
- package/src/presentation/api/routes/tables/comment-handlers.ts +377 -0
- package/src/presentation/api/routes/tables/create-record-helpers.ts +179 -0
- package/src/presentation/api/routes/tables/effect-runner.ts +58 -0
- package/src/presentation/api/routes/tables/error-handlers.ts +53 -0
- package/src/presentation/api/routes/tables/field-permission-validation.ts +167 -0
- package/src/presentation/api/routes/tables/filter-parser.ts +75 -0
- package/src/presentation/api/routes/tables/formula-parser.ts +118 -0
- package/src/presentation/api/routes/tables/index.ts +113 -0
- package/src/presentation/api/routes/tables/list-records-filter.ts +54 -0
- package/src/presentation/api/routes/tables/param-parsers.ts +59 -0
- package/src/presentation/api/routes/tables/record-handlers.ts +484 -0
- package/src/presentation/api/routes/tables/record-routes.ts +53 -0
- package/src/presentation/api/routes/tables/record-update-handler.ts +200 -0
- package/src/presentation/api/routes/tables/sort-validation.ts +85 -0
- package/src/presentation/api/routes/tables/table-routes.ts +76 -0
- package/src/presentation/api/routes/tables/timezone-validation.ts +41 -0
- package/src/presentation/api/routes/tables/upsert-helpers.ts +471 -0
- package/src/presentation/api/routes/tables/utils.ts +159 -0
- package/src/presentation/api/routes/tables/view-routes.ts +51 -0
- package/src/presentation/api/routes/tables.ts +9 -0
- package/src/presentation/api/utils/context-helpers.ts +43 -0
- package/src/presentation/api/utils/error-sanitizer.ts +235 -0
- package/src/presentation/api/utils/field-permission-validator.ts +53 -0
- package/src/presentation/api/utils/filter-field-validator.ts +90 -0
- package/src/presentation/api/utils/index.ts +13 -0
- package/src/presentation/api/utils/run-effect.ts +94 -0
- package/src/presentation/api/utils/validate-request.ts +89 -0
- package/src/presentation/api/validation/index.ts +29 -0
- package/src/presentation/api/validation/rules/field-rules.ts +158 -0
- package/src/presentation/api/validation/rules/record-rules.ts +73 -0
- package/src/presentation/cli/index.ts +19 -0
- package/src/presentation/cli/schema-loader.ts +172 -0
- package/src/presentation/hooks/use-breakpoint.ts +155 -0
- package/src/presentation/rendering/render-error-pages.tsx +60 -0
- package/src/presentation/rendering/render-homepage.tsx +137 -0
- package/src/presentation/scripts/script-renderers.ts +112 -0
- package/src/presentation/styling/animation-composer.ts +117 -0
- package/src/presentation/styling/index.ts +13 -0
- package/src/presentation/styling/parse-style.ts +243 -0
- package/src/presentation/styling/style-utils.ts +50 -0
- package/src/presentation/styling/theme-colors.ts +53 -0
- package/src/presentation/translations/component-utils.ts +54 -0
- package/src/presentation/translations/index.ts +16 -0
- package/src/presentation/translations/translation-resolver.ts +22 -0
- package/src/presentation/ui/languages/language-switcher.tsx +119 -0
- package/src/presentation/ui/metadata/analytics-builders.tsx +174 -0
- package/src/presentation/ui/metadata/analytics-head.tsx +39 -0
- package/src/presentation/ui/metadata/custom-elements-builders.tsx +157 -0
- package/src/presentation/ui/metadata/extract-component-meta.ts +108 -0
- package/src/presentation/ui/metadata/head-elements.tsx +164 -0
- package/src/presentation/ui/metadata/index.tsx +35 -0
- package/src/presentation/ui/metadata/meta-utils.tsx +42 -0
- package/src/presentation/ui/metadata/open-graph-meta.tsx +57 -0
- package/src/presentation/ui/metadata/structured-data-from-component.tsx +134 -0
- package/src/presentation/ui/metadata/structured-data.tsx +88 -0
- package/src/presentation/ui/metadata/twitter-card-meta.tsx +80 -0
- package/src/presentation/ui/pages/DefaultHomePage.tsx +43 -0
- package/src/presentation/ui/pages/DefaultPageConfigs.ts +220 -0
- package/src/presentation/ui/pages/DynamicPage.tsx +307 -0
- package/src/presentation/ui/pages/ErrorPage.tsx +25 -0
- package/src/presentation/ui/pages/NotFoundPage.tsx +25 -0
- package/src/presentation/ui/pages/PageBodyScripts.tsx +242 -0
- package/src/presentation/ui/pages/PageBodyStyles.ts +52 -0
- package/src/presentation/ui/pages/PageHead.tsx +380 -0
- package/src/presentation/ui/pages/PageLangResolver.ts +58 -0
- package/src/presentation/ui/pages/PageMain.tsx +58 -0
- package/src/presentation/ui/pages/PageMetadata.ts +168 -0
- package/src/presentation/ui/pages/PageMetadataI18n.ts +169 -0
- package/src/presentation/ui/pages/PageScripts.ts +78 -0
- package/src/presentation/ui/pages/SectionRenderer.tsx +67 -0
- package/src/presentation/ui/pages/SectionSpacing.tsx +131 -0
- package/src/presentation/ui/sections/component-renderer.tsx +426 -0
- package/src/presentation/ui/sections/component-renderer.types.ts +33 -0
- package/src/presentation/ui/sections/components/component-reference-handler.tsx +74 -0
- package/src/presentation/ui/sections/components/component-resolution.ts +65 -0
- package/src/presentation/ui/sections/components/index.ts +9 -0
- package/src/presentation/ui/sections/hero.tsx +394 -0
- package/src/presentation/ui/sections/props/component-builder.ts +183 -0
- package/src/presentation/ui/sections/props/element-props.ts +179 -0
- package/src/presentation/ui/sections/props/index.ts +9 -0
- package/src/presentation/ui/sections/props/prop-conversion.ts +171 -0
- package/src/presentation/ui/sections/props/props-builder-config.ts +42 -0
- package/src/presentation/ui/sections/props/props-builder.ts +296 -0
- package/src/presentation/ui/sections/renderers/element-renderers/html-element-renderer.tsx +124 -0
- package/src/presentation/ui/sections/renderers/element-renderers/index.ts +59 -0
- package/src/presentation/ui/sections/renderers/element-renderers/interactive-renderers.tsx +231 -0
- package/src/presentation/ui/sections/renderers/element-renderers/media-renderers.tsx +102 -0
- package/src/presentation/ui/sections/renderers/element-renderers/text-content-renderers.tsx +42 -0
- package/src/presentation/ui/sections/renderers/element-renderers.ts +53 -0
- package/src/presentation/ui/sections/renderers/html-element-helpers.ts +100 -0
- package/src/presentation/ui/sections/renderers/specialized-renderers.tsx +212 -0
- package/src/presentation/ui/sections/rendering/component-dispatch-config.ts +31 -0
- package/src/presentation/ui/sections/rendering/component-registry/index.ts +39 -0
- package/src/presentation/ui/sections/rendering/component-registry/interactive-components.ts +54 -0
- package/src/presentation/ui/sections/rendering/component-registry/media-components.ts +36 -0
- package/src/presentation/ui/sections/rendering/component-registry/special-components.tsx +153 -0
- package/src/presentation/ui/sections/rendering/component-registry/structural-components.ts +215 -0
- package/src/presentation/ui/sections/rendering/component-registry/text-components.ts +57 -0
- package/src/presentation/ui/sections/rendering/component-registry-helpers.tsx +29 -0
- package/src/presentation/ui/sections/rendering/component-registry.tsx +21 -0
- package/src/presentation/ui/sections/rendering/component-type-dispatcher.tsx +33 -0
- package/src/presentation/ui/sections/rendering/index.ts +9 -0
- package/src/presentation/ui/sections/responsive/responsive-children-builder.tsx +96 -0
- package/src/presentation/ui/sections/responsive/responsive-content-builder.tsx +95 -0
- package/src/presentation/ui/sections/responsive/responsive-props-merger.ts +195 -0
- package/src/presentation/ui/sections/responsive/responsive-resolver.ts +213 -0
- package/src/presentation/ui/sections/styling/animation-composer-wrapper.ts +65 -0
- package/src/presentation/ui/sections/styling/class-builders.ts +45 -0
- package/src/presentation/ui/sections/styling/color-resolver.ts +43 -0
- package/src/presentation/ui/sections/styling/hover-interaction-handler.ts +107 -0
- package/src/presentation/ui/sections/styling/index.ts +9 -0
- package/src/presentation/ui/sections/styling/interaction-props-builder.ts +55 -0
- package/src/presentation/ui/sections/styling/shadow-resolver.ts +83 -0
- package/src/presentation/ui/sections/styling/spacing-resolver.ts +104 -0
- package/src/presentation/ui/sections/styling/style-processor.ts +170 -0
- package/src/presentation/ui/sections/styling/theme-tokens.ts +184 -0
- package/src/presentation/ui/sections/translations/i18n-content-resolver.ts +198 -0
- package/src/presentation/ui/sections/translations/index.ts +9 -0
- package/src/presentation/ui/sections/translations/translation-handler.ts +143 -0
- package/src/presentation/ui/sections/translations/variable-substitution.ts +225 -0
- package/src/presentation/ui/sections/utils/time-parser.ts +82 -0
- package/src/presentation/utils/link-attributes.ts +50 -0
- package/src/presentation/utils/string-utils.ts +58 -0
- package/src/presentation/utils/styles.ts +50 -0
- package/tsconfig.json +46 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Table } from '@/domain/models/app/table'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate automatic id column definition based on primary key type
|
|
12
|
+
* @param primaryKeyType - Type of primary key (uuid, bigserial, or default serial)
|
|
13
|
+
* @param isPrimaryKey - Whether this id column is the primary key (adds PRIMARY KEY constraint inline)
|
|
14
|
+
*/
|
|
15
|
+
export const generateIdColumn = (
|
|
16
|
+
primaryKeyType: string | undefined,
|
|
17
|
+
isPrimaryKey: boolean
|
|
18
|
+
): string => {
|
|
19
|
+
const pkConstraint = isPrimaryKey ? ' PRIMARY KEY' : ''
|
|
20
|
+
if (primaryKeyType === 'uuid') {
|
|
21
|
+
return `id UUID NOT NULL DEFAULT gen_random_uuid()${pkConstraint}`
|
|
22
|
+
}
|
|
23
|
+
if (primaryKeyType === 'bigserial') {
|
|
24
|
+
return `id BIGSERIAL NOT NULL${pkConstraint}`
|
|
25
|
+
}
|
|
26
|
+
return `id SERIAL NOT NULL${pkConstraint}`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Determine if table needs an automatic id column
|
|
31
|
+
* Creates automatic id column if:
|
|
32
|
+
* - No explicit id field is defined in the fields array
|
|
33
|
+
* - Either: no primary key is defined OR primary key references the special 'id' field
|
|
34
|
+
*/
|
|
35
|
+
export const needsAutomaticIdColumn = (
|
|
36
|
+
table: Table,
|
|
37
|
+
primaryKeyFields: readonly string[]
|
|
38
|
+
): boolean => {
|
|
39
|
+
const hasIdField = table.fields.some((field) => field.name === 'id')
|
|
40
|
+
const primaryKeyReferencesId = primaryKeyFields.includes('id')
|
|
41
|
+
const hasNonIdPrimaryKey = primaryKeyFields.length > 0 && !primaryKeyReferencesId
|
|
42
|
+
return !hasIdField && !hasNonIdPrimaryKey
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generate created_at column definition if not explicitly defined
|
|
47
|
+
* Note: Includes DEFAULT CURRENT_TIMESTAMP to support INSERT ... DEFAULT VALUES
|
|
48
|
+
* Triggers also set the value to ensure consistency
|
|
49
|
+
*/
|
|
50
|
+
export const generateCreatedAtColumn = (table: Table): readonly string[] => {
|
|
51
|
+
const hasCreatedAtField = table.fields.some((field) => field.name === 'created_at')
|
|
52
|
+
return !hasCreatedAtField ? ['created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP'] : []
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generate updated_at column definition if not explicitly defined
|
|
57
|
+
* Note: Includes DEFAULT CURRENT_TIMESTAMP to support INSERT ... DEFAULT VALUES
|
|
58
|
+
* Triggers update the value on INSERT and UPDATE to ensure currency
|
|
59
|
+
*/
|
|
60
|
+
export const generateUpdatedAtColumn = (table: Table): readonly string[] => {
|
|
61
|
+
const hasUpdatedAtField = table.fields.some((field) => field.name === 'updated_at')
|
|
62
|
+
return !hasUpdatedAtField ? ['updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP'] : []
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generate deleted_at column definition if not explicitly defined
|
|
67
|
+
*/
|
|
68
|
+
export const generateDeletedAtColumn = (table: Table): readonly string[] => {
|
|
69
|
+
const hasDeletedAtField = table.fields.some((field) => field.name === 'deleted_at')
|
|
70
|
+
return !hasDeletedAtField ? ['deleted_at TIMESTAMPTZ'] : []
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Generate primary key constraint if needed
|
|
75
|
+
*/
|
|
76
|
+
export const generatePrimaryKeyConstraintIfNeeded = (
|
|
77
|
+
table: Table,
|
|
78
|
+
primaryKeyFields: readonly string[]
|
|
79
|
+
): readonly string[] =>
|
|
80
|
+
needsAutomaticIdColumn(table, primaryKeyFields) && primaryKeyFields.length === 0
|
|
81
|
+
? ['PRIMARY KEY (id)']
|
|
82
|
+
: []
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { shouldCreateDatabaseColumn, sanitizeTableName } from '../field-utils'
|
|
9
|
+
import { shouldUseView, getBaseTableName } from '../lookup/lookup-view-generators'
|
|
10
|
+
import { generateColumnDefinition, generateTableConstraints } from '../sql/sql-generators'
|
|
11
|
+
import {
|
|
12
|
+
generateIdColumn,
|
|
13
|
+
needsAutomaticIdColumn,
|
|
14
|
+
generateCreatedAtColumn,
|
|
15
|
+
generateUpdatedAtColumn,
|
|
16
|
+
generateDeletedAtColumn,
|
|
17
|
+
generatePrimaryKeyConstraintIfNeeded,
|
|
18
|
+
} from './column-generators'
|
|
19
|
+
import type { Table } from '@/domain/models/app/table'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate CREATE TABLE statement
|
|
23
|
+
* When table has lookup fields, creates a base table (_base suffix) and will later create a VIEW
|
|
24
|
+
*
|
|
25
|
+
* @param table - Table definition
|
|
26
|
+
* @param tableUsesView - Map of table names to whether they use a VIEW
|
|
27
|
+
* @param skipForeignKeys - Skip foreign key constraints (for circular dependencies)
|
|
28
|
+
*/
|
|
29
|
+
export const generateCreateTableSQL = (
|
|
30
|
+
table: Table,
|
|
31
|
+
tableUsesView?: ReadonlyMap<string, boolean>,
|
|
32
|
+
skipForeignKeys?: boolean,
|
|
33
|
+
hasAuthConfig: boolean = true
|
|
34
|
+
): string => {
|
|
35
|
+
// Sanitize table name for PostgreSQL (lowercase, underscores)
|
|
36
|
+
const sanitized = sanitizeTableName(table.name)
|
|
37
|
+
// Determine table name (add _base suffix if using VIEW for lookup fields)
|
|
38
|
+
const tableName = shouldUseView(table) ? getBaseTableName(sanitized) : sanitized
|
|
39
|
+
|
|
40
|
+
// Identify primary key fields
|
|
41
|
+
const primaryKeyFields =
|
|
42
|
+
table.primaryKey?.type === 'composite' ? (table.primaryKey.fields ?? []) : []
|
|
43
|
+
|
|
44
|
+
// Generate automatic id column based on primary key type
|
|
45
|
+
// Add PRIMARY KEY inline if the primary key is on the 'id' field
|
|
46
|
+
const primaryKeyOnId = primaryKeyFields.length === 1 && primaryKeyFields[0] === 'id'
|
|
47
|
+
const idColumnDefinition = needsAutomaticIdColumn(table, primaryKeyFields)
|
|
48
|
+
? [generateIdColumn(table.primaryKey?.type, primaryKeyOnId)]
|
|
49
|
+
: []
|
|
50
|
+
|
|
51
|
+
// Filter out UI-only fields (like button), lookup fields, and rollup fields (handled by VIEW)
|
|
52
|
+
// Lookup and rollup fields don't exist as columns in the base table
|
|
53
|
+
const columnDefinitions = table.fields
|
|
54
|
+
.filter(
|
|
55
|
+
(field) =>
|
|
56
|
+
shouldCreateDatabaseColumn(field) && field.type !== 'lookup' && field.type !== 'rollup'
|
|
57
|
+
)
|
|
58
|
+
.map((field) => {
|
|
59
|
+
// Only add inline PRIMARY KEY for single-field composite keys (handled by generateSerialColumn)
|
|
60
|
+
// Multi-field composite keys must have PRIMARY KEY at table level to avoid "multiple primary keys" error
|
|
61
|
+
const isPrimaryKey = primaryKeyFields.includes(field.name) && primaryKeyFields.length === 1
|
|
62
|
+
return generateColumnDefinition(field, isPrimaryKey, table.fields, hasAuthConfig)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// Add PRIMARY KEY constraint on id if no custom primary key is defined
|
|
66
|
+
const tableConstraints = generateTableConstraints(table, tableUsesView, skipForeignKeys)
|
|
67
|
+
|
|
68
|
+
const allDefinitions = [
|
|
69
|
+
...idColumnDefinition,
|
|
70
|
+
...generateCreatedAtColumn(table),
|
|
71
|
+
...generateUpdatedAtColumn(table),
|
|
72
|
+
...generateDeletedAtColumn(table),
|
|
73
|
+
...columnDefinitions,
|
|
74
|
+
...tableConstraints,
|
|
75
|
+
...generatePrimaryKeyConstraintIfNeeded(table, primaryKeyFields),
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
return `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
79
|
+
${allDefinitions.join(',\n ')}
|
|
80
|
+
)`
|
|
81
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Table Operations Module
|
|
10
|
+
*
|
|
11
|
+
* This module provides utilities for database table operations:
|
|
12
|
+
* - CREATE TABLE statement generation
|
|
13
|
+
* - Table migration (ALTER TABLE, data preservation)
|
|
14
|
+
* - Table feature application (indexes, triggers, RLS policies)
|
|
15
|
+
* - Lookup VIEW creation
|
|
16
|
+
* - User-defined VIEW creation
|
|
17
|
+
*
|
|
18
|
+
* All functions use Effect for type-safe error handling.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Type compatibility utilities
|
|
22
|
+
export { normalizeType, areTypesCompatible } from './type-compatibility'
|
|
23
|
+
|
|
24
|
+
// Column generators
|
|
25
|
+
export {
|
|
26
|
+
generateIdColumn,
|
|
27
|
+
needsAutomaticIdColumn,
|
|
28
|
+
generateCreatedAtColumn,
|
|
29
|
+
generateUpdatedAtColumn,
|
|
30
|
+
generateDeletedAtColumn,
|
|
31
|
+
generatePrimaryKeyConstraintIfNeeded,
|
|
32
|
+
} from './column-generators'
|
|
33
|
+
|
|
34
|
+
// CREATE TABLE SQL generation
|
|
35
|
+
export { generateCreateTableSQL } from './create-table-sql'
|
|
36
|
+
|
|
37
|
+
// Table features (indexes, triggers, RLS policies)
|
|
38
|
+
export { applyTableFeatures, applyTableFeaturesWithoutIndexes } from './table-features'
|
|
39
|
+
|
|
40
|
+
// Migration utilities
|
|
41
|
+
export {
|
|
42
|
+
getCompatibleColumns,
|
|
43
|
+
copyDataAndResetSequences,
|
|
44
|
+
recreateTableWithDataEffect,
|
|
45
|
+
} from './migration-utils'
|
|
46
|
+
|
|
47
|
+
// Table effect operations
|
|
48
|
+
export type { MigrationConfig } from './table-effects'
|
|
49
|
+
export {
|
|
50
|
+
migrateExistingTableEffect,
|
|
51
|
+
createNewTableEffect,
|
|
52
|
+
createLookupViewsEffect,
|
|
53
|
+
createTableViewsEffect,
|
|
54
|
+
createOrMigrateTableEffect,
|
|
55
|
+
} from './table-effects'
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Effect } from 'effect'
|
|
9
|
+
import { sanitizeTableName } from '../field-utils'
|
|
10
|
+
import { shouldUseView, getBaseTableName } from '../lookup/lookup-view-generators'
|
|
11
|
+
import { executeSQL, SQLExecutionError, type TransactionLike } from '../sql/sql-execution'
|
|
12
|
+
import { generateCreateTableSQL } from './create-table-sql'
|
|
13
|
+
import { areTypesCompatible } from './type-compatibility'
|
|
14
|
+
import type { Table } from '@/domain/models/app/table'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get compatible columns between existing and new table for data migration
|
|
18
|
+
*/
|
|
19
|
+
export const getCompatibleColumns = (
|
|
20
|
+
existingColumns: ReadonlyMap<
|
|
21
|
+
string,
|
|
22
|
+
{ dataType: string; isNullable: string; columnDefault: string | null }
|
|
23
|
+
>,
|
|
24
|
+
newColumnInfo: ReadonlyMap<string, { columnDefault: string | null; dataType: string }>
|
|
25
|
+
): readonly string[] =>
|
|
26
|
+
Array.from(existingColumns.keys()).filter((col) => {
|
|
27
|
+
const newColInfo = newColumnInfo.get(col)
|
|
28
|
+
if (!newColInfo) return false
|
|
29
|
+
const oldType = existingColumns.get(col)?.dataType.toLowerCase() ?? ''
|
|
30
|
+
return areTypesCompatible(oldType, newColInfo.dataType.toLowerCase())
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
interface CopyDataParams {
|
|
34
|
+
readonly tx: TransactionLike
|
|
35
|
+
readonly tempTableName: string
|
|
36
|
+
readonly physicalTableName: string
|
|
37
|
+
readonly commonColumns: readonly string[]
|
|
38
|
+
readonly newColumnInfo: ReadonlyMap<string, { columnDefault: string | null; dataType: string }>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Copy data and reset SERIAL sequences for migration
|
|
43
|
+
*/
|
|
44
|
+
export const copyDataAndResetSequences = (
|
|
45
|
+
params: CopyDataParams
|
|
46
|
+
): Effect.Effect<void, SQLExecutionError> =>
|
|
47
|
+
Effect.gen(function* () {
|
|
48
|
+
const { tx, tempTableName, physicalTableName, commonColumns, newColumnInfo } = params
|
|
49
|
+
if (commonColumns.length === 0) return
|
|
50
|
+
|
|
51
|
+
const columnList = commonColumns.join(', ')
|
|
52
|
+
yield* executeSQL(
|
|
53
|
+
tx,
|
|
54
|
+
`INSERT INTO ${tempTableName} (${columnList}) SELECT ${columnList} FROM ${physicalTableName}`
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// Reset SERIAL sequences to max value + 1 to avoid conflicts
|
|
58
|
+
const serialColumns = commonColumns.filter((col) =>
|
|
59
|
+
newColumnInfo.get(col)?.columnDefault?.includes('nextval')
|
|
60
|
+
)
|
|
61
|
+
yield* Effect.forEach(serialColumns, (col) =>
|
|
62
|
+
executeSQL(
|
|
63
|
+
tx,
|
|
64
|
+
`SELECT setval(pg_get_serial_sequence('${tempTableName}', '${col}'), COALESCE((SELECT MAX(${col}) FROM ${tempTableName}), 1), true)`
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
/** Get column metadata from a table */
|
|
70
|
+
const fetchColumnInfo = (
|
|
71
|
+
tx: TransactionLike,
|
|
72
|
+
tableName: string
|
|
73
|
+
): Effect.Effect<
|
|
74
|
+
Map<string, { columnDefault: string | null; dataType: string }>,
|
|
75
|
+
SQLExecutionError
|
|
76
|
+
> =>
|
|
77
|
+
Effect.gen(function* () {
|
|
78
|
+
const columns = yield* executeSQL(
|
|
79
|
+
tx,
|
|
80
|
+
`SELECT column_name, column_default, data_type FROM information_schema.columns WHERE table_name = '${tableName}'`
|
|
81
|
+
)
|
|
82
|
+
return new Map(
|
|
83
|
+
(
|
|
84
|
+
columns as readonly {
|
|
85
|
+
column_name: string
|
|
86
|
+
column_default: string | null
|
|
87
|
+
data_type: string
|
|
88
|
+
}[]
|
|
89
|
+
).map((row) => [
|
|
90
|
+
row.column_name,
|
|
91
|
+
{ columnDefault: row.column_default, dataType: row.data_type },
|
|
92
|
+
])
|
|
93
|
+
)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
/** Finalize table recreation by dropping old table and renaming temp table */
|
|
97
|
+
const finalizeTableRecreation = (
|
|
98
|
+
tx: TransactionLike,
|
|
99
|
+
physicalTableName: string,
|
|
100
|
+
tempTableName: string
|
|
101
|
+
): Effect.Effect<void, SQLExecutionError> =>
|
|
102
|
+
Effect.gen(function* () {
|
|
103
|
+
yield* executeSQL(tx, `DROP TABLE ${physicalTableName} CASCADE`)
|
|
104
|
+
yield* executeSQL(tx, `ALTER TABLE ${tempTableName} RENAME TO ${physicalTableName}`)
|
|
105
|
+
yield* executeSQL(
|
|
106
|
+
tx,
|
|
107
|
+
`DO $$ BEGIN ALTER TABLE ${physicalTableName} RENAME CONSTRAINT ${tempTableName}_pkey TO ${physicalTableName}_pkey; EXCEPTION WHEN undefined_object THEN NULL; END $$`
|
|
108
|
+
)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Recreate table with data preservation when schema changes are incompatible with ALTER TABLE
|
|
113
|
+
* Used when primary key type changes or other incompatible schema modifications occur
|
|
114
|
+
*/
|
|
115
|
+
export const recreateTableWithDataEffect = (
|
|
116
|
+
tx: TransactionLike,
|
|
117
|
+
table: Table,
|
|
118
|
+
existingColumns: ReadonlyMap<
|
|
119
|
+
string,
|
|
120
|
+
{ dataType: string; isNullable: string; columnDefault: string | null }
|
|
121
|
+
>,
|
|
122
|
+
tableUsesView?: ReadonlyMap<string, boolean>
|
|
123
|
+
): Effect.Effect<void, SQLExecutionError> =>
|
|
124
|
+
Effect.gen(function* () {
|
|
125
|
+
const sanitized = sanitizeTableName(table.name)
|
|
126
|
+
const physicalTableName = shouldUseView(table) ? getBaseTableName(sanitized) : sanitized
|
|
127
|
+
const tempTableName = `${physicalTableName}_migration_temp`
|
|
128
|
+
|
|
129
|
+
// Create temporary table with new schema
|
|
130
|
+
const createTableSQL = yield* Effect.try({
|
|
131
|
+
try: () =>
|
|
132
|
+
generateCreateTableSQL(table, tableUsesView).replace(
|
|
133
|
+
`CREATE TABLE IF NOT EXISTS ${physicalTableName}`,
|
|
134
|
+
`CREATE TABLE ${tempTableName}`
|
|
135
|
+
),
|
|
136
|
+
catch: (error) =>
|
|
137
|
+
new SQLExecutionError({
|
|
138
|
+
message: `Failed to generate CREATE TABLE DDL for migration: ${String(error)}`,
|
|
139
|
+
cause: error,
|
|
140
|
+
}),
|
|
141
|
+
})
|
|
142
|
+
yield* executeSQL(tx, createTableSQL)
|
|
143
|
+
|
|
144
|
+
// Get new table column info and copy compatible data
|
|
145
|
+
const newColumnInfo = yield* fetchColumnInfo(tx, tempTableName)
|
|
146
|
+
const commonColumns = getCompatibleColumns(existingColumns, newColumnInfo)
|
|
147
|
+
yield* copyDataAndResetSequences({
|
|
148
|
+
tx,
|
|
149
|
+
tempTableName,
|
|
150
|
+
physicalTableName,
|
|
151
|
+
commonColumns,
|
|
152
|
+
newColumnInfo,
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Finalize by dropping old table and renaming temp table
|
|
156
|
+
yield* finalizeTableRecreation(tx, physicalTableName, tempTableName)
|
|
157
|
+
})
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Effect } from 'effect'
|
|
9
|
+
import {
|
|
10
|
+
shouldUseView,
|
|
11
|
+
generateLookupViewSQL,
|
|
12
|
+
generateLookupViewTriggers,
|
|
13
|
+
} from '../lookup/lookup-view-generators'
|
|
14
|
+
import {
|
|
15
|
+
generateAlterTableStatements,
|
|
16
|
+
syncUniqueConstraints,
|
|
17
|
+
syncForeignKeyConstraints,
|
|
18
|
+
syncCheckConstraints,
|
|
19
|
+
syncIndexes,
|
|
20
|
+
type BunSQLTransaction,
|
|
21
|
+
} from '../schema-migration-helpers'
|
|
22
|
+
import {
|
|
23
|
+
executeSQL,
|
|
24
|
+
executeSQLStatements,
|
|
25
|
+
getExistingColumns,
|
|
26
|
+
SQLExecutionError,
|
|
27
|
+
type TransactionLike,
|
|
28
|
+
} from '../sql/sql-execution'
|
|
29
|
+
import { generateTableViewStatements, generateReadOnlyViewTrigger } from '../views/view-generators'
|
|
30
|
+
import { generateCreateTableSQL } from './create-table-sql'
|
|
31
|
+
import { recreateTableWithDataEffect } from './migration-utils'
|
|
32
|
+
import { applyTableFeatures, applyTableFeaturesWithoutIndexes } from './table-features'
|
|
33
|
+
import type { Table } from '@/domain/models/app/table'
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Configuration for table migration operations
|
|
37
|
+
*/
|
|
38
|
+
export type MigrationConfig = {
|
|
39
|
+
readonly tableUsesView?: ReadonlyMap<string, boolean>
|
|
40
|
+
readonly previousSchema?: { readonly tables: readonly object[] }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Migrate existing table (ALTER statements + constraints + indexes)
|
|
45
|
+
*/
|
|
46
|
+
export const migrateExistingTableEffect = (params: {
|
|
47
|
+
readonly tx: TransactionLike
|
|
48
|
+
readonly table: Table
|
|
49
|
+
readonly existingColumns: ReadonlyMap<
|
|
50
|
+
string,
|
|
51
|
+
{ dataType: string; isNullable: string; columnDefault: string | null }
|
|
52
|
+
>
|
|
53
|
+
readonly tableUsesView?: ReadonlyMap<string, boolean>
|
|
54
|
+
readonly previousSchema?: { readonly tables: readonly object[] }
|
|
55
|
+
}): Effect.Effect<void, SQLExecutionError> =>
|
|
56
|
+
Effect.gen(function* () {
|
|
57
|
+
const { tx, table, existingColumns, tableUsesView, previousSchema } = params
|
|
58
|
+
const alterStatements = generateAlterTableStatements(table, existingColumns, previousSchema)
|
|
59
|
+
|
|
60
|
+
// If alterStatements is empty, table has incompatible schema changes
|
|
61
|
+
// (e.g., primary key type change) - need to recreate with data preservation
|
|
62
|
+
if (alterStatements.length === 0) {
|
|
63
|
+
yield* recreateTableWithDataEffect(tx, table, existingColumns, tableUsesView)
|
|
64
|
+
} else {
|
|
65
|
+
// Apply incremental migrations
|
|
66
|
+
yield* executeSQLStatements(tx, alterStatements)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Always add/update unique constraints for existing tables
|
|
70
|
+
yield* syncUniqueConstraints(tx, table, previousSchema)
|
|
71
|
+
|
|
72
|
+
// Always sync foreign key constraints to ensure referential actions are up-to-date
|
|
73
|
+
yield* syncForeignKeyConstraints(tx, table, tableUsesView)
|
|
74
|
+
|
|
75
|
+
// Always sync CHECK constraints for fields with validation requirements
|
|
76
|
+
yield* syncCheckConstraints(tx, table)
|
|
77
|
+
|
|
78
|
+
// Always sync indexes when field indexed property changes or custom indexes are modified
|
|
79
|
+
yield* syncIndexes(tx, table, previousSchema)
|
|
80
|
+
|
|
81
|
+
// Apply table features (triggers, RLS) - indexes handled by syncIndexes above
|
|
82
|
+
yield* applyTableFeaturesWithoutIndexes(tx, table)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create new table (CREATE statement + indexes + triggers)
|
|
87
|
+
* Note: VIEWs are created in a separate phase after all base tables exist
|
|
88
|
+
*
|
|
89
|
+
* @param tx - Transaction object
|
|
90
|
+
* @param table - Table definition
|
|
91
|
+
* @param tableUsesView - Map of table names to whether they use a VIEW
|
|
92
|
+
* @param skipForeignKeys - Skip foreign key constraints (for circular dependencies)
|
|
93
|
+
*/
|
|
94
|
+
export const createNewTableEffect = (params: {
|
|
95
|
+
readonly tx: TransactionLike
|
|
96
|
+
readonly table: Table
|
|
97
|
+
readonly tableUsesView?: ReadonlyMap<string, boolean>
|
|
98
|
+
readonly skipForeignKeys?: boolean
|
|
99
|
+
readonly hasAuthConfig?: boolean
|
|
100
|
+
}): Effect.Effect<void, SQLExecutionError> =>
|
|
101
|
+
Effect.gen(function* () {
|
|
102
|
+
const { tx, table, tableUsesView, skipForeignKeys, hasAuthConfig = true } = params
|
|
103
|
+
// Wrap DDL generation in Effect.try to catch synchronous errors (e.g., unknown field types)
|
|
104
|
+
const createTableSQL = yield* Effect.try({
|
|
105
|
+
try: () => generateCreateTableSQL(table, tableUsesView, skipForeignKeys, hasAuthConfig),
|
|
106
|
+
catch: (error) =>
|
|
107
|
+
new SQLExecutionError({
|
|
108
|
+
message: `Failed to generate CREATE TABLE DDL: ${String(error)}`,
|
|
109
|
+
cause: error,
|
|
110
|
+
}),
|
|
111
|
+
})
|
|
112
|
+
yield* executeSQL(tx, createTableSQL)
|
|
113
|
+
|
|
114
|
+
// Apply all table features (indexes, triggers, RLS)
|
|
115
|
+
yield* applyTableFeatures(tx, table)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Create lookup VIEWs for tables with lookup fields
|
|
120
|
+
* Called after all base tables have been created to avoid dependency issues
|
|
121
|
+
*/
|
|
122
|
+
export const createLookupViewsEffect = (
|
|
123
|
+
tx: TransactionLike,
|
|
124
|
+
table: Table
|
|
125
|
+
): Effect.Effect<void, SQLExecutionError> =>
|
|
126
|
+
Effect.gen(function* () {
|
|
127
|
+
if (shouldUseView(table)) {
|
|
128
|
+
const createViewSQL = generateLookupViewSQL(table)
|
|
129
|
+
if (createViewSQL) {
|
|
130
|
+
// Drop existing table if it exists (to allow VIEW creation)
|
|
131
|
+
// This handles the transition from TABLE to VIEW when rollup/lookup fields are added
|
|
132
|
+
yield* executeSQL(tx, `DROP TABLE IF EXISTS ${table.name} CASCADE`)
|
|
133
|
+
|
|
134
|
+
yield* executeSQL(tx, createViewSQL)
|
|
135
|
+
|
|
136
|
+
// Create INSTEAD OF triggers to make the VIEW writable
|
|
137
|
+
const triggerStatements = generateLookupViewTriggers(table)
|
|
138
|
+
yield* executeSQLStatements(tx, triggerStatements)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create table views (user-defined VIEWs from table.views configuration)
|
|
145
|
+
* Called after all tables and lookup views have been created
|
|
146
|
+
*/
|
|
147
|
+
export const createTableViewsEffect = (
|
|
148
|
+
tx: TransactionLike,
|
|
149
|
+
table: Table
|
|
150
|
+
): Effect.Effect<void, SQLExecutionError> =>
|
|
151
|
+
Effect.gen(function* () {
|
|
152
|
+
// Views are dropped globally in schema-initializer.ts before this function is called
|
|
153
|
+
// This ensures all obsolete views are removed before creating new ones
|
|
154
|
+
|
|
155
|
+
// Only create views if table has views defined
|
|
156
|
+
if (!table.views || table.views.length === 0) {
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Drop and recreate each view (PostgreSQL doesn't support IF NOT EXISTS for views)
|
|
161
|
+
const viewSQL = generateTableViewStatements(table)
|
|
162
|
+
|
|
163
|
+
// Process each view sequentially (views may depend on each other)
|
|
164
|
+
/* eslint-disable functional/no-loop-statements */
|
|
165
|
+
for (const view of table.views) {
|
|
166
|
+
// Convert view.id to string (ViewId can be number or string)
|
|
167
|
+
const viewIdStr = String(view.id)
|
|
168
|
+
|
|
169
|
+
// Drop existing view or materialized view (if any)
|
|
170
|
+
// Try both types since we don't know what exists in the database
|
|
171
|
+
if (view.materialized) {
|
|
172
|
+
yield* executeSQL(tx, `DROP MATERIALIZED VIEW IF EXISTS ${viewIdStr} CASCADE`)
|
|
173
|
+
} else {
|
|
174
|
+
yield* executeSQL(tx, `DROP VIEW IF EXISTS ${viewIdStr} CASCADE`)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Create view (regular or materialized)
|
|
178
|
+
const createSQL = viewSQL.find((sql) => sql.includes(viewIdStr))
|
|
179
|
+
if (createSQL) {
|
|
180
|
+
yield* executeSQL(tx, createSQL)
|
|
181
|
+
|
|
182
|
+
// For regular (non-materialized) views, add read-only triggers
|
|
183
|
+
// PostgreSQL views can be automatically updatable, so we need triggers to prevent modifications
|
|
184
|
+
if (!view.materialized) {
|
|
185
|
+
const readOnlyTriggerSQL = generateReadOnlyViewTrigger(view.id)
|
|
186
|
+
/* eslint-disable functional/no-loop-statements */
|
|
187
|
+
for (const triggerSQL of readOnlyTriggerSQL) {
|
|
188
|
+
yield* executeSQL(tx, triggerSQL)
|
|
189
|
+
}
|
|
190
|
+
/* eslint-enable functional/no-loop-statements */
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Refresh materialized view if requested
|
|
194
|
+
if (view.materialized && view.refreshOnMigration) {
|
|
195
|
+
yield* executeSQL(tx, `REFRESH MATERIALIZED VIEW ${viewIdStr}`)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Create or migrate table based on existence
|
|
203
|
+
*/
|
|
204
|
+
export const createOrMigrateTableEffect = (params: {
|
|
205
|
+
readonly tx: BunSQLTransaction
|
|
206
|
+
readonly table: Table
|
|
207
|
+
readonly exists: boolean
|
|
208
|
+
readonly tableUsesView?: ReadonlyMap<string, boolean>
|
|
209
|
+
readonly previousSchema?: { readonly tables: readonly object[] }
|
|
210
|
+
readonly skipForeignKeys?: boolean
|
|
211
|
+
readonly hasAuthConfig?: boolean
|
|
212
|
+
}): Effect.Effect<void, SQLExecutionError> =>
|
|
213
|
+
Effect.gen(function* () {
|
|
214
|
+
const { tx, table, exists, tableUsesView, previousSchema, skipForeignKeys, hasAuthConfig } =
|
|
215
|
+
params
|
|
216
|
+
if (exists) {
|
|
217
|
+
const existingColumns = yield* getExistingColumns(tx, table.name)
|
|
218
|
+
yield* migrateExistingTableEffect({
|
|
219
|
+
tx,
|
|
220
|
+
table,
|
|
221
|
+
existingColumns,
|
|
222
|
+
tableUsesView,
|
|
223
|
+
previousSchema,
|
|
224
|
+
})
|
|
225
|
+
} else {
|
|
226
|
+
yield* createNewTableEffect({
|
|
227
|
+
tx,
|
|
228
|
+
table,
|
|
229
|
+
tableUsesView,
|
|
230
|
+
skipForeignKeys,
|
|
231
|
+
hasAuthConfig: hasAuthConfig ?? true,
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
})
|