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,65 @@
|
|
|
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 {
|
|
9
|
+
substituteVariableValues,
|
|
10
|
+
substituteChildrenVariables,
|
|
11
|
+
substitutePropsVariables,
|
|
12
|
+
} from '../translations/variable-substitution'
|
|
13
|
+
import type { Components } from '@/domain/models/app/components'
|
|
14
|
+
import type { Component } from '@/domain/models/app/page/sections'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolves a component reference to a Component with optional variable substitution
|
|
18
|
+
*
|
|
19
|
+
* Pure function that finds a component template by name, converts it to a Component,
|
|
20
|
+
* and applies variable substitution if vars are provided.
|
|
21
|
+
*
|
|
22
|
+
* @param componentName - Name of the component template to resolve
|
|
23
|
+
* @param components - Array of available component templates
|
|
24
|
+
* @param vars - Optional variables for substitution
|
|
25
|
+
* @returns Resolved component and name, or undefined if not found
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const components = [
|
|
30
|
+
* { name: 'hero', type: 'section', content: '$title' }
|
|
31
|
+
* ]
|
|
32
|
+
* const resolved = resolveComponent('hero', components, { title: 'Welcome' })
|
|
33
|
+
* // { component: { type: 'section', content: 'Welcome' }, name: 'hero' }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function resolveComponent(
|
|
37
|
+
componentName: string,
|
|
38
|
+
components?: Components,
|
|
39
|
+
vars?: Record<string, string | number | boolean>
|
|
40
|
+
): { readonly component: Component; readonly name: string } | undefined {
|
|
41
|
+
const template = components?.find((b) => b.name === componentName)
|
|
42
|
+
if (!template) {
|
|
43
|
+
// DEVELOPMENT WARNING: Keep console.warn for development debugging
|
|
44
|
+
// This warning alerts developers when a referenced component doesn't exist
|
|
45
|
+
// Helps identify typos or missing component definitions during development
|
|
46
|
+
// Safe to keep - provides helpful feedback for configuration errors
|
|
47
|
+
console.warn(`Component not found: ${componentName}`)
|
|
48
|
+
return undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Cast template.children to Component children type for type compatibility
|
|
52
|
+
const templateChildren = template.children as ReadonlyArray<Component | string> | undefined
|
|
53
|
+
|
|
54
|
+
const component: Component = {
|
|
55
|
+
type: template.type,
|
|
56
|
+
props: substitutePropsVariables(template.props, vars),
|
|
57
|
+
children: substituteChildrenVariables(templateChildren, vars),
|
|
58
|
+
content:
|
|
59
|
+
typeof template.content === 'string'
|
|
60
|
+
? (substituteVariableValues(template.content, vars) as string)
|
|
61
|
+
: template.content,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return { component, name: template.name }
|
|
65
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
// Barrel export for component system utilities
|
|
9
|
+
// Files will be added during migration
|
|
@@ -0,0 +1,394 @@
|
|
|
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 { Theme } from '@/domain/models/app/theme'
|
|
9
|
+
import type { ReactElement, ReactNode } from 'react'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extracted theme tokens for Hero component
|
|
13
|
+
*/
|
|
14
|
+
interface HeroThemeTokens {
|
|
15
|
+
readonly breakpoints: {
|
|
16
|
+
readonly sm: number
|
|
17
|
+
readonly md: number
|
|
18
|
+
readonly lg: number
|
|
19
|
+
}
|
|
20
|
+
readonly colors: {
|
|
21
|
+
readonly background: string
|
|
22
|
+
readonly text: string
|
|
23
|
+
readonly primary: string
|
|
24
|
+
}
|
|
25
|
+
readonly spacing: {
|
|
26
|
+
readonly section: string
|
|
27
|
+
}
|
|
28
|
+
readonly borderRadius: {
|
|
29
|
+
readonly lg: string
|
|
30
|
+
}
|
|
31
|
+
readonly fonts: {
|
|
32
|
+
readonly title: {
|
|
33
|
+
readonly family: string
|
|
34
|
+
readonly weight: number
|
|
35
|
+
readonly size: string
|
|
36
|
+
}
|
|
37
|
+
readonly body: {
|
|
38
|
+
readonly family: string
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Default theme values
|
|
45
|
+
*/
|
|
46
|
+
const DEFAULT_THEME = {
|
|
47
|
+
breakpoints: { sm: '640px', md: '768px', lg: '1024px' },
|
|
48
|
+
colors: { background: '#ffffff', text: '#212529', primary: '#007bff' },
|
|
49
|
+
spacing: { section: '4rem' },
|
|
50
|
+
borderRadius: { lg: '0.5rem' },
|
|
51
|
+
fonts: {
|
|
52
|
+
title: { family: 'Bely Display', weight: 700, size: '2.5rem' },
|
|
53
|
+
body: { family: 'Inter' },
|
|
54
|
+
},
|
|
55
|
+
} as const
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Extract breakpoint values from theme
|
|
59
|
+
*/
|
|
60
|
+
function extractBreakpoints(theme?: Theme): HeroThemeTokens['breakpoints'] {
|
|
61
|
+
return {
|
|
62
|
+
sm: parseInt(theme?.breakpoints?.sm ?? DEFAULT_THEME.breakpoints.sm, 10),
|
|
63
|
+
md: parseInt(theme?.breakpoints?.md ?? DEFAULT_THEME.breakpoints.md, 10),
|
|
64
|
+
lg: parseInt(theme?.breakpoints?.lg ?? DEFAULT_THEME.breakpoints.lg, 10),
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extract color values from theme
|
|
70
|
+
*/
|
|
71
|
+
function extractColors(theme?: Theme): HeroThemeTokens['colors'] {
|
|
72
|
+
return {
|
|
73
|
+
background: theme?.colors?.background ?? DEFAULT_THEME.colors.background,
|
|
74
|
+
text: theme?.colors?.text ?? DEFAULT_THEME.colors.text,
|
|
75
|
+
primary: theme?.colors?.primary ?? DEFAULT_THEME.colors.primary,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Type helper for a single font configuration item
|
|
81
|
+
*/
|
|
82
|
+
type FontItem = NonNullable<Theme['fonts']>[string]
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Extract title font weight (handles both legacy and current schemas)
|
|
86
|
+
*/
|
|
87
|
+
function extractTitleWeight(titleFont?: FontItem): number {
|
|
88
|
+
// @ts-expect-error - legacy schema support (weight as number)
|
|
89
|
+
const legacyWeight = titleFont?.weight as number | undefined
|
|
90
|
+
const currentWeight = titleFont?.weights?.[0]
|
|
91
|
+
return legacyWeight ?? currentWeight ?? DEFAULT_THEME.fonts.title.weight
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extract title font configuration
|
|
96
|
+
*/
|
|
97
|
+
function extractTitleFont(titleFont?: FontItem): HeroThemeTokens['fonts']['title'] {
|
|
98
|
+
return {
|
|
99
|
+
family: titleFont?.family ?? DEFAULT_THEME.fonts.title.family,
|
|
100
|
+
weight: extractTitleWeight(titleFont),
|
|
101
|
+
size: titleFont?.size ?? DEFAULT_THEME.fonts.title.size,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Extract font values from theme
|
|
107
|
+
*/
|
|
108
|
+
function extractFonts(theme?: Theme): HeroThemeTokens['fonts'] {
|
|
109
|
+
return {
|
|
110
|
+
title: extractTitleFont(theme?.fonts?.title),
|
|
111
|
+
body: {
|
|
112
|
+
family: theme?.fonts?.body?.family ?? DEFAULT_THEME.fonts.body.family,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Extract and normalize theme tokens for Hero component
|
|
119
|
+
*/
|
|
120
|
+
function extractHeroTheme(theme?: Theme): HeroThemeTokens {
|
|
121
|
+
return {
|
|
122
|
+
breakpoints: extractBreakpoints(theme),
|
|
123
|
+
colors: extractColors(theme),
|
|
124
|
+
spacing: {
|
|
125
|
+
// Use explicit theme.spacing.section if provided, otherwise use mobile-first default
|
|
126
|
+
section: theme?.spacing?.section ?? '2rem',
|
|
127
|
+
},
|
|
128
|
+
borderRadius: {
|
|
129
|
+
lg: theme?.borderRadius?.lg ?? DEFAULT_THEME.borderRadius.lg,
|
|
130
|
+
},
|
|
131
|
+
fonts: extractFonts(theme),
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Default content demonstrating cohesive theme integration
|
|
137
|
+
*/
|
|
138
|
+
function HeroDefaultContent({
|
|
139
|
+
themeTokens,
|
|
140
|
+
}: Readonly<{
|
|
141
|
+
readonly themeTokens: HeroThemeTokens
|
|
142
|
+
}>): ReactElement {
|
|
143
|
+
return (
|
|
144
|
+
<div
|
|
145
|
+
style={{
|
|
146
|
+
textAlign: 'center',
|
|
147
|
+
maxWidth: '800px',
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
<h1
|
|
151
|
+
style={{
|
|
152
|
+
fontFamily: themeTokens.fonts.title.family,
|
|
153
|
+
fontWeight: themeTokens.fonts.title.weight,
|
|
154
|
+
fontSize: themeTokens.fonts.title.size,
|
|
155
|
+
color: themeTokens.colors.text,
|
|
156
|
+
marginBottom: '2rem',
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
Welcome to Sovrium
|
|
160
|
+
</h1>
|
|
161
|
+
<button
|
|
162
|
+
style={{
|
|
163
|
+
backgroundColor: themeTokens.colors.primary,
|
|
164
|
+
color: '#ffffff',
|
|
165
|
+
fontFamily: themeTokens.fonts.body.family,
|
|
166
|
+
fontSize: '1rem',
|
|
167
|
+
padding: '0.75rem 1.5rem',
|
|
168
|
+
borderRadius: themeTokens.borderRadius.lg,
|
|
169
|
+
border: 'none',
|
|
170
|
+
cursor: 'pointer',
|
|
171
|
+
}}
|
|
172
|
+
>
|
|
173
|
+
Get Started
|
|
174
|
+
</button>
|
|
175
|
+
</div>
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Generate responsive media query styles for Hero section
|
|
181
|
+
*/
|
|
182
|
+
function generateHeroMediaQueries(
|
|
183
|
+
breakpoints: HeroThemeTokens['breakpoints'],
|
|
184
|
+
testId?: string
|
|
185
|
+
): string {
|
|
186
|
+
return `
|
|
187
|
+
@media (min-width: ${breakpoints.sm}px) {
|
|
188
|
+
section[data-testid="${testId}"] {
|
|
189
|
+
padding: 3rem;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
@media (min-width: ${breakpoints.md}px) {
|
|
193
|
+
section[data-testid="${testId}"] {
|
|
194
|
+
padding: 4rem;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
@media (min-width: ${breakpoints.lg}px) {
|
|
198
|
+
section[data-testid="${testId}"] {
|
|
199
|
+
padding: 5rem;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
`
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Resolve easing token from theme
|
|
207
|
+
*/
|
|
208
|
+
function resolveEasingToken(tokenName: string, theme?: Theme): string | undefined {
|
|
209
|
+
if (!theme?.animations) return undefined
|
|
210
|
+
const animations = theme.animations as Record<string, unknown>
|
|
211
|
+
const easingTokens = animations.easing as Record<string, unknown> | undefined
|
|
212
|
+
if (!easingTokens || typeof easingTokens !== 'object') return undefined
|
|
213
|
+
const easingValue = easingTokens[tokenName]
|
|
214
|
+
return easingValue ? String(easingValue) : undefined
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Resolve color token from theme
|
|
219
|
+
*/
|
|
220
|
+
function resolveColorToken(tokenName: string, theme?: Theme): string | undefined {
|
|
221
|
+
if (!theme?.colors) return undefined
|
|
222
|
+
const colorValue = theme.colors[tokenName]
|
|
223
|
+
return colorValue ? String(colorValue) : undefined
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Resolve single token reference
|
|
228
|
+
*/
|
|
229
|
+
function resolveSingleToken(category: string, tokenName: string, theme?: Theme): string {
|
|
230
|
+
if (category === 'easing') {
|
|
231
|
+
return resolveEasingToken(tokenName, theme) ?? `$${category}.${tokenName}`
|
|
232
|
+
}
|
|
233
|
+
if (category === 'colors') {
|
|
234
|
+
return resolveColorToken(tokenName, theme) ?? `$${category}.${tokenName}`
|
|
235
|
+
}
|
|
236
|
+
return `$${category}.${tokenName}`
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Resolve token references in animation string
|
|
241
|
+
* Supports: $easing.smooth, $colors.primary, etc.
|
|
242
|
+
*/
|
|
243
|
+
function resolveAnimationTokens(animation: string, theme?: Theme): string {
|
|
244
|
+
return animation.replace(/\$(\w+)\.(\w+)/g, (_match, category, tokenName) =>
|
|
245
|
+
resolveSingleToken(category, tokenName, theme)
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Content structure for Hero section
|
|
251
|
+
*/
|
|
252
|
+
interface HeroContent {
|
|
253
|
+
readonly button?: {
|
|
254
|
+
readonly text: string
|
|
255
|
+
readonly animation?: string
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Base section styles for Hero component
|
|
261
|
+
*/
|
|
262
|
+
const heroSectionBaseStyle = {
|
|
263
|
+
minHeight: '200px',
|
|
264
|
+
display: 'flex',
|
|
265
|
+
alignItems: 'center',
|
|
266
|
+
justifyContent: 'center',
|
|
267
|
+
} as const
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Check if theme has fadeInUp animation configured
|
|
271
|
+
*/
|
|
272
|
+
function hasFadeInUpAnimation(theme?: Theme): boolean {
|
|
273
|
+
if (!theme?.animations) return false
|
|
274
|
+
const animations = theme.animations as Record<string, unknown>
|
|
275
|
+
return Boolean(animations.fadeInUp)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Build section style with theme tokens
|
|
280
|
+
*/
|
|
281
|
+
function buildHeroSectionStyle(themeTokens: HeroThemeTokens): Record<string, string> {
|
|
282
|
+
return {
|
|
283
|
+
...heroSectionBaseStyle,
|
|
284
|
+
backgroundColor: themeTokens.colors.background,
|
|
285
|
+
padding: themeTokens.spacing.section,
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Render Hero section with custom animated button
|
|
291
|
+
*/
|
|
292
|
+
function HeroWithButton({
|
|
293
|
+
themeTokens,
|
|
294
|
+
buttonContent,
|
|
295
|
+
testId,
|
|
296
|
+
theme,
|
|
297
|
+
}: Readonly<{
|
|
298
|
+
readonly themeTokens: HeroThemeTokens
|
|
299
|
+
readonly buttonContent: NonNullable<HeroContent['button']>
|
|
300
|
+
readonly testId?: string
|
|
301
|
+
readonly theme?: Theme
|
|
302
|
+
}>): ReactElement {
|
|
303
|
+
const resolvedAnimation = buttonContent.animation
|
|
304
|
+
? resolveAnimationTokens(buttonContent.animation, theme)
|
|
305
|
+
: undefined
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<section
|
|
309
|
+
data-testid={testId}
|
|
310
|
+
style={buildHeroSectionStyle(themeTokens)}
|
|
311
|
+
>
|
|
312
|
+
<button
|
|
313
|
+
data-testid="animated-cta"
|
|
314
|
+
style={{
|
|
315
|
+
backgroundColor: themeTokens.colors.primary,
|
|
316
|
+
color: '#ffffff',
|
|
317
|
+
fontFamily: themeTokens.fonts.body.family,
|
|
318
|
+
fontSize: '1rem',
|
|
319
|
+
padding: '0.75rem 1.5rem',
|
|
320
|
+
borderRadius: themeTokens.borderRadius.lg,
|
|
321
|
+
border: 'none',
|
|
322
|
+
cursor: 'pointer',
|
|
323
|
+
animation: resolvedAnimation,
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
326
|
+
{buttonContent.text}
|
|
327
|
+
</button>
|
|
328
|
+
<style>{generateHeroMediaQueries(themeTokens.breakpoints, testId)}</style>
|
|
329
|
+
</section>
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Hero Section Component
|
|
335
|
+
*
|
|
336
|
+
* Renders a hero section with full theme integration demonstrating cohesive UI.
|
|
337
|
+
* When no children are provided, renders default content (h1 heading + CTA button)
|
|
338
|
+
* that showcases all theme tokens applied together:
|
|
339
|
+
* - Background color (theme.colors.background)
|
|
340
|
+
* - Heading with theme fonts (family, size, weight, color)
|
|
341
|
+
* - Button with theme colors and border radius
|
|
342
|
+
* - Section padding (theme.spacing.section)
|
|
343
|
+
*
|
|
344
|
+
* Uses theme.breakpoints to determine responsive behavior via CSS custom properties.
|
|
345
|
+
* Applies progressive enhancement - padding increases as viewport grows.
|
|
346
|
+
*
|
|
347
|
+
* @param props - Component props
|
|
348
|
+
* @param props.theme - Theme configuration with all design tokens
|
|
349
|
+
* @param props.content - Structured content (button, etc.)
|
|
350
|
+
* @param props.children - Hero content (optional - defaults to themed heading + button)
|
|
351
|
+
* @param props.data-testid - Test identifier
|
|
352
|
+
* @returns Hero section element with cohesive theme integration
|
|
353
|
+
*/
|
|
354
|
+
export function Hero({
|
|
355
|
+
theme,
|
|
356
|
+
content,
|
|
357
|
+
children,
|
|
358
|
+
...props
|
|
359
|
+
}: Readonly<{
|
|
360
|
+
readonly theme?: Theme
|
|
361
|
+
readonly content?: HeroContent
|
|
362
|
+
readonly children?: ReactNode
|
|
363
|
+
readonly 'data-testid'?: string
|
|
364
|
+
}>): Readonly<ReactElement> {
|
|
365
|
+
const themeTokens = extractHeroTheme(theme)
|
|
366
|
+
|
|
367
|
+
if (content?.button) {
|
|
368
|
+
return (
|
|
369
|
+
<HeroWithButton
|
|
370
|
+
themeTokens={themeTokens}
|
|
371
|
+
buttonContent={content.button}
|
|
372
|
+
testId={props['data-testid']}
|
|
373
|
+
theme={theme}
|
|
374
|
+
/>
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const hasChildren =
|
|
379
|
+
children && (Array.isArray(children) ? children.length > 0 : Boolean(children))
|
|
380
|
+
const renderedContent = hasChildren ? children : <HeroDefaultContent themeTokens={themeTokens} />
|
|
381
|
+
const shouldAnimateFadeInUp = hasFadeInUpAnimation(theme)
|
|
382
|
+
const sectionClassName = shouldAnimateFadeInUp ? 'animate-fadeInUp' : undefined
|
|
383
|
+
|
|
384
|
+
return (
|
|
385
|
+
<section
|
|
386
|
+
data-testid={props['data-testid']}
|
|
387
|
+
style={buildHeroSectionStyle(themeTokens)}
|
|
388
|
+
className={sectionClassName}
|
|
389
|
+
>
|
|
390
|
+
{renderedContent}
|
|
391
|
+
<style>{generateHeroMediaQueries(themeTokens.breakpoints, props['data-testid'])}</style>
|
|
392
|
+
</section>
|
|
393
|
+
)
|
|
394
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
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 { buildHoverTransitionStyles } from '../styling/hover-interaction-handler'
|
|
9
|
+
import { applySpacingStyles } from '../styling/spacing-resolver'
|
|
10
|
+
import { buildFinalClassName, processComponentStyle } from '../styling/style-processor'
|
|
11
|
+
import { substitutePropsThemeTokens } from '../styling/theme-tokens'
|
|
12
|
+
import {
|
|
13
|
+
extractTranslationKeyFromContent,
|
|
14
|
+
findFirstTranslationKey,
|
|
15
|
+
getTranslationData,
|
|
16
|
+
substitutePropsTranslationTokens,
|
|
17
|
+
} from '../translations/translation-handler'
|
|
18
|
+
import { buildElementProps } from './props-builder'
|
|
19
|
+
import type { Languages } from '@/domain/models/app/languages'
|
|
20
|
+
import type { Interactions } from '@/domain/models/app/page/common/interactions/interactions'
|
|
21
|
+
import type { Component } from '@/domain/models/app/page/sections'
|
|
22
|
+
import type { Theme } from '@/domain/models/app/theme'
|
|
23
|
+
import type { ReactElement } from 'react'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for building component props
|
|
27
|
+
*/
|
|
28
|
+
export type ComponentPropsConfig = {
|
|
29
|
+
readonly type: string
|
|
30
|
+
readonly props: Record<string, unknown> | undefined
|
|
31
|
+
readonly children: ReadonlyArray<Component | string> | undefined
|
|
32
|
+
readonly content: string | undefined
|
|
33
|
+
readonly componentName: string | undefined
|
|
34
|
+
readonly componentInstanceIndex: number | undefined
|
|
35
|
+
readonly theme: Theme | undefined
|
|
36
|
+
readonly languages: Languages | undefined
|
|
37
|
+
readonly currentLang: string | undefined
|
|
38
|
+
readonly childIndex: number | undefined
|
|
39
|
+
readonly interactions: Interactions | undefined
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Result of component props building
|
|
44
|
+
*/
|
|
45
|
+
export type ComponentPropsResult = {
|
|
46
|
+
readonly elementProps: Record<string, unknown>
|
|
47
|
+
readonly elementPropsWithSpacing: Record<string, unknown>
|
|
48
|
+
readonly renderedChildren: ReadonlyArray<ReactElement | string | null>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Props configuration for component rendering
|
|
53
|
+
*/
|
|
54
|
+
export type RenderPropsConfig = {
|
|
55
|
+
readonly components?: unknown
|
|
56
|
+
readonly theme?: Theme
|
|
57
|
+
readonly languages?: Languages
|
|
58
|
+
readonly currentLang?: string
|
|
59
|
+
readonly componentInstanceIndex?: number
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Applies token substitutions to component props
|
|
64
|
+
*
|
|
65
|
+
* @param props - Original props
|
|
66
|
+
* @param currentLang - Current language
|
|
67
|
+
* @param languages - Languages configuration
|
|
68
|
+
* @param theme - Theme configuration
|
|
69
|
+
* @returns Props with all tokens substituted
|
|
70
|
+
*/
|
|
71
|
+
function applyTokenSubstitutions(
|
|
72
|
+
props: Record<string, unknown> | undefined,
|
|
73
|
+
currentLang: string | undefined,
|
|
74
|
+
languages: Languages | undefined,
|
|
75
|
+
theme: Theme | undefined
|
|
76
|
+
): Record<string, unknown> | undefined {
|
|
77
|
+
// Translation token substitution (must happen before theme tokens)
|
|
78
|
+
const translationSubstitutedProps = substitutePropsTranslationTokens(
|
|
79
|
+
props,
|
|
80
|
+
currentLang,
|
|
81
|
+
languages
|
|
82
|
+
)
|
|
83
|
+
// Theme token substitution
|
|
84
|
+
return substitutePropsThemeTokens(translationSubstitutedProps, theme)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Prepares processed component values (tokens, translations, styles, className)
|
|
89
|
+
*
|
|
90
|
+
* @param config - Component props configuration
|
|
91
|
+
* @returns Processed intermediate values
|
|
92
|
+
*/
|
|
93
|
+
function prepareProcessedValues(config: ComponentPropsConfig) {
|
|
94
|
+
const { type, props, children, content, currentLang, languages, theme, interactions } = config
|
|
95
|
+
|
|
96
|
+
const substitutedProps = applyTokenSubstitutions(props, currentLang, languages, theme)
|
|
97
|
+
// Check both children and content for translation keys
|
|
98
|
+
const firstTranslationKey =
|
|
99
|
+
findFirstTranslationKey(children) || extractTranslationKeyFromContent(content)
|
|
100
|
+
const translationData = getTranslationData(firstTranslationKey, languages)
|
|
101
|
+
const styleWithShadow = processComponentStyle(
|
|
102
|
+
type,
|
|
103
|
+
substitutedProps?.style,
|
|
104
|
+
theme,
|
|
105
|
+
substitutedProps
|
|
106
|
+
)
|
|
107
|
+
const hoverTransitionStyles = buildHoverTransitionStyles(interactions?.hover)
|
|
108
|
+
const finalClassName = buildFinalClassName({
|
|
109
|
+
type,
|
|
110
|
+
className: substitutedProps?.className,
|
|
111
|
+
substitutedProps,
|
|
112
|
+
interactions,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Merge hover transition styles with existing styles
|
|
116
|
+
const styleWithHover = hoverTransitionStyles
|
|
117
|
+
? { ...styleWithShadow, ...hoverTransitionStyles }
|
|
118
|
+
: styleWithShadow
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
substitutedProps,
|
|
122
|
+
firstTranslationKey,
|
|
123
|
+
translationData,
|
|
124
|
+
styleWithShadow: styleWithHover,
|
|
125
|
+
finalClassName,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Builds complete component props with all transformations applied
|
|
131
|
+
*
|
|
132
|
+
* Orchestrates: token substitution, translation handling, style processing,
|
|
133
|
+
* className finalization, element props building, and spacing styles application.
|
|
134
|
+
*
|
|
135
|
+
* @param config - Component props configuration
|
|
136
|
+
* @returns Complete element props with spacing
|
|
137
|
+
*/
|
|
138
|
+
export function buildComponentProps(config: ComponentPropsConfig): {
|
|
139
|
+
readonly substitutedProps: Record<string, unknown> | undefined
|
|
140
|
+
readonly firstTranslationKey: string | undefined
|
|
141
|
+
readonly translationData: Record<string, string> | undefined
|
|
142
|
+
readonly styleWithShadow: Record<string, unknown> | undefined
|
|
143
|
+
readonly finalClassName: string | undefined
|
|
144
|
+
readonly elementProps: Record<string, unknown>
|
|
145
|
+
readonly elementPropsWithSpacing: Record<string, unknown>
|
|
146
|
+
} {
|
|
147
|
+
const { type, content, children, componentName, componentInstanceIndex, theme, childIndex } =
|
|
148
|
+
config
|
|
149
|
+
|
|
150
|
+
const {
|
|
151
|
+
substitutedProps,
|
|
152
|
+
firstTranslationKey,
|
|
153
|
+
translationData,
|
|
154
|
+
styleWithShadow,
|
|
155
|
+
finalClassName,
|
|
156
|
+
} = prepareProcessedValues(config)
|
|
157
|
+
|
|
158
|
+
const elementProps = buildElementProps({
|
|
159
|
+
type,
|
|
160
|
+
substitutedProps,
|
|
161
|
+
finalClassName,
|
|
162
|
+
styleWithShadow,
|
|
163
|
+
componentName,
|
|
164
|
+
componentInstanceIndex,
|
|
165
|
+
firstTranslationKey,
|
|
166
|
+
translationData,
|
|
167
|
+
hasContent: Boolean(content || children?.length),
|
|
168
|
+
hasChildren: Boolean(children?.length),
|
|
169
|
+
theme,
|
|
170
|
+
childIndex,
|
|
171
|
+
interactions: config.interactions,
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
substitutedProps,
|
|
176
|
+
firstTranslationKey,
|
|
177
|
+
translationData,
|
|
178
|
+
styleWithShadow,
|
|
179
|
+
finalClassName,
|
|
180
|
+
elementProps,
|
|
181
|
+
elementPropsWithSpacing: applySpacingStyles(type, elementProps, theme),
|
|
182
|
+
}
|
|
183
|
+
}
|