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,77 @@
|
|
|
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 { Schema } from 'effect'
|
|
9
|
+
import { HttpUrlSchema } from '../common/url'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* DNS prefetch domain URL
|
|
13
|
+
*
|
|
14
|
+
* Absolute URL to external domain for DNS prefetching.
|
|
15
|
+
* - Pattern: ^https?:// (must start with http:// or https://)
|
|
16
|
+
* - Examples: https://fonts.googleapis.com, https://www.google-analytics.com
|
|
17
|
+
* - Format: uri (valid URL)
|
|
18
|
+
*/
|
|
19
|
+
export const DnsPrefetchDomainSchema = HttpUrlSchema.annotations({
|
|
20
|
+
description: 'Domain to prefetch DNS for',
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* DNS prefetch hints for external domains
|
|
25
|
+
*
|
|
26
|
+
* Array of external domain URLs to perform DNS resolution early in page load.
|
|
27
|
+
* Reduces connection latency by resolving domain names before resources are requested.
|
|
28
|
+
*
|
|
29
|
+
* How DNS prefetch works:
|
|
30
|
+
* 1. Browser receives <link rel="dns-prefetch" href="..."> in <head>
|
|
31
|
+
* 2. Browser resolves domain name to IP address in the background
|
|
32
|
+
* 3. When resource is later requested, DNS is already resolved (faster connection)
|
|
33
|
+
* 4. Reduces latency by 20-120ms per domain (DNS lookup time)
|
|
34
|
+
*
|
|
35
|
+
* Common use cases:
|
|
36
|
+
* - **Fonts**: https://fonts.googleapis.com, https://fonts.gstatic.com
|
|
37
|
+
* - **Analytics**: https://www.google-analytics.com, https://plausible.io
|
|
38
|
+
* - **CDNs**: https://unpkg.com, https://cdn.jsdelivr.net, https://cdnjs.cloudflare.com
|
|
39
|
+
* - **Social**: https://www.facebook.com, https://platform.twitter.com
|
|
40
|
+
* - **APIs**: https://api.example.com (backend API domains)
|
|
41
|
+
*
|
|
42
|
+
* Performance impact:
|
|
43
|
+
* - DNS resolution: typically 20-120ms per domain
|
|
44
|
+
* - Mobile networks: DNS can take 200-500ms (critical optimization)
|
|
45
|
+
* - First request: DNS + TCP + TLS handshake (300-1000ms total)
|
|
46
|
+
* - With DNS prefetch: Only TCP + TLS (100-400ms total)
|
|
47
|
+
*
|
|
48
|
+
* Best practices:
|
|
49
|
+
* - Only prefetch domains with high certainty of use (avoid wasting bandwidth)
|
|
50
|
+
* - Limit to 4-6 domains (too many = diminishing returns)
|
|
51
|
+
* - Include domains for critical resources (fonts, analytics, CDN)
|
|
52
|
+
* - Combine with preconnect for even faster connections (DNS + TCP + TLS)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const dnsPrefetch = [
|
|
57
|
+
* // Google Fonts (most common external resource)
|
|
58
|
+
* 'https://fonts.googleapis.com',
|
|
59
|
+
* 'https://fonts.gstatic.com',
|
|
60
|
+
* // Analytics
|
|
61
|
+
* 'https://www.google-analytics.com',
|
|
62
|
+
* // CDN
|
|
63
|
+
* 'https://cdn.example.com',
|
|
64
|
+
* // API backend
|
|
65
|
+
* 'https://api.example.com'
|
|
66
|
+
* ]
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @see specs/app/pages/meta/performance/dns-prefetch.schema.json
|
|
70
|
+
*/
|
|
71
|
+
export const DnsPrefetchSchema = Schema.Array(DnsPrefetchDomainSchema).annotations({
|
|
72
|
+
title: 'DNS Prefetch',
|
|
73
|
+
description: 'DNS prefetch hints for external domains',
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export type DnsPrefetchDomain = Schema.Schema.Type<typeof DnsPrefetchDomainSchema>
|
|
77
|
+
export type DnsPrefetch = Schema.Schema.Type<typeof DnsPrefetchSchema>
|
|
@@ -0,0 +1,203 @@
|
|
|
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 { Schema } from 'effect'
|
|
9
|
+
import { HexColorSchema } from '@/domain/models/app/common/definitions'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Favicon relationship type
|
|
13
|
+
*
|
|
14
|
+
* 4 types of favicons for different contexts:
|
|
15
|
+
* - icon: Standard browser favicon (most common)
|
|
16
|
+
* - apple-touch-icon: iOS home screen icon
|
|
17
|
+
* - manifest: PWA manifest file reference
|
|
18
|
+
* - mask-icon: Safari pinned tab icon (monochrome SVG)
|
|
19
|
+
*/
|
|
20
|
+
export const FaviconRelSchema = Schema.Literal(
|
|
21
|
+
'icon',
|
|
22
|
+
'apple-touch-icon',
|
|
23
|
+
'manifest',
|
|
24
|
+
'mask-icon'
|
|
25
|
+
).annotations({
|
|
26
|
+
description: 'Favicon relationship type',
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Favicon item in a multi-device favicon set
|
|
31
|
+
*
|
|
32
|
+
* Defines a single favicon for a specific device or context.
|
|
33
|
+
*
|
|
34
|
+
* Required properties:
|
|
35
|
+
* - rel: Relationship type (icon, apple-touch-icon, manifest, mask-icon)
|
|
36
|
+
* - href: Path to the favicon file (relative, starts with ./)
|
|
37
|
+
*
|
|
38
|
+
* Optional properties:
|
|
39
|
+
* - type: MIME type (image/png, image/x-icon, image/svg+xml)
|
|
40
|
+
* - sizes: Icon dimensions (16x16, 32x32, 180x180, 192x192, 512x512)
|
|
41
|
+
* - color: Hex color for mask-icon (Safari pinned tab)
|
|
42
|
+
*
|
|
43
|
+
* Common favicon set:
|
|
44
|
+
* - 16x16: Browser tab (small)
|
|
45
|
+
* - 32x32: Browser tab (standard)
|
|
46
|
+
* - 180x180: Apple touch icon (iOS home screen)
|
|
47
|
+
* - 192x192: Android icon (home screen)
|
|
48
|
+
* - 512x512: PWA icon (splash screen)
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const browserIcon = {
|
|
53
|
+
* rel: 'icon',
|
|
54
|
+
* type: 'image/png',
|
|
55
|
+
* sizes: '32x32',
|
|
56
|
+
* href: './public/favicon/favicon-32x32.png'
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* const appleIcon = {
|
|
60
|
+
* rel: 'apple-touch-icon',
|
|
61
|
+
* sizes: '180x180',
|
|
62
|
+
* href: './public/favicon/apple-touch-icon.png'
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* const safariIcon = {
|
|
66
|
+
* rel: 'mask-icon',
|
|
67
|
+
* href: './public/favicon/safari-pinned-tab.svg',
|
|
68
|
+
* color: '#5BBAD5'
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* const manifestRef = {
|
|
72
|
+
* rel: 'manifest',
|
|
73
|
+
* href: './public/favicon/site.webmanifest'
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export const FaviconItemSchema = Schema.Struct({
|
|
78
|
+
rel: FaviconRelSchema,
|
|
79
|
+
type: Schema.optional(
|
|
80
|
+
Schema.String.pipe(
|
|
81
|
+
Schema.pattern(/^image\//, {
|
|
82
|
+
message: () => 'MIME type must start with image/ (e.g., image/png, image/x-icon)',
|
|
83
|
+
})
|
|
84
|
+
).annotations({
|
|
85
|
+
description: 'MIME type',
|
|
86
|
+
examples: ['image/png', 'image/x-icon', 'image/svg+xml'],
|
|
87
|
+
})
|
|
88
|
+
),
|
|
89
|
+
sizes: Schema.optional(
|
|
90
|
+
Schema.String.pipe(
|
|
91
|
+
Schema.pattern(/^[0-9]+x[0-9]+$/, {
|
|
92
|
+
message: () => 'Sizes must be in format WIDTHxHEIGHT (e.g., 16x16, 32x32, 180x180)',
|
|
93
|
+
})
|
|
94
|
+
).annotations({
|
|
95
|
+
description: 'Icon dimensions',
|
|
96
|
+
examples: ['16x16', '32x32', '180x180', '192x192'],
|
|
97
|
+
})
|
|
98
|
+
),
|
|
99
|
+
href: Schema.String.pipe(
|
|
100
|
+
Schema.pattern(/^\.\//, {
|
|
101
|
+
message: () => 'Favicon path must be relative starting with ./',
|
|
102
|
+
})
|
|
103
|
+
).annotations({
|
|
104
|
+
description: 'Path to the favicon file',
|
|
105
|
+
}),
|
|
106
|
+
color: Schema.optional(
|
|
107
|
+
HexColorSchema.annotations({
|
|
108
|
+
description: 'Color for mask-icon (Safari pinned tab)',
|
|
109
|
+
})
|
|
110
|
+
),
|
|
111
|
+
}).annotations({
|
|
112
|
+
description: 'Favicon item',
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Multiple favicon sizes and types for different devices
|
|
117
|
+
*
|
|
118
|
+
* Comprehensive favicon configuration for cross-device compatibility.
|
|
119
|
+
* Includes icons for browsers, iOS, Android, PWAs, and Safari pinned tabs.
|
|
120
|
+
*
|
|
121
|
+
* Recommended favicon set:
|
|
122
|
+
* 1. Browser tabs:
|
|
123
|
+
* - 16x16 (icon, image/png) - small display
|
|
124
|
+
* - 32x32 (icon, image/png) - standard display
|
|
125
|
+
*
|
|
126
|
+
* 2. iOS devices:
|
|
127
|
+
* - 180x180 (apple-touch-icon) - home screen icon
|
|
128
|
+
*
|
|
129
|
+
* 3. Android devices:
|
|
130
|
+
* - 192x192 (icon, image/png) - home screen icon
|
|
131
|
+
* - 512x512 (icon, image/png) - splash screen
|
|
132
|
+
*
|
|
133
|
+
* 4. Safari pinned tabs:
|
|
134
|
+
* - mask-icon (SVG) with color - monochrome pinned tab icon
|
|
135
|
+
*
|
|
136
|
+
* 5. PWA manifest:
|
|
137
|
+
* - manifest (site.webmanifest) - PWA configuration
|
|
138
|
+
*
|
|
139
|
+
* Browser support:
|
|
140
|
+
* - icon: All browsers
|
|
141
|
+
* - apple-touch-icon: Safari (iOS), Chrome (Android add to home screen)
|
|
142
|
+
* - mask-icon: Safari 9+ (macOS pinned tabs)
|
|
143
|
+
* - manifest: Chrome, Edge, Firefox, Safari (PWA support)
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const completeFaviconSet = [
|
|
148
|
+
* // Browser tabs
|
|
149
|
+
* {
|
|
150
|
+
* rel: 'icon',
|
|
151
|
+
* type: 'image/png',
|
|
152
|
+
* sizes: '16x16',
|
|
153
|
+
* href: './public/favicon/favicon-16x16.png'
|
|
154
|
+
* },
|
|
155
|
+
* {
|
|
156
|
+
* rel: 'icon',
|
|
157
|
+
* type: 'image/png',
|
|
158
|
+
* sizes: '32x32',
|
|
159
|
+
* href: './public/favicon/favicon-32x32.png'
|
|
160
|
+
* },
|
|
161
|
+
* // iOS home screen
|
|
162
|
+
* {
|
|
163
|
+
* rel: 'apple-touch-icon',
|
|
164
|
+
* sizes: '180x180',
|
|
165
|
+
* href: './public/favicon/apple-touch-icon.png'
|
|
166
|
+
* },
|
|
167
|
+
* // Android/PWA
|
|
168
|
+
* {
|
|
169
|
+
* rel: 'icon',
|
|
170
|
+
* type: 'image/png',
|
|
171
|
+
* sizes: '192x192',
|
|
172
|
+
* href: './public/favicon/android-chrome-192x192.png'
|
|
173
|
+
* },
|
|
174
|
+
* {
|
|
175
|
+
* rel: 'icon',
|
|
176
|
+
* type: 'image/png',
|
|
177
|
+
* sizes: '512x512',
|
|
178
|
+
* href: './public/favicon/android-chrome-512x512.png'
|
|
179
|
+
* },
|
|
180
|
+
* // Safari pinned tabs
|
|
181
|
+
* {
|
|
182
|
+
* rel: 'mask-icon',
|
|
183
|
+
* href: './public/favicon/safari-pinned-tab.svg',
|
|
184
|
+
* color: '#5BBAD5'
|
|
185
|
+
* },
|
|
186
|
+
* // PWA manifest
|
|
187
|
+
* {
|
|
188
|
+
* rel: 'manifest',
|
|
189
|
+
* href: './public/favicon/site.webmanifest'
|
|
190
|
+
* }
|
|
191
|
+
* ]
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @see specs/app/pages/meta/favicons/favicon-set.schema.json
|
|
195
|
+
*/
|
|
196
|
+
export const FaviconSetSchema = Schema.Array(FaviconItemSchema).annotations({
|
|
197
|
+
title: 'Favicon Set',
|
|
198
|
+
description: 'Multiple favicon sizes and types for different devices',
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
export type FaviconRel = Schema.Schema.Type<typeof FaviconRelSchema>
|
|
202
|
+
export type FaviconItem = Schema.Schema.Type<typeof FaviconItemSchema>
|
|
203
|
+
export type FaviconSet = Schema.Schema.Type<typeof FaviconSetSchema>
|
|
@@ -0,0 +1,50 @@
|
|
|
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 { Schema } from 'effect'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Default favicon path
|
|
12
|
+
*
|
|
13
|
+
* Simple string pointing to the default favicon file.
|
|
14
|
+
* Supports 3 formats: .ico (legacy), .png (modern), .svg (scalable).
|
|
15
|
+
*
|
|
16
|
+
* Pattern: Must be a relative path starting with ./ and ending with .ico, .png, or .svg
|
|
17
|
+
*
|
|
18
|
+
* Common locations:
|
|
19
|
+
* - ./public/favicon.ico (Next.js, React, standard)
|
|
20
|
+
* - ./favicon.png (root directory)
|
|
21
|
+
* - ./assets/favicon.svg (assets folder)
|
|
22
|
+
*
|
|
23
|
+
* Format recommendations:
|
|
24
|
+
* - .ico: Legacy support (IE11, old browsers), 16x16 or 32x32
|
|
25
|
+
* - .png: Modern standard, 32x32 or 192x192
|
|
26
|
+
* - .svg: Scalable, best quality, smallest file size
|
|
27
|
+
*
|
|
28
|
+
* Use this for simple favicon setup. For multi-device support with
|
|
29
|
+
* Apple touch icons, Android icons, etc., use FaviconSetSchema instead.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const icoFavicon = './public/favicon.ico'
|
|
34
|
+
* const pngFavicon = './favicon.png'
|
|
35
|
+
* const svgFavicon = './assets/favicon.svg'
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @see specs/app/pages/meta/favicons/favicon.schema.json
|
|
39
|
+
*/
|
|
40
|
+
export const FaviconSchema = Schema.String.pipe(
|
|
41
|
+
Schema.pattern(/^\.\/.+\.(ico|png|svg)$/, {
|
|
42
|
+
message: () =>
|
|
43
|
+
'Favicon must be a relative path starting with ./ and ending with .ico, .png, or .svg (e.g., ./public/favicon.ico)',
|
|
44
|
+
})
|
|
45
|
+
).annotations({
|
|
46
|
+
title: 'Favicon',
|
|
47
|
+
description: 'Default favicon path',
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
export type Favicon = Schema.Schema.Type<typeof FaviconSchema>
|
|
@@ -0,0 +1,73 @@
|
|
|
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 { Schema } from 'effect'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Size specification for favicon
|
|
12
|
+
*/
|
|
13
|
+
export const FaviconSizeItemSchema = Schema.Struct({
|
|
14
|
+
size: Schema.String.pipe(
|
|
15
|
+
Schema.pattern(/^[0-9]+x[0-9]+$/, {
|
|
16
|
+
message: () => 'Size must be in format WIDTHxHEIGHT (e.g., 16x16, 32x32)',
|
|
17
|
+
})
|
|
18
|
+
).annotations({
|
|
19
|
+
description: 'Icon dimensions (e.g., 32x32, 16x16)',
|
|
20
|
+
}),
|
|
21
|
+
href: Schema.String.annotations({
|
|
22
|
+
description: 'Path to the favicon file',
|
|
23
|
+
}),
|
|
24
|
+
}).annotations({
|
|
25
|
+
description: 'Favicon size specification',
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Helper configuration for favicons with named properties
|
|
30
|
+
*
|
|
31
|
+
* This is a convenience format that gets transformed into FaviconSet array.
|
|
32
|
+
* Provides a simpler API for common favicon configurations.
|
|
33
|
+
*
|
|
34
|
+
* Properties:
|
|
35
|
+
* - icon: Default favicon (usually SVG or ICO)
|
|
36
|
+
* - appleTouchIcon: iOS home screen icon
|
|
37
|
+
* - sizes: Array of size-specific PNG favicons
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const faviconsConfig = {
|
|
42
|
+
* icon: '/icon.svg',
|
|
43
|
+
* appleTouchIcon: '/apple-touch-icon.png',
|
|
44
|
+
* sizes: [
|
|
45
|
+
* { size: '32x32', href: '/favicon-32x32.png' },
|
|
46
|
+
* { size: '16x16', href: '/favicon-16x16.png' }
|
|
47
|
+
* ]
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export const FaviconsConfigSchema = Schema.Struct({
|
|
52
|
+
icon: Schema.optional(
|
|
53
|
+
Schema.String.annotations({
|
|
54
|
+
description: 'Default icon (SVG or ICO)',
|
|
55
|
+
})
|
|
56
|
+
),
|
|
57
|
+
appleTouchIcon: Schema.optional(
|
|
58
|
+
Schema.String.annotations({
|
|
59
|
+
description: 'iOS home screen icon',
|
|
60
|
+
})
|
|
61
|
+
),
|
|
62
|
+
sizes: Schema.optional(
|
|
63
|
+
Schema.Array(FaviconSizeItemSchema).annotations({
|
|
64
|
+
description: 'Size-specific favicons',
|
|
65
|
+
})
|
|
66
|
+
),
|
|
67
|
+
}).annotations({
|
|
68
|
+
title: 'Favicons Configuration',
|
|
69
|
+
description: 'Helper configuration for favicons with named properties',
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
export type FaviconSizeItem = Schema.Schema.Type<typeof FaviconSizeItemSchema>
|
|
73
|
+
export type FaviconsConfig = Schema.Schema.Type<typeof FaviconsConfigSchema>
|
|
@@ -0,0 +1,278 @@
|
|
|
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 { Schema } from 'effect'
|
|
9
|
+
import { AnalyticsSchema } from './analytics'
|
|
10
|
+
import { CustomElementsSchema } from './custom-elements'
|
|
11
|
+
import { DnsPrefetchSchema } from './dns-prefetch'
|
|
12
|
+
import { FaviconSchema } from './favicon'
|
|
13
|
+
import { FaviconSetSchema } from './favicon-set'
|
|
14
|
+
import { FaviconsConfigSchema } from './favicons-config'
|
|
15
|
+
import { OpenGraphSchema } from './open-graph'
|
|
16
|
+
import { PreloadSchema } from './preload'
|
|
17
|
+
import { TwitterCardSchema } from './twitter-card'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Language code format
|
|
21
|
+
*
|
|
22
|
+
* ISO 639-1 language code with optional ISO 3166-1 country code.
|
|
23
|
+
* - Pattern: ^[a-z]{2}(-[A-Z]{2})?$ (2 lowercase letters, optional hyphen + 2 uppercase)
|
|
24
|
+
* - Examples: en, en-US, fr, fr-FR, es-ES, de, de-DE, ja, ja-JP
|
|
25
|
+
* - Used in <html lang="..."> attribute
|
|
26
|
+
*/
|
|
27
|
+
export const LanguageCodeSchema = Schema.String.pipe(
|
|
28
|
+
Schema.pattern(/^[a-z]{2}(-[A-Z]{2})?$/, {
|
|
29
|
+
message: () =>
|
|
30
|
+
'Language code must be ISO 639-1 format with optional country (e.g., en, en-US, fr-FR, es-ES)',
|
|
31
|
+
})
|
|
32
|
+
).annotations({
|
|
33
|
+
description: 'Page language code (ISO 639-1 with optional country)',
|
|
34
|
+
examples: ['en-US', 'fr-FR', 'es-ES', 'de-DE'],
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Comprehensive page metadata
|
|
39
|
+
*
|
|
40
|
+
* Master orchestrator schema that combines all meta categories into a single configuration.
|
|
41
|
+
* Provides comprehensive SEO, social media, structured data, performance, and analytics
|
|
42
|
+
* capabilities for optimal web presence.
|
|
43
|
+
*
|
|
44
|
+
* Required properties:
|
|
45
|
+
* - title: Page title for browser tab and SEO (max 60 chars)
|
|
46
|
+
* - description: Page description for SEO and social sharing (max 160 chars)
|
|
47
|
+
*
|
|
48
|
+
* Semi-optional properties:
|
|
49
|
+
* - lang: Page language code (e.g., "en-US", "fr-FR"). Optional to allow auto-detection
|
|
50
|
+
*
|
|
51
|
+
* Optional SEO properties:
|
|
52
|
+
* - keywords: Comma-separated keywords (limited SEO impact, mostly legacy)
|
|
53
|
+
* - author: Page author or organization name
|
|
54
|
+
* - canonical: Canonical URL to prevent duplicate content issues
|
|
55
|
+
*
|
|
56
|
+
* Optional resource properties:
|
|
57
|
+
* - favicon: Simple single favicon path (e.g., "./favicon.ico")
|
|
58
|
+
* - favicons: Complete favicon set for multi-device support
|
|
59
|
+
* - stylesheet: Path to main stylesheet (e.g., "./output.css")
|
|
60
|
+
* - googleFonts: Google Fonts API URL
|
|
61
|
+
* - socialImage: Default image for social sharing (fallback)
|
|
62
|
+
*
|
|
63
|
+
* Optional social media properties:
|
|
64
|
+
* - openGraph: Open Graph metadata for Facebook/LinkedIn
|
|
65
|
+
* - twitter: Twitter Card metadata for Twitter/X
|
|
66
|
+
*
|
|
67
|
+
* Optional structured data:
|
|
68
|
+
* - schema: Schema.org structured data for rich results
|
|
69
|
+
*
|
|
70
|
+
* Optional performance:
|
|
71
|
+
* - preload: Resource preloading for faster page load
|
|
72
|
+
* - dnsPrefetch: DNS prefetch hints for external domains
|
|
73
|
+
*
|
|
74
|
+
* Optional analytics:
|
|
75
|
+
* - analytics: Analytics provider configuration (Google, Plausible, etc.)
|
|
76
|
+
*
|
|
77
|
+
* Optional custom:
|
|
78
|
+
* - customElements: Arbitrary HTML elements for <head> (escape hatch)
|
|
79
|
+
*
|
|
80
|
+
* Metadata categories and their purposes:
|
|
81
|
+
* 1. **SEO basics**: title, description, keywords, canonical, author
|
|
82
|
+
* 2. **Branding**: favicon/favicons, stylesheet, socialImage
|
|
83
|
+
* 3. **Social media**: openGraph (Facebook/LinkedIn), twitter (Twitter/X)
|
|
84
|
+
* 4. **Rich results**: schema (Schema.org structured data)
|
|
85
|
+
* 5. **Performance**: preload (critical resources), dnsPrefetch (external domains)
|
|
86
|
+
* 6. **Analytics**: analytics (tracking providers)
|
|
87
|
+
* 7. **Custom**: customElements (escape hatch for special cases)
|
|
88
|
+
*
|
|
89
|
+
* Common page patterns:
|
|
90
|
+
* - **Homepage**: lang + title + description + openGraph + twitter + schema (organization) + analytics
|
|
91
|
+
* - **Blog post**: + schema (article + breadcrumb + person) + canonical
|
|
92
|
+
* - **Product page**: + schema (product + breadcrumb) + preload (hero image)
|
|
93
|
+
* - **FAQ page**: + schema (faqPage + breadcrumb)
|
|
94
|
+
* - **Event page**: + schema (educationEvent + breadcrumb)
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const meta = {
|
|
99
|
+
* lang: "en-US",
|
|
100
|
+
* title: "Complete Page Metadata Example",
|
|
101
|
+
* description: "Comprehensive metadata with SEO, social, structured data, performance, and analytics.",
|
|
102
|
+
* keywords: "metadata, seo, social media, structured data",
|
|
103
|
+
* canonical: "https://example.com/complete",
|
|
104
|
+
* favicon: "./favicon.ico",
|
|
105
|
+
* stylesheet: "./output.css",
|
|
106
|
+
* openGraph: {
|
|
107
|
+
* title: "Complete Page Metadata Example",
|
|
108
|
+
* description: "Comprehensive metadata...",
|
|
109
|
+
* type: "website",
|
|
110
|
+
* url: "https://example.com/complete",
|
|
111
|
+
* image: "https://example.com/og-image.jpg"
|
|
112
|
+
* },
|
|
113
|
+
* twitter: {
|
|
114
|
+
* card: "summary_large_image",
|
|
115
|
+
* title: "Complete Page Metadata Example",
|
|
116
|
+
* image: "https://example.com/twitter-image.jpg"
|
|
117
|
+
* },
|
|
118
|
+
* schema: {
|
|
119
|
+
* organization: {
|
|
120
|
+
* "@context": "https://schema.org",
|
|
121
|
+
* "@type": "Organization",
|
|
122
|
+
* name: "Acme Inc"
|
|
123
|
+
* }
|
|
124
|
+
* },
|
|
125
|
+
* dnsPrefetch: ["https://fonts.googleapis.com"],
|
|
126
|
+
* analytics: {
|
|
127
|
+
* providers: [
|
|
128
|
+
* {
|
|
129
|
+
* name: "google",
|
|
130
|
+
* enabled: true,
|
|
131
|
+
* config: { trackingId: "G-XXXXXXXXXX" }
|
|
132
|
+
* }
|
|
133
|
+
* ]
|
|
134
|
+
* }
|
|
135
|
+
* }
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @see specs/app/pages/meta/meta.schema.json
|
|
139
|
+
*/
|
|
140
|
+
export const MetaSchema = Schema.Struct({
|
|
141
|
+
lang: Schema.optional(
|
|
142
|
+
LanguageCodeSchema.annotations({
|
|
143
|
+
description: 'Page language code (optional - uses auto-detection if not specified)',
|
|
144
|
+
})
|
|
145
|
+
),
|
|
146
|
+
title: Schema.String.pipe(Schema.maxLength(60)).annotations({
|
|
147
|
+
description: 'Page title for browser tab and SEO (max 60 characters for optimal display)',
|
|
148
|
+
}),
|
|
149
|
+
description: Schema.optional(
|
|
150
|
+
Schema.String.pipe(Schema.maxLength(160)).annotations({
|
|
151
|
+
description: 'Page description for SEO and social sharing (max 160 characters)',
|
|
152
|
+
})
|
|
153
|
+
),
|
|
154
|
+
keywords: Schema.optional(
|
|
155
|
+
Schema.String.annotations({
|
|
156
|
+
description: 'Comma-separated keywords for SEO',
|
|
157
|
+
})
|
|
158
|
+
),
|
|
159
|
+
author: Schema.optional(
|
|
160
|
+
Schema.String.annotations({
|
|
161
|
+
description: 'Page author or organization name',
|
|
162
|
+
})
|
|
163
|
+
),
|
|
164
|
+
canonical: Schema.optional(
|
|
165
|
+
Schema.String.annotations({
|
|
166
|
+
description: 'Canonical URL to prevent duplicate content issues',
|
|
167
|
+
format: 'uri',
|
|
168
|
+
})
|
|
169
|
+
),
|
|
170
|
+
robots: Schema.optional(
|
|
171
|
+
Schema.String.annotations({
|
|
172
|
+
description: 'Robot directives (e.g., noindex, nofollow, noindex, nofollow)',
|
|
173
|
+
})
|
|
174
|
+
),
|
|
175
|
+
noindex: Schema.optional(
|
|
176
|
+
Schema.Boolean.annotations({
|
|
177
|
+
description: 'Prevent indexing by search engines (shorthand for robots: noindex)',
|
|
178
|
+
})
|
|
179
|
+
),
|
|
180
|
+
priority: Schema.optional(
|
|
181
|
+
Schema.Number.pipe(Schema.between(0, 1)).annotations({
|
|
182
|
+
description: 'Sitemap priority (0.0 to 1.0) for search engine crawling hints',
|
|
183
|
+
})
|
|
184
|
+
),
|
|
185
|
+
changefreq: Schema.optional(
|
|
186
|
+
Schema.Literal('always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never').annotations(
|
|
187
|
+
{
|
|
188
|
+
description: 'Sitemap change frequency hint for search engines',
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
),
|
|
192
|
+
favicon: Schema.optional(FaviconSchema),
|
|
193
|
+
favicons: Schema.optional(Schema.Union(FaviconSetSchema, FaviconsConfigSchema)),
|
|
194
|
+
stylesheet: Schema.optional(
|
|
195
|
+
Schema.String.annotations({
|
|
196
|
+
description: 'Path to the main stylesheet',
|
|
197
|
+
})
|
|
198
|
+
),
|
|
199
|
+
googleFonts: Schema.optional(
|
|
200
|
+
Schema.String.annotations({
|
|
201
|
+
description: 'Google Fonts URL',
|
|
202
|
+
format: 'uri',
|
|
203
|
+
})
|
|
204
|
+
),
|
|
205
|
+
socialImage: Schema.optional(
|
|
206
|
+
Schema.String.annotations({
|
|
207
|
+
description: 'Default image for social media sharing',
|
|
208
|
+
format: 'uri',
|
|
209
|
+
})
|
|
210
|
+
),
|
|
211
|
+
openGraph: Schema.optional(OpenGraphSchema),
|
|
212
|
+
twitter: Schema.optional(TwitterCardSchema),
|
|
213
|
+
schema: Schema.optional(
|
|
214
|
+
Schema.Unknown.annotations({
|
|
215
|
+
description:
|
|
216
|
+
'Schema.org structured data - accepts orchestrator format (organization, faqPage, etc.) or direct Schema.org object (@context, @type, ...)',
|
|
217
|
+
})
|
|
218
|
+
),
|
|
219
|
+
preload: Schema.optional(PreloadSchema),
|
|
220
|
+
dnsPrefetch: Schema.optional(DnsPrefetchSchema),
|
|
221
|
+
analytics: Schema.optional(
|
|
222
|
+
Schema.Union(Schema.Record({ key: Schema.String, value: Schema.Unknown }), AnalyticsSchema)
|
|
223
|
+
),
|
|
224
|
+
customElements: Schema.optional(CustomElementsSchema),
|
|
225
|
+
viewport: Schema.optional(
|
|
226
|
+
Schema.String.annotations({
|
|
227
|
+
description:
|
|
228
|
+
'Viewport meta tag content (e.g., "width=device-width, initial-scale=1.0") for responsive design',
|
|
229
|
+
})
|
|
230
|
+
),
|
|
231
|
+
// Aliases for test compatibility
|
|
232
|
+
twitterCard: Schema.optional(TwitterCardSchema),
|
|
233
|
+
structuredData: Schema.optional(Schema.Unknown),
|
|
234
|
+
'og:site_name': Schema.optional(
|
|
235
|
+
Schema.String.annotations({
|
|
236
|
+
description: 'OpenGraph site name (shorthand for openGraph.siteName)',
|
|
237
|
+
})
|
|
238
|
+
),
|
|
239
|
+
// Internationalization for metadata
|
|
240
|
+
i18n: Schema.optional(
|
|
241
|
+
Schema.Record({
|
|
242
|
+
key: LanguageCodeSchema,
|
|
243
|
+
value: Schema.Struct({
|
|
244
|
+
title: Schema.optional(
|
|
245
|
+
Schema.String.pipe(Schema.maxLength(60)).annotations({
|
|
246
|
+
description: 'Translated page title (max 60 characters)',
|
|
247
|
+
})
|
|
248
|
+
),
|
|
249
|
+
description: Schema.optional(
|
|
250
|
+
Schema.String.pipe(Schema.maxLength(160)).annotations({
|
|
251
|
+
description: 'Translated page description (max 160 characters)',
|
|
252
|
+
})
|
|
253
|
+
),
|
|
254
|
+
}),
|
|
255
|
+
}).annotations({
|
|
256
|
+
description: 'Localized metadata translations per language',
|
|
257
|
+
})
|
|
258
|
+
),
|
|
259
|
+
}).annotations({
|
|
260
|
+
title: 'Page Metadata',
|
|
261
|
+
description:
|
|
262
|
+
'Comprehensive page metadata including SEO, social media, structured data, performance, and analytics',
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
export type LanguageCode = Schema.Schema.Type<typeof LanguageCodeSchema>
|
|
266
|
+
export type Meta = Schema.Schema.Type<typeof MetaSchema>
|
|
267
|
+
|
|
268
|
+
// Re-export all meta schemas for convenience
|
|
269
|
+
export * from './favicon'
|
|
270
|
+
export * from './favicon-set'
|
|
271
|
+
export * from './favicons-config'
|
|
272
|
+
export * from './open-graph'
|
|
273
|
+
export * from './twitter-card'
|
|
274
|
+
export * from './structured-data'
|
|
275
|
+
export * from './preload'
|
|
276
|
+
export * from './dns-prefetch'
|
|
277
|
+
export * from './analytics'
|
|
278
|
+
export * from './custom-elements'
|