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,14 @@
|
|
|
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 { createTaggedError } from '@/domain/errors/create-tagged-error'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error class for app validation failures
|
|
12
|
+
*/
|
|
13
|
+
export const AppValidationError = createTaggedError('AppValidationError')
|
|
14
|
+
export type AppValidationError = InstanceType<typeof AppValidationError>
|
|
@@ -0,0 +1,16 @@
|
|
|
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 { Data } from 'effect'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error class for static site generation failures
|
|
12
|
+
*/
|
|
13
|
+
export class StaticGenerationError extends Data.TaggedError('StaticGenerationError')<{
|
|
14
|
+
readonly message: string
|
|
15
|
+
readonly cause?: unknown
|
|
16
|
+
}> {}
|
|
@@ -0,0 +1,127 @@
|
|
|
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 { FaviconSet } from '@/domain/models/app/page/meta/favicon-set'
|
|
9
|
+
import type { FaviconsConfig } from '@/domain/models/app/page/meta/favicons-config'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes a favicon path to ensure it starts with './'
|
|
13
|
+
*
|
|
14
|
+
* @param href - Favicon path (with or without './' prefix)
|
|
15
|
+
* @returns Path guaranteed to start with './'
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* normalizeFaviconPath('/icon.svg') // './icon.svg'
|
|
20
|
+
* normalizeFaviconPath('./icon.svg') // './icon.svg'
|
|
21
|
+
* normalizeFaviconPath('icon.svg') // './icon.svg'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function normalizeFaviconPath(href: string): string {
|
|
25
|
+
return href.startsWith('./') ? href : `.${href}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Transforms FaviconsConfig (object format) to FaviconSet (array format)
|
|
30
|
+
*
|
|
31
|
+
* This function converts the simplified object-based configuration format
|
|
32
|
+
* into the array-based FaviconSet format expected by the rendering components.
|
|
33
|
+
*
|
|
34
|
+
* Transformation rules:
|
|
35
|
+
* - icon → { rel: 'icon', type: 'image/svg+xml', href: icon }
|
|
36
|
+
* - appleTouchIcon → { rel: 'apple-touch-icon', href: appleTouchIcon }
|
|
37
|
+
* - sizes → { rel: 'icon', type: 'image/png', sizes: size, href: href }
|
|
38
|
+
*
|
|
39
|
+
* @param config - FaviconsConfig object with named properties
|
|
40
|
+
* @returns FaviconSet array with favicon items
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const config = {
|
|
45
|
+
* icon: '/icon.svg',
|
|
46
|
+
* appleTouchIcon: '/apple-touch-icon.png',
|
|
47
|
+
* sizes: [
|
|
48
|
+
* { size: '32x32', href: '/favicon-32x32.png' },
|
|
49
|
+
* { size: '16x16', href: '/favicon-16x16.png' }
|
|
50
|
+
* ]
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* const faviconSet = transformFaviconsConfigToSet(config)
|
|
54
|
+
* // [
|
|
55
|
+
* // { rel: 'icon', type: 'image/svg+xml', href: './icon.svg' },
|
|
56
|
+
* // { rel: 'apple-touch-icon', href: './apple-touch-icon.png' },
|
|
57
|
+
* // { rel: 'icon', type: 'image/png', sizes: '32x32', href: './favicon-32x32.png' },
|
|
58
|
+
* // { rel: 'icon', type: 'image/png', sizes: '16x16', href: './favicon-16x16.png' }
|
|
59
|
+
* // ]
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function transformFaviconsConfigToSet(config: FaviconsConfig): FaviconSet {
|
|
63
|
+
// Transform icon
|
|
64
|
+
const iconItems = config.icon
|
|
65
|
+
? [
|
|
66
|
+
{
|
|
67
|
+
rel: 'icon' as const,
|
|
68
|
+
type: 'image/svg+xml' as const,
|
|
69
|
+
href: normalizeFaviconPath(config.icon),
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
: []
|
|
73
|
+
|
|
74
|
+
// Transform appleTouchIcon
|
|
75
|
+
const appleTouchIconItems = config.appleTouchIcon
|
|
76
|
+
? [
|
|
77
|
+
{
|
|
78
|
+
rel: 'apple-touch-icon' as const,
|
|
79
|
+
href: normalizeFaviconPath(config.appleTouchIcon),
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
: []
|
|
83
|
+
|
|
84
|
+
// Transform sizes
|
|
85
|
+
const sizeItems =
|
|
86
|
+
config.sizes?.map((sizeItem) => ({
|
|
87
|
+
rel: 'icon' as const,
|
|
88
|
+
type: 'image/png' as const,
|
|
89
|
+
sizes: sizeItem.size,
|
|
90
|
+
href: normalizeFaviconPath(sizeItem.href),
|
|
91
|
+
})) ?? []
|
|
92
|
+
|
|
93
|
+
return [...iconItems, ...appleTouchIconItems, ...sizeItems]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Type guard to check if favicons is FaviconsConfig (object format)
|
|
98
|
+
*/
|
|
99
|
+
export function isFaviconsConfig(
|
|
100
|
+
favicons: FaviconSet | FaviconsConfig | undefined
|
|
101
|
+
): favicons is FaviconsConfig {
|
|
102
|
+
if (!favicons) return false
|
|
103
|
+
return (
|
|
104
|
+
!Array.isArray(favicons) &&
|
|
105
|
+
typeof favicons === 'object' &&
|
|
106
|
+
('icon' in favicons || 'appleTouchIcon' in favicons || 'sizes' in favicons)
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Normalizes favicons to FaviconSet array format
|
|
112
|
+
*
|
|
113
|
+
* Accepts both FaviconSet (array) and FaviconsConfig (object) formats,
|
|
114
|
+
* returning a normalized FaviconSet array.
|
|
115
|
+
*
|
|
116
|
+
* @param favicons - Favicons in either format
|
|
117
|
+
* @returns FaviconSet array or undefined
|
|
118
|
+
*/
|
|
119
|
+
export function normalizeFavicons(
|
|
120
|
+
favicons: FaviconSet | FaviconsConfig | undefined
|
|
121
|
+
): FaviconSet | undefined {
|
|
122
|
+
if (!favicons) return undefined
|
|
123
|
+
if (isFaviconsConfig(favicons)) {
|
|
124
|
+
return transformFaviconsConfigToSet(favicons)
|
|
125
|
+
}
|
|
126
|
+
return favicons as FaviconSet
|
|
127
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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 { Effect } from 'effect'
|
|
9
|
+
import type { Hono } from 'hono'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Running server instance with stop capability
|
|
13
|
+
*
|
|
14
|
+
* This represents a domain concept of a running web server
|
|
15
|
+
* that can be controlled (stopped) through Effect operations.
|
|
16
|
+
*
|
|
17
|
+
* The actual server implementation (Bun.serve) is hidden
|
|
18
|
+
* behind this interface to maintain layer separation.
|
|
19
|
+
*
|
|
20
|
+
* The Hono app is exposed for static site generation (SSG) purposes.
|
|
21
|
+
*/
|
|
22
|
+
export interface ServerInstance {
|
|
23
|
+
readonly server: ReturnType<typeof Bun.serve>
|
|
24
|
+
readonly url: string
|
|
25
|
+
readonly stop: Effect.Effect<void>
|
|
26
|
+
readonly app: Readonly<Hono>
|
|
27
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
* Minimal user metadata embedded in domain records
|
|
10
|
+
*
|
|
11
|
+
* Represents the common shape returned by user-joined queries
|
|
12
|
+
* (activity logs, comments, activity history). Defined at the
|
|
13
|
+
* application boundary so both application and infrastructure
|
|
14
|
+
* layers can reference the same contract.
|
|
15
|
+
*
|
|
16
|
+
* Variants:
|
|
17
|
+
* - `UserMetadata` — core fields (id, name, email)
|
|
18
|
+
* - `UserMetadataWithImage` — adds optional image (comments, activity history)
|
|
19
|
+
*/
|
|
20
|
+
export interface UserMetadata {
|
|
21
|
+
readonly id: string
|
|
22
|
+
readonly name: string
|
|
23
|
+
readonly email: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface UserMetadataWithImage extends UserMetadata {
|
|
27
|
+
readonly image: string | null | undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Variant with image typed as `string | undefined` only (no null).
|
|
32
|
+
* Used by comment queries where infrastructure converts null → undefined.
|
|
33
|
+
*/
|
|
34
|
+
export interface UserMetadataWithOptionalImage extends UserMetadata {
|
|
35
|
+
readonly image: string | undefined
|
|
36
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
* User session interface for application layer
|
|
10
|
+
*
|
|
11
|
+
* Structurally compatible with Better Auth's Session type
|
|
12
|
+
* so infrastructure implementations can accept it without conversion.
|
|
13
|
+
* Application layer uses this instead of importing from infrastructure.
|
|
14
|
+
*/
|
|
15
|
+
export interface UserSession {
|
|
16
|
+
readonly id: string
|
|
17
|
+
readonly userId: string
|
|
18
|
+
readonly token: string
|
|
19
|
+
readonly expiresAt: Date
|
|
20
|
+
readonly createdAt: Date
|
|
21
|
+
readonly updatedAt: Date
|
|
22
|
+
readonly ipAddress: string | null
|
|
23
|
+
readonly userAgent: string | null
|
|
24
|
+
readonly impersonatedBy: string | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Session type alias for backward compatibility
|
|
29
|
+
*
|
|
30
|
+
* Allows presentation layer to import Session from the application
|
|
31
|
+
* boundary instead of reaching into infrastructure. Structurally
|
|
32
|
+
* compatible with the Drizzle-inferred Session type from Better Auth.
|
|
33
|
+
*/
|
|
34
|
+
export type Session = UserSession
|
|
@@ -0,0 +1,68 @@
|
|
|
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 { Context, Data } from 'effect'
|
|
9
|
+
import type { UserMetadata } from '@/application/ports/models/user-metadata'
|
|
10
|
+
import type { Effect } from 'effect'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Activity Log record type (port-level definition)
|
|
14
|
+
*
|
|
15
|
+
* Structurally compatible with the Drizzle schema inference.
|
|
16
|
+
* Defined here to avoid application→infrastructure dependency.
|
|
17
|
+
*/
|
|
18
|
+
export interface ActivityLog {
|
|
19
|
+
readonly id: string
|
|
20
|
+
readonly createdAt: Date
|
|
21
|
+
readonly userId: string | null
|
|
22
|
+
readonly sessionId: string | null
|
|
23
|
+
readonly action: 'create' | 'update' | 'delete' | 'restore'
|
|
24
|
+
readonly tableName: string
|
|
25
|
+
readonly tableId: string | null
|
|
26
|
+
readonly recordId: string
|
|
27
|
+
readonly changes: {
|
|
28
|
+
readonly before?: Record<string, unknown>
|
|
29
|
+
readonly after?: Record<string, unknown>
|
|
30
|
+
} | null
|
|
31
|
+
readonly ipAddress: string | null
|
|
32
|
+
readonly userAgent: string | null
|
|
33
|
+
readonly user?: UserMetadata | null | undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Database error for activity log operations
|
|
38
|
+
*/
|
|
39
|
+
export class ActivityLogDatabaseError extends Data.TaggedError('ActivityLogDatabaseError')<{
|
|
40
|
+
readonly cause: unknown
|
|
41
|
+
}> {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Activity Log Repository Port
|
|
45
|
+
*
|
|
46
|
+
* Provides type-safe database operations for activity logs.
|
|
47
|
+
* Implementation lives in infrastructure layer (activity-log-repository-live.ts).
|
|
48
|
+
*/
|
|
49
|
+
export class ActivityLogRepository extends Context.Tag('ActivityLogRepository')<
|
|
50
|
+
ActivityLogRepository,
|
|
51
|
+
{
|
|
52
|
+
readonly listAll: () => Effect.Effect<readonly ActivityLog[], ActivityLogDatabaseError>
|
|
53
|
+
readonly create: (log: {
|
|
54
|
+
readonly userId: string
|
|
55
|
+
readonly action: 'create' | 'update' | 'delete' | 'restore'
|
|
56
|
+
readonly tableName: string
|
|
57
|
+
readonly tableId: string
|
|
58
|
+
readonly recordId: string
|
|
59
|
+
readonly changes: {
|
|
60
|
+
readonly before?: Record<string, unknown>
|
|
61
|
+
readonly after?: Record<string, unknown>
|
|
62
|
+
}
|
|
63
|
+
readonly sessionId?: string
|
|
64
|
+
readonly ipAddress?: string
|
|
65
|
+
readonly userAgent?: string
|
|
66
|
+
}) => Effect.Effect<ActivityLog, ActivityLogDatabaseError>
|
|
67
|
+
}
|
|
68
|
+
>() {}
|
|
@@ -0,0 +1,49 @@
|
|
|
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 { Context } from 'effect'
|
|
9
|
+
import type { UserMetadataWithImage } from '@/application/ports/models/user-metadata'
|
|
10
|
+
import type { UserSession } from '@/application/ports/models/user-session'
|
|
11
|
+
import type { SessionContextError } from '@/domain/errors'
|
|
12
|
+
import type { Effect } from 'effect'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Activity history entry with user metadata
|
|
16
|
+
*/
|
|
17
|
+
export interface ActivityHistoryEntry {
|
|
18
|
+
readonly action: string
|
|
19
|
+
readonly createdAt: Date
|
|
20
|
+
readonly changes: unknown
|
|
21
|
+
readonly user: UserMetadataWithImage | undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Activity Repository Port
|
|
26
|
+
*/
|
|
27
|
+
export class ActivityRepository extends Context.Tag('ActivityRepository')<
|
|
28
|
+
ActivityRepository,
|
|
29
|
+
{
|
|
30
|
+
readonly getRecordHistory: (config: {
|
|
31
|
+
readonly session: Readonly<UserSession>
|
|
32
|
+
readonly tableName: string
|
|
33
|
+
readonly recordId: string
|
|
34
|
+
readonly limit?: number
|
|
35
|
+
readonly offset?: number
|
|
36
|
+
}) => Effect.Effect<
|
|
37
|
+
{
|
|
38
|
+
readonly entries: readonly ActivityHistoryEntry[]
|
|
39
|
+
readonly total: number
|
|
40
|
+
},
|
|
41
|
+
SessionContextError
|
|
42
|
+
>
|
|
43
|
+
readonly checkRecordExists: (config: {
|
|
44
|
+
readonly session: Readonly<UserSession>
|
|
45
|
+
readonly tableName: string
|
|
46
|
+
readonly recordId: string
|
|
47
|
+
}) => Effect.Effect<boolean, SessionContextError>
|
|
48
|
+
}
|
|
49
|
+
>() {}
|
|
@@ -0,0 +1,164 @@
|
|
|
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 { Context, Data } from 'effect'
|
|
9
|
+
import type { Effect } from 'effect'
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Port-level types (avoid infrastructure dependency)
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Page view input for recording a new event
|
|
17
|
+
*/
|
|
18
|
+
export interface PageViewInput {
|
|
19
|
+
readonly appName: string
|
|
20
|
+
readonly pagePath: string
|
|
21
|
+
readonly pageTitle?: string
|
|
22
|
+
readonly visitorHash: string
|
|
23
|
+
readonly sessionHash: string
|
|
24
|
+
readonly isEntrance: boolean
|
|
25
|
+
readonly referrerUrl?: string
|
|
26
|
+
readonly referrerDomain?: string
|
|
27
|
+
readonly utmSource?: string
|
|
28
|
+
readonly utmMedium?: string
|
|
29
|
+
readonly utmCampaign?: string
|
|
30
|
+
readonly utmContent?: string
|
|
31
|
+
readonly utmTerm?: string
|
|
32
|
+
readonly deviceType?: string
|
|
33
|
+
readonly browserName?: string
|
|
34
|
+
readonly osName?: string
|
|
35
|
+
readonly language?: string
|
|
36
|
+
readonly screenWidth?: number
|
|
37
|
+
readonly screenHeight?: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Query parameters for analytics data retrieval
|
|
42
|
+
*/
|
|
43
|
+
export interface AnalyticsQueryParams {
|
|
44
|
+
readonly appName: string
|
|
45
|
+
readonly from: Date
|
|
46
|
+
readonly to: Date
|
|
47
|
+
readonly granularity: 'hour' | 'day' | 'week' | 'month'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Time series data point
|
|
52
|
+
*/
|
|
53
|
+
export interface TimeSeriesPoint {
|
|
54
|
+
readonly period: string
|
|
55
|
+
readonly pageViews: number
|
|
56
|
+
readonly uniqueVisitors: number
|
|
57
|
+
readonly sessions: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Summary metrics
|
|
62
|
+
*/
|
|
63
|
+
export interface AnalyticsSummary {
|
|
64
|
+
readonly pageViews: number
|
|
65
|
+
readonly uniqueVisitors: number
|
|
66
|
+
readonly sessions: number
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Top page entry
|
|
71
|
+
*/
|
|
72
|
+
export interface TopPage {
|
|
73
|
+
readonly path: string
|
|
74
|
+
readonly pageViews: number
|
|
75
|
+
readonly uniqueVisitors: number
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Top referrer entry
|
|
80
|
+
*/
|
|
81
|
+
export interface TopReferrer {
|
|
82
|
+
readonly domain: string | null
|
|
83
|
+
readonly pageViews: number
|
|
84
|
+
readonly uniqueVisitors: number
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Breakdown entry (device type, browser, OS)
|
|
89
|
+
*/
|
|
90
|
+
export interface BreakdownEntry {
|
|
91
|
+
readonly name: string
|
|
92
|
+
readonly count: number
|
|
93
|
+
readonly percentage: number
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Device breakdown result
|
|
98
|
+
*/
|
|
99
|
+
export interface DeviceBreakdown {
|
|
100
|
+
readonly deviceTypes: readonly BreakdownEntry[]
|
|
101
|
+
readonly browsers: readonly BreakdownEntry[]
|
|
102
|
+
readonly operatingSystems: readonly BreakdownEntry[]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Campaign entry
|
|
107
|
+
*/
|
|
108
|
+
export interface CampaignEntry {
|
|
109
|
+
readonly source: string | null
|
|
110
|
+
readonly medium: string | null
|
|
111
|
+
readonly campaign: string | null
|
|
112
|
+
readonly pageViews: number
|
|
113
|
+
readonly uniqueVisitors: number
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Error type
|
|
118
|
+
// ============================================================================
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Database error for analytics operations
|
|
122
|
+
*/
|
|
123
|
+
export class AnalyticsDatabaseError extends Data.TaggedError('AnalyticsDatabaseError')<{
|
|
124
|
+
readonly cause: unknown
|
|
125
|
+
}> {}
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Repository port
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Analytics Repository Port
|
|
133
|
+
*
|
|
134
|
+
* Provides type-safe database operations for analytics page views.
|
|
135
|
+
* Implementation lives in infrastructure layer (analytics-repository-live.ts).
|
|
136
|
+
*/
|
|
137
|
+
export class AnalyticsRepository extends Context.Tag('AnalyticsRepository')<
|
|
138
|
+
AnalyticsRepository,
|
|
139
|
+
{
|
|
140
|
+
readonly recordPageView: (input: PageViewInput) => Effect.Effect<void, AnalyticsDatabaseError>
|
|
141
|
+
readonly getTimeSeries: (
|
|
142
|
+
params: AnalyticsQueryParams
|
|
143
|
+
) => Effect.Effect<readonly TimeSeriesPoint[], AnalyticsDatabaseError>
|
|
144
|
+
readonly getSummary: (
|
|
145
|
+
params: AnalyticsQueryParams
|
|
146
|
+
) => Effect.Effect<AnalyticsSummary, AnalyticsDatabaseError>
|
|
147
|
+
readonly getTopPages: (
|
|
148
|
+
params: AnalyticsQueryParams
|
|
149
|
+
) => Effect.Effect<readonly TopPage[], AnalyticsDatabaseError>
|
|
150
|
+
readonly getTopReferrers: (
|
|
151
|
+
params: AnalyticsQueryParams
|
|
152
|
+
) => Effect.Effect<readonly TopReferrer[], AnalyticsDatabaseError>
|
|
153
|
+
readonly getDevices: (
|
|
154
|
+
params: AnalyticsQueryParams
|
|
155
|
+
) => Effect.Effect<DeviceBreakdown, AnalyticsDatabaseError>
|
|
156
|
+
readonly getCampaigns: (
|
|
157
|
+
params: AnalyticsQueryParams
|
|
158
|
+
) => Effect.Effect<readonly CampaignEntry[], AnalyticsDatabaseError>
|
|
159
|
+
readonly deleteOlderThan: (
|
|
160
|
+
appName: string,
|
|
161
|
+
cutoff: Date
|
|
162
|
+
) => Effect.Effect<number, AnalyticsDatabaseError>
|
|
163
|
+
}
|
|
164
|
+
>() {}
|
|
@@ -0,0 +1,33 @@
|
|
|
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 { Context, Data } from 'effect'
|
|
9
|
+
import type { Effect } from 'effect'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Database error for auth operations (users table)
|
|
13
|
+
*/
|
|
14
|
+
export class AuthDatabaseError extends Data.TaggedError('AuthDatabaseError')<{
|
|
15
|
+
readonly cause: unknown
|
|
16
|
+
}> {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Auth Repository Port
|
|
20
|
+
*
|
|
21
|
+
* Provides type-safe database operations for authentication-related
|
|
22
|
+
* user management (email verification, role lookup).
|
|
23
|
+
* Both methods operate on the Better Auth `users` table.
|
|
24
|
+
*
|
|
25
|
+
* Implementation lives in infrastructure layer (auth-repository-live.ts).
|
|
26
|
+
*/
|
|
27
|
+
export class AuthRepository extends Context.Tag('AuthRepository')<
|
|
28
|
+
AuthRepository,
|
|
29
|
+
{
|
|
30
|
+
readonly verifyUserEmail: (userId: string) => Effect.Effect<void, AuthDatabaseError>
|
|
31
|
+
readonly getUserRole: (userId: string) => Effect.Effect<string | undefined, AuthDatabaseError>
|
|
32
|
+
}
|
|
33
|
+
>() {}
|
|
@@ -0,0 +1,86 @@
|
|
|
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 { Context } from 'effect'
|
|
9
|
+
import type { UserSession } from '@/application/ports/models/user-session'
|
|
10
|
+
import type { SessionContextError, ValidationError } from '@/domain/errors'
|
|
11
|
+
import type { Effect } from 'effect'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Batch validation error interface
|
|
15
|
+
*
|
|
16
|
+
* Structurally compatible with infrastructure's BatchValidationError
|
|
17
|
+
* (Data.TaggedError). Defined here so application layer doesn't need
|
|
18
|
+
* to import from infrastructure.
|
|
19
|
+
*/
|
|
20
|
+
export interface BatchValidationError extends Error {
|
|
21
|
+
readonly _tag: 'BatchValidationError'
|
|
22
|
+
readonly message: string
|
|
23
|
+
readonly details?: readonly string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Upsert operation result
|
|
28
|
+
*/
|
|
29
|
+
export interface UpsertResult {
|
|
30
|
+
readonly records: readonly Record<string, unknown>[]
|
|
31
|
+
readonly created: number
|
|
32
|
+
readonly updated: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Batch Repository port for batch operations
|
|
37
|
+
*
|
|
38
|
+
* Defines the contract for bulk create, update, delete, restore, and upsert.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const program = Effect.gen(function* () {
|
|
43
|
+
* const batch = yield* BatchRepository
|
|
44
|
+
* const result = yield* batch.batchCreate(session, 'users', records)
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export class BatchRepository extends Context.Tag('BatchRepository')<
|
|
49
|
+
BatchRepository,
|
|
50
|
+
{
|
|
51
|
+
readonly batchCreate: (
|
|
52
|
+
session: Readonly<UserSession>,
|
|
53
|
+
tableName: string,
|
|
54
|
+
recordsData: readonly Record<string, unknown>[]
|
|
55
|
+
) => Effect.Effect<readonly Record<string, unknown>[], SessionContextError | ValidationError>
|
|
56
|
+
|
|
57
|
+
readonly batchUpdate: (
|
|
58
|
+
session: Readonly<UserSession>,
|
|
59
|
+
tableName: string,
|
|
60
|
+
updates: readonly {
|
|
61
|
+
readonly id: string
|
|
62
|
+
readonly fields?: Record<string, unknown>
|
|
63
|
+
}[]
|
|
64
|
+
) => Effect.Effect<readonly Record<string, unknown>[], SessionContextError | ValidationError>
|
|
65
|
+
|
|
66
|
+
readonly batchDelete: (
|
|
67
|
+
session: Readonly<UserSession>,
|
|
68
|
+
tableName: string,
|
|
69
|
+
recordIds: readonly string[],
|
|
70
|
+
permanent?: boolean
|
|
71
|
+
) => Effect.Effect<number, SessionContextError>
|
|
72
|
+
|
|
73
|
+
readonly batchRestore: (
|
|
74
|
+
session: Readonly<UserSession>,
|
|
75
|
+
tableName: string,
|
|
76
|
+
recordIds: readonly string[]
|
|
77
|
+
) => Effect.Effect<number, SessionContextError>
|
|
78
|
+
|
|
79
|
+
readonly upsert: (
|
|
80
|
+
session: Readonly<UserSession>,
|
|
81
|
+
tableName: string,
|
|
82
|
+
recordsData: readonly Record<string, unknown>[],
|
|
83
|
+
fieldsToMergeOn: readonly string[]
|
|
84
|
+
) => Effect.Effect<UpsertResult, SessionContextError | BatchValidationError | ValidationError>
|
|
85
|
+
}
|
|
86
|
+
>() {}
|