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,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { buildHoverData } from './hover-interaction-handler'
|
|
9
|
+
import type { Interactions } from '@/domain/models/app/page/common/interactions/interactions'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Merges hover attributes into element props
|
|
13
|
+
*
|
|
14
|
+
* @param elementProps - Base element props
|
|
15
|
+
* @param hoverData - Hover data with attributes
|
|
16
|
+
* @returns Element props with hover attributes merged
|
|
17
|
+
*/
|
|
18
|
+
function mergeHoverAttributes(
|
|
19
|
+
elementProps: Record<string, unknown>,
|
|
20
|
+
hoverData: { readonly attributes: Record<string, string> } | undefined
|
|
21
|
+
): Record<string, unknown> {
|
|
22
|
+
return hoverData ? { ...elementProps, ...hoverData.attributes } : elementProps
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds interaction props with hover data merged into element props
|
|
27
|
+
*
|
|
28
|
+
* @param interactions - Component interactions configuration
|
|
29
|
+
* @param uniqueId - Unique ID for hover data
|
|
30
|
+
* @param elementProps - Base element props
|
|
31
|
+
* @param elementPropsWithSpacing - Base element props with spacing
|
|
32
|
+
* @returns Element props with hover attributes and hover data for style injection
|
|
33
|
+
*/
|
|
34
|
+
export function buildInteractionProps(
|
|
35
|
+
interactions: Interactions | undefined,
|
|
36
|
+
uniqueId: string,
|
|
37
|
+
elementProps: Record<string, unknown>,
|
|
38
|
+
elementPropsWithSpacing: Record<string, unknown>
|
|
39
|
+
): {
|
|
40
|
+
readonly finalElementProps: Record<string, unknown>
|
|
41
|
+
readonly finalElementPropsWithSpacing: Record<string, unknown>
|
|
42
|
+
readonly hoverData:
|
|
43
|
+
| { readonly attributes: Record<string, string>; readonly styleContent: string }
|
|
44
|
+
| undefined
|
|
45
|
+
} {
|
|
46
|
+
const hoverData = buildHoverData(interactions?.hover, uniqueId)
|
|
47
|
+
const finalElementProps = mergeHoverAttributes(elementProps, hoverData)
|
|
48
|
+
const finalElementPropsWithSpacing = mergeHoverAttributes(elementPropsWithSpacing, hoverData)
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
finalElementProps,
|
|
52
|
+
finalElementPropsWithSpacing,
|
|
53
|
+
hoverData,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
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 { Component } from '@/domain/models/app/page/sections'
|
|
9
|
+
import type { Theme } from '@/domain/models/app/theme'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Standard shadow size names
|
|
13
|
+
*/
|
|
14
|
+
const STANDARD_SHADOWS = ['sm', 'md', 'lg', 'xl', '2xl', 'inner', 'none'] as const
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Shadow mapping for component types
|
|
18
|
+
*/
|
|
19
|
+
const COMPONENT_SHADOW_MAP: Record<string, readonly string[]> = {
|
|
20
|
+
'list-item': ['sm'],
|
|
21
|
+
dropdown: ['lg'],
|
|
22
|
+
modal: ['xl'],
|
|
23
|
+
input: ['inner'],
|
|
24
|
+
button: ['brand', 'md'],
|
|
25
|
+
card: [], // Card uses custom logic
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Find first available custom shadow (non-standard)
|
|
30
|
+
*/
|
|
31
|
+
function findCustomShadow(shadows: Theme['shadows']): string | undefined {
|
|
32
|
+
if (!shadows) return undefined
|
|
33
|
+
return Object.keys(shadows).find((name) => !STANDARD_SHADOWS.includes(name as never))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get shadow value for component type
|
|
38
|
+
*/
|
|
39
|
+
function getShadowForType(type: Component['type'], shadows: Theme['shadows']): string | undefined {
|
|
40
|
+
if (!shadows) return undefined
|
|
41
|
+
|
|
42
|
+
// Special handling for card: custom shadows first, then md
|
|
43
|
+
if (type === 'card') {
|
|
44
|
+
const customShadow = findCustomShadow(shadows)
|
|
45
|
+
if (customShadow) {
|
|
46
|
+
return `var(--shadow-${customShadow})`
|
|
47
|
+
}
|
|
48
|
+
return shadows.md ? 'var(--shadow-md)' : undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Standard component shadow resolution
|
|
52
|
+
const shadowPriority = COMPONENT_SHADOW_MAP[type]
|
|
53
|
+
if (!shadowPriority) {
|
|
54
|
+
return undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const foundShadow = shadowPriority.find((shadowName) =>
|
|
58
|
+
Boolean(shadows[shadowName as keyof typeof shadows])
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return foundShadow ? `var(--shadow-${foundShadow})` : undefined
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Apply theme shadows to component types based on conventions
|
|
66
|
+
* - Card components use available shadow tokens (md, neumorphic, etc.)
|
|
67
|
+
* - Modal components use xl shadow
|
|
68
|
+
* - Input components use inner shadow
|
|
69
|
+
* - Button components use md shadow (or custom like brand)
|
|
70
|
+
* - List-item components use sm shadow (lowest elevation)
|
|
71
|
+
* - Dropdown components use lg shadow (higher than card, lower than modal)
|
|
72
|
+
*/
|
|
73
|
+
export function getComponentShadow(
|
|
74
|
+
type: Component['type'],
|
|
75
|
+
theme?: Theme
|
|
76
|
+
): Record<string, unknown> | undefined {
|
|
77
|
+
if (!theme?.shadows) {
|
|
78
|
+
return undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const shadowValue = getShadowForType(type, theme.shadows)
|
|
82
|
+
return shadowValue ? { boxShadow: shadowValue } : undefined
|
|
83
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
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 { isCssValue } from '@/presentation/styling/style-utils'
|
|
9
|
+
import { getSectionColorStyle } from './color-resolver'
|
|
10
|
+
import type { Component } from '@/domain/models/app/page/sections'
|
|
11
|
+
import type { Theme } from '@/domain/models/app/theme'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Component types that should receive section spacing
|
|
15
|
+
*/
|
|
16
|
+
const SECTION_TYPES = new Set(['section', 'header', 'footer', 'hero'])
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Apply theme spacing to section elements when spacing.section is a CSS value
|
|
20
|
+
*/
|
|
21
|
+
export function getSectionSpacingStyle(
|
|
22
|
+
type: Component['type'],
|
|
23
|
+
theme?: Theme
|
|
24
|
+
): Record<string, unknown> | undefined {
|
|
25
|
+
const sectionSpacing = SECTION_TYPES.has(type) && theme?.spacing?.section
|
|
26
|
+
return sectionSpacing && isCssValue(sectionSpacing) ? { padding: sectionSpacing } : undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Apply theme spacing to container elements when spacing.container is a CSS value
|
|
31
|
+
*/
|
|
32
|
+
export function getContainerSpacingStyle(
|
|
33
|
+
type: Component['type'],
|
|
34
|
+
theme?: Theme
|
|
35
|
+
): Record<string, unknown> | undefined {
|
|
36
|
+
const containerSpacing = type === 'container' && theme?.spacing?.container
|
|
37
|
+
return containerSpacing && isCssValue(containerSpacing)
|
|
38
|
+
? { maxWidth: containerSpacing, margin: '0 auto' }
|
|
39
|
+
: undefined
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Apply theme spacing to flex elements when spacing.gap is a CSS value
|
|
44
|
+
*/
|
|
45
|
+
export function getFlexSpacingStyle(
|
|
46
|
+
type: Component['type'],
|
|
47
|
+
theme?: Theme
|
|
48
|
+
): Record<string, unknown> | undefined {
|
|
49
|
+
const flexSpacing = type === 'flex' && theme?.spacing?.gap
|
|
50
|
+
return flexSpacing && isCssValue(flexSpacing) ? { display: 'flex', gap: flexSpacing } : undefined
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Apply all spacing and color styles in order: color → section → container → flex
|
|
55
|
+
*/
|
|
56
|
+
export function applySpacingStyles(
|
|
57
|
+
type: Component['type'],
|
|
58
|
+
baseProps: Record<string, unknown>,
|
|
59
|
+
theme?: Theme
|
|
60
|
+
): Record<string, unknown> {
|
|
61
|
+
const colorStyle = getSectionColorStyle(type, theme)
|
|
62
|
+
const propsWithColor = colorStyle
|
|
63
|
+
? {
|
|
64
|
+
...baseProps,
|
|
65
|
+
style: {
|
|
66
|
+
...(baseProps.style as Record<string, unknown> | undefined),
|
|
67
|
+
...colorStyle,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
: baseProps
|
|
71
|
+
|
|
72
|
+
const sectionSpacingStyle = getSectionSpacingStyle(type, theme)
|
|
73
|
+
const propsWithSection = sectionSpacingStyle
|
|
74
|
+
? {
|
|
75
|
+
...propsWithColor,
|
|
76
|
+
style: {
|
|
77
|
+
...(propsWithColor.style as Record<string, unknown> | undefined),
|
|
78
|
+
...sectionSpacingStyle,
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
: propsWithColor
|
|
82
|
+
|
|
83
|
+
const containerSpacingStyle = getContainerSpacingStyle(type, theme)
|
|
84
|
+
const propsWithContainer = containerSpacingStyle
|
|
85
|
+
? {
|
|
86
|
+
...propsWithSection,
|
|
87
|
+
style: {
|
|
88
|
+
...(propsWithSection.style as Record<string, unknown> | undefined),
|
|
89
|
+
...containerSpacingStyle,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
: propsWithSection
|
|
93
|
+
|
|
94
|
+
const flexSpacingStyle = getFlexSpacingStyle(type, theme)
|
|
95
|
+
return flexSpacingStyle
|
|
96
|
+
? {
|
|
97
|
+
...propsWithContainer,
|
|
98
|
+
style: {
|
|
99
|
+
...(propsWithContainer.style as Record<string, unknown> | undefined),
|
|
100
|
+
...flexSpacingStyle,
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
: propsWithContainer
|
|
104
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
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
|
+
isCssProperty,
|
|
10
|
+
normalizeStyleAnimations,
|
|
11
|
+
parseStyle,
|
|
12
|
+
} from '@/presentation/styling/parse-style'
|
|
13
|
+
import { applyComponentAnimations } from './animation-composer-wrapper'
|
|
14
|
+
import { buildFlexClasses, buildGridClasses } from './class-builders'
|
|
15
|
+
import { getComponentShadow } from './shadow-resolver'
|
|
16
|
+
import type { Interactions } from '@/domain/models/app/page/common/interactions/interactions'
|
|
17
|
+
import type { Component } from '@/domain/models/app/page/sections'
|
|
18
|
+
import type { Theme } from '@/domain/models/app/theme'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extract CSS properties from props object
|
|
22
|
+
* Separates CSS properties (e.g., maxWidth, backgroundColor) from other props
|
|
23
|
+
*
|
|
24
|
+
* @param props - Props object that may contain CSS properties
|
|
25
|
+
* @returns Object with cssProps and remainingProps
|
|
26
|
+
*/
|
|
27
|
+
export function extractCssProperties(props: Record<string, unknown> | undefined): {
|
|
28
|
+
readonly cssProps: Record<string, unknown>
|
|
29
|
+
readonly remainingProps: Record<string, unknown>
|
|
30
|
+
} {
|
|
31
|
+
if (!props) {
|
|
32
|
+
return { cssProps: {}, remainingProps: {} }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Use reduce for immutable accumulation
|
|
36
|
+
return Object.entries(props).reduce<{
|
|
37
|
+
readonly cssProps: Record<string, unknown>
|
|
38
|
+
readonly remainingProps: Record<string, unknown>
|
|
39
|
+
}>(
|
|
40
|
+
(acc, [key, value]) => {
|
|
41
|
+
if (isCssProperty(key)) {
|
|
42
|
+
return {
|
|
43
|
+
...acc,
|
|
44
|
+
cssProps: { ...acc.cssProps, [key]: value },
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
...acc,
|
|
49
|
+
remainingProps: { ...acc.remainingProps, [key]: value },
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{ cssProps: {}, remainingProps: {} }
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Parse and normalize style object
|
|
58
|
+
* Extracts CSS properties from the root of the props object and merges them with the style property
|
|
59
|
+
*/
|
|
60
|
+
export function parseComponentStyle(
|
|
61
|
+
styleValue: unknown,
|
|
62
|
+
props: Record<string, unknown> | undefined
|
|
63
|
+
): Record<string, unknown> | undefined {
|
|
64
|
+
// Parse the explicit style property
|
|
65
|
+
const explicitStyle = styleValue
|
|
66
|
+
? normalizeStyleAnimations(
|
|
67
|
+
typeof styleValue === 'string'
|
|
68
|
+
? parseStyle(styleValue)
|
|
69
|
+
: (styleValue as Record<string, unknown>)
|
|
70
|
+
)
|
|
71
|
+
: undefined
|
|
72
|
+
|
|
73
|
+
// Extract CSS properties from props (excluding the style property itself)
|
|
74
|
+
const { cssProps } = extractCssProperties(props)
|
|
75
|
+
|
|
76
|
+
// Remove the style property from cssProps if it exists (already handled above)
|
|
77
|
+
const { style: _style, ...cssPropsWithoutStyle } = cssProps
|
|
78
|
+
|
|
79
|
+
// Merge CSS properties with explicit style
|
|
80
|
+
const mergedStyle = {
|
|
81
|
+
...cssPropsWithoutStyle,
|
|
82
|
+
...explicitStyle,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Object.keys(mergedStyle).length > 0 ? mergedStyle : undefined
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Maps component types to their corresponding CSS class names in @layer components.
|
|
90
|
+
* These classes are automatically added to the element when rendering.
|
|
91
|
+
*
|
|
92
|
+
* Most types map directly (e.g. 'card' -> 'card'), but 'button' maps to 'btn'
|
|
93
|
+
* because the CSS components layer uses `.btn` (not a `button` type selector)
|
|
94
|
+
* to avoid applying default button styles to all `<button>` elements globally.
|
|
95
|
+
*/
|
|
96
|
+
const COMPONENT_TYPE_CLASS_MAP: Partial<Record<string, string>> = {
|
|
97
|
+
card: 'card',
|
|
98
|
+
badge: 'badge',
|
|
99
|
+
btn: 'btn',
|
|
100
|
+
button: 'btn',
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Build entrance animation class from interactions
|
|
105
|
+
*
|
|
106
|
+
* @param interactions - Component interactions
|
|
107
|
+
* @returns Animation class or undefined
|
|
108
|
+
*/
|
|
109
|
+
function buildEntranceAnimationClass(interactions: Interactions | undefined): string | undefined {
|
|
110
|
+
if (!interactions?.entrance?.animation) return undefined
|
|
111
|
+
|
|
112
|
+
return `animate-${interactions.entrance.animation}`
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Configuration for building final className
|
|
117
|
+
*/
|
|
118
|
+
type BuildClassNameConfig = {
|
|
119
|
+
readonly type: Component['type']
|
|
120
|
+
readonly className: unknown
|
|
121
|
+
readonly substitutedProps: Record<string, unknown> | undefined
|
|
122
|
+
readonly interactions: Interactions | undefined
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Build final className based on component type
|
|
127
|
+
*/
|
|
128
|
+
export function buildFinalClassName(config: BuildClassNameConfig): string | undefined {
|
|
129
|
+
const { type, className, substitutedProps, interactions } = config
|
|
130
|
+
|
|
131
|
+
// Build classes array immutably
|
|
132
|
+
const typeClass = COMPONENT_TYPE_CLASS_MAP[type]
|
|
133
|
+
const flexClass = type === 'flex' ? buildFlexClasses(substitutedProps) : undefined
|
|
134
|
+
const gridClass = type === 'grid' ? buildGridClasses(substitutedProps) : undefined
|
|
135
|
+
const customClass = className as string | undefined
|
|
136
|
+
const entranceClass = buildEntranceAnimationClass(interactions)
|
|
137
|
+
// Don't add scroll animation class to initial className - it will be added by scroll-animation.js
|
|
138
|
+
const scrollClass = undefined
|
|
139
|
+
|
|
140
|
+
const classes = [typeClass, flexClass, gridClass, customClass, entranceClass, scrollClass]
|
|
141
|
+
.filter(Boolean)
|
|
142
|
+
.join(' ')
|
|
143
|
+
return classes || undefined
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Apply shadow to style based on component type
|
|
148
|
+
*/
|
|
149
|
+
export function applyComponentShadow(
|
|
150
|
+
type: Component['type'],
|
|
151
|
+
style: Record<string, unknown> | undefined,
|
|
152
|
+
theme: Theme | undefined
|
|
153
|
+
): Record<string, unknown> | undefined {
|
|
154
|
+
const componentShadow = getComponentShadow(type, theme)
|
|
155
|
+
return componentShadow ? { ...style, ...componentShadow } : style
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Process style with animations and shadows
|
|
160
|
+
*/
|
|
161
|
+
export function processComponentStyle(
|
|
162
|
+
type: Component['type'],
|
|
163
|
+
styleValue: unknown,
|
|
164
|
+
theme: Theme | undefined,
|
|
165
|
+
props?: Record<string, unknown> | undefined
|
|
166
|
+
): Record<string, unknown> | undefined {
|
|
167
|
+
const baseStyle = parseComponentStyle(styleValue, props)
|
|
168
|
+
const styleWithAnimations = applyComponentAnimations(type, baseStyle, theme)
|
|
169
|
+
return applyComponentShadow(type, styleWithAnimations, theme)
|
|
170
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Substitutes theme tokens in a value
|
|
12
|
+
*
|
|
13
|
+
* Replaces `$theme.category.key` patterns with actual theme values.
|
|
14
|
+
* Supports multiple tokens in a single string.
|
|
15
|
+
*
|
|
16
|
+
* @param value - Value that may contain theme tokens
|
|
17
|
+
* @param theme - Theme configuration
|
|
18
|
+
* @returns Value with theme tokens replaced
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const theme = {
|
|
23
|
+
* colors: { primary: '#007bff' },
|
|
24
|
+
* spacing: { section: 'py-16', container: 'px-4' }
|
|
25
|
+
* }
|
|
26
|
+
* substituteThemeTokens('$theme.colors.primary', theme)
|
|
27
|
+
* // '#007bff'
|
|
28
|
+
*
|
|
29
|
+
* substituteThemeTokens('$theme.spacing.section $theme.spacing.container', theme)
|
|
30
|
+
* // 'py-16 px-4'
|
|
31
|
+
*
|
|
32
|
+
* substituteThemeTokens('static', theme)
|
|
33
|
+
* // 'static'
|
|
34
|
+
*
|
|
35
|
+
* substituteThemeTokens(123, theme)
|
|
36
|
+
* // 123
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function substituteThemeTokens(value: unknown, theme?: Theme): unknown {
|
|
40
|
+
if (typeof value !== 'string') {
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!theme || !value.includes('$theme.')) {
|
|
45
|
+
return value
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Handle multiple theme tokens in a single string
|
|
49
|
+
// Example: "$theme.spacing.section $theme.spacing.container" → "py-16 px-4"
|
|
50
|
+
// Supports color names with numbers like gray-100, primary-500, etc.
|
|
51
|
+
return value.replace(/\$theme\.[a-z]+(\.[a-z0-9-]+)+/g, (match) => {
|
|
52
|
+
// Extract the path: $theme.colors.primary → ['colors', 'primary']
|
|
53
|
+
const path = match.slice(7).split('.')
|
|
54
|
+
|
|
55
|
+
// Navigate through the theme object using functional reduce
|
|
56
|
+
const result = path.reduce<unknown>((acc, key) => {
|
|
57
|
+
if (acc && typeof acc === 'object' && key in acc) {
|
|
58
|
+
return (acc as Record<string, unknown>)[key]
|
|
59
|
+
}
|
|
60
|
+
// Return a sentinel to indicate path not found
|
|
61
|
+
return undefined
|
|
62
|
+
}, theme as unknown)
|
|
63
|
+
|
|
64
|
+
// If path navigation failed, return original token
|
|
65
|
+
return result !== undefined ? String(result) : match
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve shorthand theme token reference
|
|
71
|
+
*
|
|
72
|
+
* Handles tokens in format: $category.key (e.g., $easing.smooth, $colors.primary)
|
|
73
|
+
* without the `theme.` prefix.
|
|
74
|
+
*
|
|
75
|
+
* @param category - Theme category (colors, easing, spacing, etc.)
|
|
76
|
+
* @param tokenName - Token key within category
|
|
77
|
+
* @param theme - Theme configuration
|
|
78
|
+
* @returns Resolved token value or original token string if not found
|
|
79
|
+
*/
|
|
80
|
+
function resolveShorthandToken(category: string, tokenName: string, theme?: Theme): string {
|
|
81
|
+
if (!theme) return `$${category}.${tokenName}`
|
|
82
|
+
|
|
83
|
+
const themeCategory = theme[category as keyof Theme]
|
|
84
|
+
if (!themeCategory || typeof themeCategory !== 'object') {
|
|
85
|
+
return `$${category}.${tokenName}`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Handle nested animations category (easing, duration, keyframes)
|
|
89
|
+
if (category === 'easing' && theme.animations) {
|
|
90
|
+
const animations = theme.animations as Record<string, unknown>
|
|
91
|
+
const easingTokens = animations.easing as Record<string, unknown> | undefined
|
|
92
|
+
if (easingTokens && typeof easingTokens === 'object') {
|
|
93
|
+
const value = easingTokens[tokenName]
|
|
94
|
+
return value !== undefined ? String(value) : `$${category}.${tokenName}`
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const value = (themeCategory as Record<string, unknown>)[tokenName]
|
|
99
|
+
return value !== undefined ? String(value) : `$${category}.${tokenName}`
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Resolve shorthand theme tokens in string
|
|
104
|
+
*
|
|
105
|
+
* Replaces tokens in format: $category.key (e.g., $easing.smooth, $colors.primary)
|
|
106
|
+
* Supports multiple tokens in a single string.
|
|
107
|
+
*
|
|
108
|
+
* @param value - String that may contain shorthand theme tokens
|
|
109
|
+
* @param theme - Theme configuration
|
|
110
|
+
* @returns String with shorthand tokens replaced
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const theme = {
|
|
115
|
+
* colors: { primary: '#007bff' },
|
|
116
|
+
* animations: { easing: { smooth: 'cubic-bezier(0.4, 0, 0.2, 1)' } }
|
|
117
|
+
* }
|
|
118
|
+
* resolveShorthandThemeTokens('colorPulse 2s $easing.smooth infinite', theme)
|
|
119
|
+
* // 'colorPulse 2s cubic-bezier(0.4, 0, 0.2, 1) infinite'
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
function resolveShorthandThemeTokens(value: unknown, theme?: Theme): unknown {
|
|
123
|
+
if (typeof value !== 'string') {
|
|
124
|
+
return value
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!theme || !value.includes('$')) {
|
|
128
|
+
return value
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Replace shorthand tokens: $category.key (without theme. prefix)
|
|
132
|
+
return value.replace(/\$(\w+)\.(\w+)/g, (_match, category, tokenName) =>
|
|
133
|
+
resolveShorthandToken(category, tokenName, theme)
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Substitutes theme tokens in props recursively
|
|
139
|
+
*
|
|
140
|
+
* Walks through props object and replaces all theme token strings with actual theme values.
|
|
141
|
+
* Handles nested objects (e.g., style props) recursively.
|
|
142
|
+
* Supports both full syntax ($theme.colors.primary) and shorthand ($colors.primary, $easing.smooth).
|
|
143
|
+
*
|
|
144
|
+
* @param props - Component props that may contain theme tokens
|
|
145
|
+
* @param theme - Theme configuration
|
|
146
|
+
* @returns Props with theme tokens replaced
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* const theme = { colors: { primary: '#007bff', secondary: '#6c757d' } }
|
|
151
|
+
* const props = {
|
|
152
|
+
* color: '$theme.colors.primary',
|
|
153
|
+
* style: { backgroundColor: '$theme.colors.secondary' }
|
|
154
|
+
* }
|
|
155
|
+
* substitutePropsThemeTokens(props, theme)
|
|
156
|
+
* // {
|
|
157
|
+
* // color: '#007bff',
|
|
158
|
+
* // style: { backgroundColor: '#6c757d' }
|
|
159
|
+
* // }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export function substitutePropsThemeTokens(
|
|
163
|
+
props: Record<string, unknown> | undefined,
|
|
164
|
+
theme?: Theme
|
|
165
|
+
): Record<string, unknown> | undefined {
|
|
166
|
+
if (!props || !theme) {
|
|
167
|
+
return props
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Use functional Object.entries + reduce for immutable transformation
|
|
171
|
+
return Object.entries(props).reduce<Record<string, unknown>>((acc, [key, value]) => {
|
|
172
|
+
if (typeof value === 'string') {
|
|
173
|
+
// Apply both full syntax and shorthand token resolution
|
|
174
|
+
const fullSyntaxResolved = substituteThemeTokens(value, theme)
|
|
175
|
+
const shorthandResolved = resolveShorthandThemeTokens(fullSyntaxResolved, theme)
|
|
176
|
+
return { ...acc, [key]: shorthandResolved }
|
|
177
|
+
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
178
|
+
// Recursively handle nested objects (like style props)
|
|
179
|
+
return { ...acc, [key]: substitutePropsThemeTokens(value as Record<string, unknown>, theme) }
|
|
180
|
+
} else {
|
|
181
|
+
return { ...acc, [key]: value }
|
|
182
|
+
}
|
|
183
|
+
}, {})
|
|
184
|
+
}
|