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,115 @@
|
|
|
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
|
+
* Spacing Configuration
|
|
12
|
+
*
|
|
13
|
+
* Spacing design tokens for consistent layout. Supports both Tailwind utility
|
|
14
|
+
* classes (py-16, px-4) and raw CSS values (4rem, 16px, 1.5em).
|
|
15
|
+
*
|
|
16
|
+
* **Behavior Specifications**:
|
|
17
|
+
* - Validates Tailwind spacing utilities (py-16, px-4, gap-6, etc.)
|
|
18
|
+
* - Validates responsive spacing with Tailwind breakpoints (py-16 sm:py-20)
|
|
19
|
+
* - Validates centering and width constraints (max-w-7xl mx-auto px-4)
|
|
20
|
+
* - Validates consistent spacing scale (gap-small, gap, gap-large)
|
|
21
|
+
* - Validates custom CSS spacing values (2rem, 16px, 1.5em)
|
|
22
|
+
* - Supports hierarchical content width constraints (container, container-small, container-xsmall)
|
|
23
|
+
*
|
|
24
|
+
* **Token Categories**:
|
|
25
|
+
* - Section spacing: Vertical rhythm for page sections (py-16 sm:py-20)
|
|
26
|
+
* - Container spacing: Width constraints and centering (max-w-7xl mx-auto px-4)
|
|
27
|
+
* - Gap spacing: Space between flex/grid items (gap-6)
|
|
28
|
+
* - Padding spacing: Internal component spacing (p-6, p-4, p-8)
|
|
29
|
+
* - Margin spacing: External component spacing (m-6, m-4, m-8)
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // Complete spacing system
|
|
34
|
+
* const spacing = {
|
|
35
|
+
* section: 'py-16 sm:py-20',
|
|
36
|
+
* container: 'max-w-7xl mx-auto px-4',
|
|
37
|
+
* 'container-small': 'max-w-4xl mx-auto px-4',
|
|
38
|
+
* 'container-xsmall': 'max-w-2xl mx-auto px-4',
|
|
39
|
+
* gap: 'gap-6',
|
|
40
|
+
* 'gap-small': 'gap-4',
|
|
41
|
+
* 'gap-large': 'gap-8',
|
|
42
|
+
* padding: 'p-6',
|
|
43
|
+
* 'padding-small': 'p-4',
|
|
44
|
+
* 'padding-large': 'p-8',
|
|
45
|
+
* margin: 'm-6',
|
|
46
|
+
* 'margin-small': 'm-4',
|
|
47
|
+
* 'margin-large': 'm-8'
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @see specs/app/theme/spacing/spacing.schema.json
|
|
52
|
+
*/
|
|
53
|
+
export const SpacingConfigSchema = Schema.Record({
|
|
54
|
+
key: Schema.String.pipe(
|
|
55
|
+
Schema.pattern(/^[a-z]+(-[a-z]+)*$/, {
|
|
56
|
+
message: () => 'Spacing key must use kebab-case (e.g., container-small, not containerSmall)',
|
|
57
|
+
}),
|
|
58
|
+
Schema.annotations({
|
|
59
|
+
title: 'Spacing Token Name',
|
|
60
|
+
description: 'Kebab-case name for spacing token (e.g., container-small, not containerSmall)',
|
|
61
|
+
examples: [
|
|
62
|
+
'section',
|
|
63
|
+
'container',
|
|
64
|
+
'container-small',
|
|
65
|
+
'gap',
|
|
66
|
+
'gap-small',
|
|
67
|
+
'padding',
|
|
68
|
+
'margin',
|
|
69
|
+
],
|
|
70
|
+
})
|
|
71
|
+
),
|
|
72
|
+
value: Schema.String.pipe(
|
|
73
|
+
Schema.annotations({
|
|
74
|
+
title: 'Spacing Value',
|
|
75
|
+
description:
|
|
76
|
+
'Spacing value as Tailwind utility classes or CSS values (rem, px, em, %). Supports responsive variants (sm:, md:, lg:) and multiple classes.',
|
|
77
|
+
examples: [
|
|
78
|
+
'py-16',
|
|
79
|
+
'px-4',
|
|
80
|
+
'py-16 sm:py-20',
|
|
81
|
+
'max-w-7xl mx-auto px-4',
|
|
82
|
+
'gap-6',
|
|
83
|
+
'p-6',
|
|
84
|
+
'm-6',
|
|
85
|
+
'4rem',
|
|
86
|
+
'16px',
|
|
87
|
+
'1.5em',
|
|
88
|
+
],
|
|
89
|
+
})
|
|
90
|
+
),
|
|
91
|
+
}).pipe(
|
|
92
|
+
Schema.annotations({
|
|
93
|
+
title: 'Spacing Configuration',
|
|
94
|
+
description: 'Spacing design tokens for consistent layout',
|
|
95
|
+
examples: [
|
|
96
|
+
{
|
|
97
|
+
section: 'py-16 sm:py-20',
|
|
98
|
+
container: 'max-w-7xl mx-auto px-4',
|
|
99
|
+
'container-small': 'max-w-4xl mx-auto px-4',
|
|
100
|
+
'container-xsmall': 'max-w-2xl mx-auto px-4',
|
|
101
|
+
gap: 'gap-6',
|
|
102
|
+
'gap-small': 'gap-4',
|
|
103
|
+
'gap-large': 'gap-8',
|
|
104
|
+
padding: 'p-6',
|
|
105
|
+
'padding-small': 'p-4',
|
|
106
|
+
'padding-large': 'p-8',
|
|
107
|
+
margin: 'm-6',
|
|
108
|
+
'margin-small': 'm-4',
|
|
109
|
+
'margin-large': 'm-8',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
})
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
export type SpacingConfig = Schema.Schema.Type<typeof SpacingConfigSchema>
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { AnimationsConfigSchema } from './theme/animations'
|
|
10
|
+
import { BorderRadiusConfigSchema } from './theme/border-radius'
|
|
11
|
+
import { BreakpointsConfigSchema } from './theme/breakpoints'
|
|
12
|
+
import { ColorsConfigSchema } from './theme/colors'
|
|
13
|
+
import { FontsConfigSchema } from './theme/fonts'
|
|
14
|
+
import { ShadowsConfigSchema } from './theme/shadows'
|
|
15
|
+
import { SpacingConfigSchema } from './theme/spacing'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Theme configuration orchestrating all design token categories
|
|
19
|
+
*
|
|
20
|
+
* Provides a unified design system by composing:
|
|
21
|
+
* - colors: Visual identity and branding
|
|
22
|
+
* - fonts: Typography system
|
|
23
|
+
* - spacing: Layout rhythm and whitespace
|
|
24
|
+
* - animations: Motion design library
|
|
25
|
+
* - breakpoints: Responsive system thresholds
|
|
26
|
+
* - shadows: Elevation and depth
|
|
27
|
+
* - borderRadius: Corner styling
|
|
28
|
+
*
|
|
29
|
+
* All properties are optional, allowing minimal themes (colors-only)
|
|
30
|
+
* or comprehensive design systems (all 7 categories).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const minimalTheme = {
|
|
35
|
+
* colors: { primary: '#007bff' }
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* const completeTheme = {
|
|
39
|
+
* colors: { primary: '#007bff' },
|
|
40
|
+
* fonts: { body: { family: 'Inter' } },
|
|
41
|
+
* spacing: { section: '4rem' },
|
|
42
|
+
* animations: { fadeIn: true },
|
|
43
|
+
* breakpoints: { md: '768px' },
|
|
44
|
+
* shadows: { md: '0 4px 6px -1px rgb(0 0 0 / 0.1)' },
|
|
45
|
+
* borderRadius: { md: '0.375rem' }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @see specs/app/theme/theme.schema.json
|
|
50
|
+
*/
|
|
51
|
+
export const ThemeSchema = Schema.Struct({
|
|
52
|
+
colors: Schema.optional(ColorsConfigSchema),
|
|
53
|
+
fonts: Schema.optional(FontsConfigSchema),
|
|
54
|
+
spacing: Schema.optional(SpacingConfigSchema),
|
|
55
|
+
animations: Schema.optional(AnimationsConfigSchema),
|
|
56
|
+
breakpoints: Schema.optional(BreakpointsConfigSchema),
|
|
57
|
+
shadows: Schema.optional(ShadowsConfigSchema),
|
|
58
|
+
borderRadius: Schema.optional(BorderRadiusConfigSchema),
|
|
59
|
+
}).pipe(
|
|
60
|
+
Schema.annotations({
|
|
61
|
+
title: 'Theme Configuration',
|
|
62
|
+
description: 'Design tokens for colors, typography, spacing, and animations',
|
|
63
|
+
})
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
export type Theme = Schema.Schema.Type<typeof ThemeSchema>
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
* VersionSchema defines validation rules for application versions.
|
|
12
|
+
*
|
|
13
|
+
* Application versions must follow Semantic Versioning (SemVer) 2.0.0 specification:
|
|
14
|
+
* - Format: MAJOR.MINOR.PATCH (e.g., 1.0.0)
|
|
15
|
+
* - Each component must be a non-negative integer without leading zeros
|
|
16
|
+
* - Optional pre-release identifiers after hyphen (e.g., 1.0.0-alpha, 1.0.0-beta.1)
|
|
17
|
+
* - Optional build metadata after plus sign (e.g., 1.0.0+build.123)
|
|
18
|
+
*
|
|
19
|
+
* Valid version format:
|
|
20
|
+
* - MAJOR version: Incremented for incompatible API changes
|
|
21
|
+
* - MINOR version: Incremented for backwards-compatible functionality additions
|
|
22
|
+
* - PATCH version: Incremented for backwards-compatible bug fixes
|
|
23
|
+
* - Pre-release: Hyphen followed by dot-separated identifiers (alphanumeric + hyphen)
|
|
24
|
+
* - Build metadata: Plus sign followed by dot-separated identifiers (alphanumeric + hyphen)
|
|
25
|
+
*
|
|
26
|
+
* @see https://semver.org/
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Valid versions
|
|
31
|
+
* const version1 = '1.0.0'
|
|
32
|
+
* const version2 = '0.0.1'
|
|
33
|
+
* const version3 = '1.2.3'
|
|
34
|
+
* const version4 = '1.0.0-alpha'
|
|
35
|
+
* const version5 = '1.0.0-beta.1'
|
|
36
|
+
* const version6 = '2.0.0-rc.1'
|
|
37
|
+
* const version7 = '1.0.0+build.123'
|
|
38
|
+
* const version8 = '1.0.0-alpha+001'
|
|
39
|
+
*
|
|
40
|
+
* // Validate version
|
|
41
|
+
* const validated = Schema.decodeUnknownSync(VersionSchema)(version1)
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const VersionSchema = Schema.String.pipe(
|
|
45
|
+
Schema.minLength(5, { message: () => 'Version must not be empty (minimum format: 0.0.0)' }),
|
|
46
|
+
Schema.pattern(
|
|
47
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/,
|
|
48
|
+
{
|
|
49
|
+
message: () =>
|
|
50
|
+
'Version must follow Semantic Versioning format (MAJOR.MINOR.PATCH, e.g., 1.0.0). No leading zeros allowed. Optional pre-release (-alpha) and build metadata (+build.123) are supported.',
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
Schema.annotations({
|
|
54
|
+
title: 'Application Version',
|
|
55
|
+
description:
|
|
56
|
+
'The version of the application following Semantic Versioning (SemVer) 2.0.0 specification',
|
|
57
|
+
examples: [
|
|
58
|
+
'1.0.0',
|
|
59
|
+
'0.0.1',
|
|
60
|
+
'1.2.3',
|
|
61
|
+
'1.0.0-alpha',
|
|
62
|
+
'1.0.0-beta.1',
|
|
63
|
+
'2.0.0-rc.1',
|
|
64
|
+
'1.0.0+build.123',
|
|
65
|
+
'1.0.0-alpha+001',
|
|
66
|
+
],
|
|
67
|
+
})
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* TypeScript type inferred from VersionSchema.
|
|
72
|
+
*
|
|
73
|
+
* Use this type for type-safe access to validated version strings.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const version: Version = '1.0.0'
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export type Version = Schema.Schema.Type<typeof VersionSchema>
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Encoded type of VersionSchema (what goes in).
|
|
84
|
+
*
|
|
85
|
+
* In this case, it's the same as Version since we don't use transformations.
|
|
86
|
+
*/
|
|
87
|
+
export type VersionEncoded = Schema.Schema.Encoded<typeof VersionSchema>
|
|
@@ -0,0 +1,91 @@
|
|
|
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
|
+
* Record Comment Domain Model
|
|
12
|
+
*
|
|
13
|
+
* Represents a comment on a table record with:
|
|
14
|
+
* - Content validation (non-empty, max 10,000 chars)
|
|
15
|
+
* - Support for @mentions stored as @[user_id]
|
|
16
|
+
* - Auto-injected user_id from session
|
|
17
|
+
* - Timestamps for audit trail
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Comment ID - UUID string
|
|
22
|
+
*/
|
|
23
|
+
export const CommentIdSchema = Schema.String.pipe(
|
|
24
|
+
Schema.pattern(/^[a-f0-9-]+$/, {
|
|
25
|
+
message: () => 'Comment ID must be a valid UUID',
|
|
26
|
+
}),
|
|
27
|
+
Schema.brand('CommentId')
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
export type CommentId = typeof CommentIdSchema.Type
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Comment Content - non-empty, max 10,000 characters
|
|
34
|
+
* Supports @mentions as @[user_id] format
|
|
35
|
+
*/
|
|
36
|
+
export const CommentContentSchema = Schema.String.pipe(
|
|
37
|
+
Schema.minLength(1, { message: () => 'Comment content cannot be empty' }),
|
|
38
|
+
Schema.maxLength(10_000, {
|
|
39
|
+
message: () => 'Comment content cannot exceed 10,000 characters',
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export type CommentContent = typeof CommentContentSchema.Type
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Record Comment Schema
|
|
47
|
+
*/
|
|
48
|
+
export const RecordCommentSchema = Schema.Struct({
|
|
49
|
+
id: CommentIdSchema,
|
|
50
|
+
recordId: Schema.String,
|
|
51
|
+
tableId: Schema.String,
|
|
52
|
+
userId: Schema.String,
|
|
53
|
+
content: CommentContentSchema,
|
|
54
|
+
createdAt: Schema.Date,
|
|
55
|
+
updatedAt: Schema.optionalWith(Schema.Date, { nullable: true }),
|
|
56
|
+
deletedAt: Schema.optionalWith(Schema.Date, { nullable: true }),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
export type RecordComment = typeof RecordCommentSchema.Type
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create Comment Input - content only (other fields auto-injected)
|
|
63
|
+
*/
|
|
64
|
+
export const CreateCommentInputSchema = Schema.Struct({
|
|
65
|
+
content: CommentContentSchema,
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
export type CreateCommentInput = typeof CreateCommentInputSchema.Type
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Comment with User Metadata (for API responses)
|
|
72
|
+
*/
|
|
73
|
+
export const CommentWithUserSchema = Schema.Struct({
|
|
74
|
+
id: CommentIdSchema,
|
|
75
|
+
recordId: Schema.String,
|
|
76
|
+
tableId: Schema.String,
|
|
77
|
+
userId: Schema.String,
|
|
78
|
+
content: CommentContentSchema,
|
|
79
|
+
createdAt: Schema.Date,
|
|
80
|
+
user: Schema.optionalWith(
|
|
81
|
+
Schema.Struct({
|
|
82
|
+
id: Schema.String,
|
|
83
|
+
name: Schema.String,
|
|
84
|
+
email: Schema.String,
|
|
85
|
+
image: Schema.optionalWith(Schema.String, { nullable: true }),
|
|
86
|
+
}),
|
|
87
|
+
{ nullable: true }
|
|
88
|
+
),
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
export type CommentWithUser = typeof CommentWithUserSchema.Type
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Content Parsing - Pure Functions
|
|
10
|
+
*
|
|
11
|
+
* Domain layer utilities for parsing schema content.
|
|
12
|
+
* These are pure functions with no side effects.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { load as parseYaml } from 'js-yaml'
|
|
16
|
+
import type { SchemaFormat } from './format-detection'
|
|
17
|
+
import type { AppEncoded } from '@/domain/models/app'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse JSON content to AppEncoded
|
|
21
|
+
*/
|
|
22
|
+
export const parseJsonContent = (content: string): AppEncoded => JSON.parse(content) as AppEncoded
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse YAML content to AppEncoded
|
|
26
|
+
*/
|
|
27
|
+
export const parseYamlContent = (content: string): AppEncoded => parseYaml(content) as AppEncoded
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parse schema content based on detected format
|
|
31
|
+
* Falls back to trying JSON first, then YAML if format is undefined
|
|
32
|
+
*/
|
|
33
|
+
export const parseSchemaContent = (
|
|
34
|
+
content: string,
|
|
35
|
+
format: SchemaFormat | undefined
|
|
36
|
+
): AppEncoded => {
|
|
37
|
+
if (format === 'json') {
|
|
38
|
+
return parseJsonContent(content)
|
|
39
|
+
}
|
|
40
|
+
if (format === 'yaml') {
|
|
41
|
+
return parseYamlContent(content)
|
|
42
|
+
}
|
|
43
|
+
// Last fallback: try JSON first, then YAML
|
|
44
|
+
try {
|
|
45
|
+
return parseJsonContent(content)
|
|
46
|
+
} catch {
|
|
47
|
+
return parseYamlContent(content)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Format Detection - Pure Functions
|
|
10
|
+
*
|
|
11
|
+
* Domain layer utilities for detecting schema file formats.
|
|
12
|
+
* These are pure functions with no side effects.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Supported schema formats */
|
|
16
|
+
export type SchemaFormat = 'json' | 'yaml'
|
|
17
|
+
|
|
18
|
+
/** Format detection result */
|
|
19
|
+
export type FormatDetectionResult = SchemaFormat | 'unsupported'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Detect file format from file extension
|
|
23
|
+
*/
|
|
24
|
+
export const detectFormat = (filePath: string): FormatDetectionResult => {
|
|
25
|
+
const lowerPath = filePath.toLowerCase()
|
|
26
|
+
if (lowerPath.endsWith('.json')) return 'json'
|
|
27
|
+
if (lowerPath.endsWith('.yaml') || lowerPath.endsWith('.yml')) return 'yaml'
|
|
28
|
+
return 'unsupported'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Extract file extension from path
|
|
33
|
+
*/
|
|
34
|
+
export const getFileExtension = (filePath: string): string => {
|
|
35
|
+
const match = filePath.match(/\.([^.]+)$/)
|
|
36
|
+
return match?.[1] ?? ''
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Detect format from Content-Type header
|
|
41
|
+
*/
|
|
42
|
+
export const detectFormatFromContentType = (contentType: string): SchemaFormat | undefined => {
|
|
43
|
+
if (contentType.includes('application/json')) return 'json'
|
|
44
|
+
if (contentType.includes('application/x-yaml') || contentType.includes('text/yaml')) return 'yaml'
|
|
45
|
+
return undefined
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Detect format from URL file extension
|
|
50
|
+
*/
|
|
51
|
+
export const detectFormatFromUrl = (url: string): SchemaFormat | undefined => {
|
|
52
|
+
const urlLower = url.toLowerCase()
|
|
53
|
+
if (urlLower.endsWith('.json')) return 'json'
|
|
54
|
+
if (urlLower.endsWith('.yaml') || urlLower.endsWith('.yml')) return 'yaml'
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Check if a string value looks like inline JSON
|
|
60
|
+
*/
|
|
61
|
+
export const isInlineJson = (value: string): boolean => value.trim().startsWith('{')
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if a string value is a URL
|
|
65
|
+
*/
|
|
66
|
+
export const isUrl = (value: string): boolean => {
|
|
67
|
+
const trimmed = value.trim()
|
|
68
|
+
return trimmed.startsWith('http://') || trimmed.startsWith('https://')
|
|
69
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export * from './format-detection'
|
|
9
|
+
export * from './content-parsing'
|
|
@@ -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
|
+
/**
|
|
9
|
+
* Route parameters extracted from a dynamic path
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const params = { slug: 'hello-world', id: '123' }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export type RouteParams = Readonly<Record<string, string>>
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Result of matching a URL against a route pattern
|
|
20
|
+
*/
|
|
21
|
+
export type RouteMatch = {
|
|
22
|
+
readonly matched: boolean
|
|
23
|
+
readonly params: RouteParams
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Converts a route pattern with dynamic segments into a regular expression
|
|
28
|
+
*
|
|
29
|
+
* Dynamic segments are defined with a colon prefix (e.g., :id, :slug)
|
|
30
|
+
*
|
|
31
|
+
* @param pattern - Route pattern (e.g., '/blog/:slug', '/products/:id')
|
|
32
|
+
* @returns Regular expression to match URLs and capture parameters
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const regex = patternToRegex('/blog/:slug')
|
|
37
|
+
* // Returns: /^\/blog\/([^/]+)$/
|
|
38
|
+
*
|
|
39
|
+
* const regex2 = patternToRegex('/users/:userId/posts/:postId')
|
|
40
|
+
* // Returns: /^\/users\/([^/]+)\/posts\/([^/]+)$/
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
function patternToRegex(pattern: string): Readonly<RegExp> {
|
|
44
|
+
// Escape forward slashes and convert :param to capture groups
|
|
45
|
+
const regexPattern = pattern
|
|
46
|
+
.split('/')
|
|
47
|
+
.map((segment) => {
|
|
48
|
+
if (segment.startsWith(':')) {
|
|
49
|
+
// Dynamic segment - capture any characters except forward slash
|
|
50
|
+
return '([^/]+)'
|
|
51
|
+
}
|
|
52
|
+
// Static segment - escape special regex characters
|
|
53
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
54
|
+
})
|
|
55
|
+
.join('/')
|
|
56
|
+
|
|
57
|
+
return new RegExp(`^${regexPattern}$`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Extracts parameter names from a route pattern
|
|
62
|
+
*
|
|
63
|
+
* @param pattern - Route pattern (e.g., '/blog/:slug')
|
|
64
|
+
* @returns Array of parameter names (e.g., ['slug'])
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const params = extractParamNames('/blog/:slug')
|
|
69
|
+
* // Returns: ['slug']
|
|
70
|
+
*
|
|
71
|
+
* const params2 = extractParamNames('/users/:userId/posts/:postId')
|
|
72
|
+
* // Returns: ['userId', 'postId']
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
function extractParamNames(pattern: string): readonly string[] {
|
|
76
|
+
return pattern
|
|
77
|
+
.split('/')
|
|
78
|
+
.filter((segment) => segment.startsWith(':'))
|
|
79
|
+
.map((segment) => segment.slice(1)) // Remove colon prefix
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Matches a URL path against a route pattern and extracts parameters
|
|
84
|
+
*
|
|
85
|
+
* Pure function with no side effects
|
|
86
|
+
*
|
|
87
|
+
* @param pattern - Route pattern with optional dynamic segments (e.g., '/blog/:slug')
|
|
88
|
+
* @param urlPath - Actual URL path to match (e.g., '/blog/hello-world')
|
|
89
|
+
* @returns Match result with extracted parameters
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // Static route
|
|
94
|
+
* matchRoute('/about', '/about')
|
|
95
|
+
* // Returns: { matched: true, params: {} }
|
|
96
|
+
*
|
|
97
|
+
* // Dynamic route with single parameter
|
|
98
|
+
* matchRoute('/blog/:slug', '/blog/hello-world')
|
|
99
|
+
* // Returns: { matched: true, params: { slug: 'hello-world' } }
|
|
100
|
+
*
|
|
101
|
+
* // Dynamic route with multiple parameters
|
|
102
|
+
* matchRoute('/users/:userId/posts/:postId', '/users/123/posts/456')
|
|
103
|
+
* // Returns: { matched: true, params: { userId: '123', postId: '456' } }
|
|
104
|
+
*
|
|
105
|
+
* // No match
|
|
106
|
+
* matchRoute('/blog/:slug', '/products/123')
|
|
107
|
+
* // Returns: { matched: false, params: {} }
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export function matchRoute(pattern: string, urlPath: string): RouteMatch {
|
|
111
|
+
// Static route - exact match
|
|
112
|
+
if (!pattern.includes(':')) {
|
|
113
|
+
return {
|
|
114
|
+
matched: pattern === urlPath,
|
|
115
|
+
params: {},
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Dynamic route - use regex matching
|
|
120
|
+
const regex = patternToRegex(pattern)
|
|
121
|
+
const match = urlPath.match(regex)
|
|
122
|
+
|
|
123
|
+
if (!match) {
|
|
124
|
+
return {
|
|
125
|
+
matched: false,
|
|
126
|
+
params: {},
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Extract parameter names and values
|
|
131
|
+
const paramNames = extractParamNames(pattern)
|
|
132
|
+
const paramValues = match.slice(1) // Remove full match, keep capture groups
|
|
133
|
+
|
|
134
|
+
// Use reduce to build params object functionally (no mutation)
|
|
135
|
+
const params = paramNames.reduce<Record<string, string>>((acc, name, i) => {
|
|
136
|
+
const value = paramValues[i]
|
|
137
|
+
if (name && value) {
|
|
138
|
+
return { ...acc, [name]: value }
|
|
139
|
+
}
|
|
140
|
+
return acc
|
|
141
|
+
}, {})
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
matched: true,
|
|
145
|
+
params,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Finds the first matching route from a list of patterns
|
|
151
|
+
*
|
|
152
|
+
* Pure function with no side effects
|
|
153
|
+
*
|
|
154
|
+
* @param patterns - Array of route patterns to try
|
|
155
|
+
* @param urlPath - URL path to match
|
|
156
|
+
* @returns Index of matched pattern and extracted parameters, or undefined if no match
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const patterns = ['/about', '/blog/:slug', '/products/:id']
|
|
161
|
+
* const result = findMatchingRoute(patterns, '/blog/hello-world')
|
|
162
|
+
* // Returns: { index: 1, params: { slug: 'hello-world' } }
|
|
163
|
+
*
|
|
164
|
+
* const result2 = findMatchingRoute(patterns, '/not-found')
|
|
165
|
+
* // Returns: undefined
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
export function findMatchingRoute(
|
|
169
|
+
patterns: readonly string[],
|
|
170
|
+
urlPath: string
|
|
171
|
+
): { readonly index: number; readonly params: RouteParams } | undefined {
|
|
172
|
+
// Use findIndex + map to avoid imperative loop
|
|
173
|
+
const matchResult = patterns
|
|
174
|
+
.map((pattern, index) => ({ pattern, index }))
|
|
175
|
+
.filter(({ pattern }) => pattern !== undefined && pattern !== '')
|
|
176
|
+
.find(({ pattern }) => matchRoute(pattern, urlPath).matched)
|
|
177
|
+
|
|
178
|
+
if (!matchResult) {
|
|
179
|
+
return undefined
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const match = matchRoute(matchResult.pattern, urlPath)
|
|
183
|
+
return { index: matchResult.index, params: match.params }
|
|
184
|
+
}
|