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.
Files changed (527) hide show
  1. package/CHANGELOG.md +3497 -0
  2. package/LICENSE.md +147 -0
  3. package/LICENSE_EE.md +297 -0
  4. package/README.md +321 -0
  5. package/drizzle/0000_melted_kabuki.sql +163 -0
  6. package/drizzle/meta/0000_snapshot.json +1216 -0
  7. package/drizzle/meta/_journal.json +13 -0
  8. package/package.json +167 -0
  9. package/schemas/0.0.1/app.openapi.json +70 -0
  10. package/schemas/0.0.1/app.schema.json +7961 -0
  11. package/schemas/0.0.2/app.openapi.json +80 -0
  12. package/schemas/0.0.2/app.schema.json +8829 -0
  13. package/schemas/development/app.openapi.json +70 -0
  14. package/schemas/development/app.schema.json +7456 -0
  15. package/src/application/errors/app-validation-error.ts +14 -0
  16. package/src/application/errors/static-generation-error.ts +16 -0
  17. package/src/application/metadata/favicon-transformer.ts +127 -0
  18. package/src/application/models/server.ts +27 -0
  19. package/src/application/ports/models/user-metadata.ts +36 -0
  20. package/src/application/ports/models/user-session.ts +34 -0
  21. package/src/application/ports/repositories/activity-log-repository.ts +68 -0
  22. package/src/application/ports/repositories/activity-repository.ts +49 -0
  23. package/src/application/ports/repositories/analytics-repository.ts +164 -0
  24. package/src/application/ports/repositories/auth-repository.ts +33 -0
  25. package/src/application/ports/repositories/batch-repository.ts +86 -0
  26. package/src/application/ports/repositories/comment-repository.ts +150 -0
  27. package/src/application/ports/repositories/index.ts +41 -0
  28. package/src/application/ports/repositories/table-repository.ts +139 -0
  29. package/src/application/ports/services/css-compiler.ts +55 -0
  30. package/src/application/ports/services/index.ts +16 -0
  31. package/src/application/ports/services/page-renderer.ts +79 -0
  32. package/src/application/ports/services/server-factory.ts +80 -0
  33. package/src/application/ports/services/static-site-generator.ts +82 -0
  34. package/src/application/use-cases/activity/programs.ts +66 -0
  35. package/src/application/use-cases/analytics/collect-page-view.ts +114 -0
  36. package/src/application/use-cases/analytics/purge-old-data.ts +40 -0
  37. package/src/application/use-cases/analytics/query-campaigns.ts +43 -0
  38. package/src/application/use-cases/analytics/query-devices.ts +36 -0
  39. package/src/application/use-cases/analytics/query-overview.ts +50 -0
  40. package/src/application/use-cases/analytics/query-pages.ts +40 -0
  41. package/src/application/use-cases/analytics/query-referrers.ts +43 -0
  42. package/src/application/use-cases/analytics/ua-parser.ts +89 -0
  43. package/src/application/use-cases/analytics/visitor-hash.ts +77 -0
  44. package/src/application/use-cases/auth/bootstrap-admin.ts +270 -0
  45. package/src/application/use-cases/list-activity-logs.ts +123 -0
  46. package/src/application/use-cases/server/generate-static-helpers.ts +374 -0
  47. package/src/application/use-cases/server/generate-static.ts +287 -0
  48. package/src/application/use-cases/server/start-server.ts +118 -0
  49. package/src/application/use-cases/server/startup-error-handler.ts +69 -0
  50. package/src/application/use-cases/server/static-content-generators.ts +182 -0
  51. package/src/application/use-cases/server/static-language-generators.ts +181 -0
  52. package/src/application/use-cases/server/static-url-rewriter.ts +237 -0
  53. package/src/application/use-cases/server/translation-replacer.ts +164 -0
  54. package/src/application/use-cases/tables/activity-programs.ts +93 -0
  55. package/src/application/use-cases/tables/batch-operations.ts +156 -0
  56. package/src/application/use-cases/tables/comment-programs.ts +436 -0
  57. package/src/application/use-cases/tables/permissions/permissions.ts +25 -0
  58. package/src/application/use-cases/tables/programs.ts +435 -0
  59. package/src/application/use-cases/tables/table-operations.ts +412 -0
  60. package/src/application/use-cases/tables/user-role.ts +52 -0
  61. package/src/application/use-cases/tables/utils/display-formatter.ts +471 -0
  62. package/src/application/use-cases/tables/utils/field-read-filter.ts +189 -0
  63. package/src/application/use-cases/tables/utils/list-helpers.ts +122 -0
  64. package/src/application/use-cases/tables/utils/record-transformer.ts +319 -0
  65. package/src/cli.ts +370 -0
  66. package/src/domain/errors/create-tagged-error.ts +36 -0
  67. package/src/domain/errors/index.ts +78 -0
  68. package/src/domain/models/api/analytics.ts +179 -0
  69. package/src/domain/models/api/auth.ts +231 -0
  70. package/src/domain/models/api/common.ts +60 -0
  71. package/src/domain/models/api/error.ts +89 -0
  72. package/src/domain/models/api/health.ts +38 -0
  73. package/src/domain/models/api/index.ts +42 -0
  74. package/src/domain/models/api/request.ts +132 -0
  75. package/src/domain/models/api/tables.ts +444 -0
  76. package/src/domain/models/app/analytics/index.ts +129 -0
  77. package/src/domain/models/app/auth/config.ts +116 -0
  78. package/src/domain/models/app/auth/index.ts +230 -0
  79. package/src/domain/models/app/auth/methods/email-and-password.ts +67 -0
  80. package/src/domain/models/app/auth/methods/index.ts +11 -0
  81. package/src/domain/models/app/auth/methods/magic-link.ts +54 -0
  82. package/src/domain/models/app/auth/oauth/index.ts +8 -0
  83. package/src/domain/models/app/auth/oauth/providers.ts +105 -0
  84. package/src/domain/models/app/auth/plugins/admin.ts +130 -0
  85. package/src/domain/models/app/auth/plugins/index.ts +74 -0
  86. package/src/domain/models/app/auth/plugins/two-factor.ts +63 -0
  87. package/src/domain/models/app/auth/roles.ts +179 -0
  88. package/src/domain/models/app/auth/strategies.ts +191 -0
  89. package/src/domain/models/app/auth/validation.ts +127 -0
  90. package/src/domain/models/app/common/branded-ids.ts +200 -0
  91. package/src/domain/models/app/common/definitions.ts +187 -0
  92. package/src/domain/models/app/component/common/component-children.ts +119 -0
  93. package/src/domain/models/app/component/common/component-props.ts +89 -0
  94. package/src/domain/models/app/component/common/component-reference.ts +170 -0
  95. package/src/domain/models/app/component/component.ts +81 -0
  96. package/src/domain/models/app/components.ts +65 -0
  97. package/src/domain/models/app/description.ts +83 -0
  98. package/src/domain/models/app/index.ts +258 -0
  99. package/src/domain/models/app/language/language-config.ts +200 -0
  100. package/src/domain/models/app/languages.ts +205 -0
  101. package/src/domain/models/app/name.ts +66 -0
  102. package/src/domain/models/app/page/common/interactions/click-interaction.ts +116 -0
  103. package/src/domain/models/app/page/common/interactions/entrance-animation.ts +84 -0
  104. package/src/domain/models/app/page/common/interactions/hover-interaction.ts +144 -0
  105. package/src/domain/models/app/page/common/interactions/interactions.ts +64 -0
  106. package/src/domain/models/app/page/common/interactions/scroll-interaction.ts +93 -0
  107. package/src/domain/models/app/page/common/responsive.ts +114 -0
  108. package/src/domain/models/app/page/common/url.ts +35 -0
  109. package/src/domain/models/app/page/common/variable-reference.ts +53 -0
  110. package/src/domain/models/app/page/id.ts +44 -0
  111. package/src/domain/models/app/page/index.ts +270 -0
  112. package/src/domain/models/app/page/meta/analytics.ts +248 -0
  113. package/src/domain/models/app/page/meta/custom-elements.ts +180 -0
  114. package/src/domain/models/app/page/meta/dns-prefetch.ts +77 -0
  115. package/src/domain/models/app/page/meta/favicon-set.ts +203 -0
  116. package/src/domain/models/app/page/meta/favicon.ts +50 -0
  117. package/src/domain/models/app/page/meta/favicons-config.ts +73 -0
  118. package/src/domain/models/app/page/meta/index.ts +278 -0
  119. package/src/domain/models/app/page/meta/open-graph.ts +166 -0
  120. package/src/domain/models/app/page/meta/preload.ts +190 -0
  121. package/src/domain/models/app/page/meta/structured-data/article.ts +211 -0
  122. package/src/domain/models/app/page/meta/structured-data/breadcrumb.ts +115 -0
  123. package/src/domain/models/app/page/meta/structured-data/common-fields.ts +201 -0
  124. package/src/domain/models/app/page/meta/structured-data/education-event.ts +256 -0
  125. package/src/domain/models/app/page/meta/structured-data/faq-page.ts +127 -0
  126. package/src/domain/models/app/page/meta/structured-data/index.ts +95 -0
  127. package/src/domain/models/app/page/meta/structured-data/local-business.ts +247 -0
  128. package/src/domain/models/app/page/meta/structured-data/organization.ts +171 -0
  129. package/src/domain/models/app/page/meta/structured-data/person.ts +138 -0
  130. package/src/domain/models/app/page/meta/structured-data/postal-address.ts +106 -0
  131. package/src/domain/models/app/page/meta/structured-data/product.ts +214 -0
  132. package/src/domain/models/app/page/meta/twitter-card.ts +217 -0
  133. package/src/domain/models/app/page/name.ts +38 -0
  134. package/src/domain/models/app/page/path.ts +21 -0
  135. package/src/domain/models/app/page/scripts/external-scripts.ts +163 -0
  136. package/src/domain/models/app/page/scripts/features.ts +135 -0
  137. package/src/domain/models/app/page/scripts/inline-scripts.ts +114 -0
  138. package/src/domain/models/app/page/scripts/scripts.ts +102 -0
  139. package/src/domain/models/app/page/sections.ts +298 -0
  140. package/src/domain/models/app/pages.ts +61 -0
  141. package/src/domain/models/app/permissions/index.ts +61 -0
  142. package/src/domain/models/app/permissions/resource-action.ts +114 -0
  143. package/src/domain/models/app/permissions/roles.ts +120 -0
  144. package/src/domain/models/app/table/check-constraints.ts +105 -0
  145. package/src/domain/models/app/table/cycle-detection.ts +124 -0
  146. package/src/domain/models/app/table/database-identifier.ts +153 -0
  147. package/src/domain/models/app/table/field-name.ts +36 -0
  148. package/src/domain/models/app/table/field-types/advanced/array-field.ts +33 -0
  149. package/src/domain/models/app/table/field-types/advanced/autonumber-field.ts +54 -0
  150. package/src/domain/models/app/table/field-types/advanced/button-field.ts +56 -0
  151. package/src/domain/models/app/table/field-types/advanced/color-field.ts +57 -0
  152. package/src/domain/models/app/table/field-types/advanced/count-field.ts +54 -0
  153. package/src/domain/models/app/table/field-types/advanced/formula-field.ts +58 -0
  154. package/src/domain/models/app/table/field-types/advanced/geolocation-field.ts +49 -0
  155. package/src/domain/models/app/table/field-types/advanced/index.ts +16 -0
  156. package/src/domain/models/app/table/field-types/advanced/json-field.ts +25 -0
  157. package/src/domain/models/app/table/field-types/advanced/unknown-field.ts +85 -0
  158. package/src/domain/models/app/table/field-types/base-field.ts +42 -0
  159. package/src/domain/models/app/table/field-types/date-time/created-at-field.ts +49 -0
  160. package/src/domain/models/app/table/field-types/date-time/date-field.ts +95 -0
  161. package/src/domain/models/app/table/field-types/date-time/deleted-at-field.ts +56 -0
  162. package/src/domain/models/app/table/field-types/date-time/duration-field.ts +73 -0
  163. package/src/domain/models/app/table/field-types/date-time/index.ts +12 -0
  164. package/src/domain/models/app/table/field-types/date-time/updated-at-field.ts +50 -0
  165. package/src/domain/models/app/table/field-types/index.ts +19 -0
  166. package/src/domain/models/app/table/field-types/media/barcode-field.ts +58 -0
  167. package/src/domain/models/app/table/field-types/media/index.ts +10 -0
  168. package/src/domain/models/app/table/field-types/media/multiple-attachments-field.ts +80 -0
  169. package/src/domain/models/app/table/field-types/media/single-attachment-field.ts +81 -0
  170. package/src/domain/models/app/table/field-types/numeric/currency-field.ts +144 -0
  171. package/src/domain/models/app/table/field-types/numeric/decimal-field.ts +113 -0
  172. package/src/domain/models/app/table/field-types/numeric/index.ts +13 -0
  173. package/src/domain/models/app/table/field-types/numeric/integer-field.ts +98 -0
  174. package/src/domain/models/app/table/field-types/numeric/percentage-field.ts +115 -0
  175. package/src/domain/models/app/table/field-types/numeric/progress-field.ts +71 -0
  176. package/src/domain/models/app/table/field-types/numeric/rating-field.ts +74 -0
  177. package/src/domain/models/app/table/field-types/relational/index.ts +10 -0
  178. package/src/domain/models/app/table/field-types/relational/lookup-field.ts +46 -0
  179. package/src/domain/models/app/table/field-types/relational/relationship-field.ts +112 -0
  180. package/src/domain/models/app/table/field-types/relational/rollup-field.ts +58 -0
  181. package/src/domain/models/app/table/field-types/selection/checkbox-field.ts +51 -0
  182. package/src/domain/models/app/table/field-types/selection/index.ts +11 -0
  183. package/src/domain/models/app/table/field-types/selection/multi-select-field.ts +68 -0
  184. package/src/domain/models/app/table/field-types/selection/single-select-field.ts +54 -0
  185. package/src/domain/models/app/table/field-types/selection/status-field.ts +37 -0
  186. package/src/domain/models/app/table/field-types/text/email-field.ts +80 -0
  187. package/src/domain/models/app/table/field-types/text/index.ts +13 -0
  188. package/src/domain/models/app/table/field-types/text/long-text-field.ts +77 -0
  189. package/src/domain/models/app/table/field-types/text/phone-number-field.ts +82 -0
  190. package/src/domain/models/app/table/field-types/text/rich-text-field.ts +66 -0
  191. package/src/domain/models/app/table/field-types/text/single-line-text-field.ts +79 -0
  192. package/src/domain/models/app/table/field-types/text/url-field.ts +81 -0
  193. package/src/domain/models/app/table/field-types/user/created-by-field.ts +50 -0
  194. package/src/domain/models/app/table/field-types/user/deleted-by-field.ts +57 -0
  195. package/src/domain/models/app/table/field-types/user/index.ts +11 -0
  196. package/src/domain/models/app/table/field-types/user/updated-by-field.ts +51 -0
  197. package/src/domain/models/app/table/field-types/user/user-field.ts +52 -0
  198. package/src/domain/models/app/table/field-types/validation-utils.ts +166 -0
  199. package/src/domain/models/app/table/fields.ts +216 -0
  200. package/src/domain/models/app/table/foreign-keys.ts +111 -0
  201. package/src/domain/models/app/table/formula-keywords.ts +326 -0
  202. package/src/domain/models/app/table/id.ts +31 -0
  203. package/src/domain/models/app/table/index.ts +290 -0
  204. package/src/domain/models/app/table/indexes.ts +80 -0
  205. package/src/domain/models/app/table/name.ts +37 -0
  206. package/src/domain/models/app/table/permissions/field-permission.ts +83 -0
  207. package/src/domain/models/app/table/permissions/index.ts +167 -0
  208. package/src/domain/models/app/table/permissions/permission-evaluator.ts +372 -0
  209. package/src/domain/models/app/table/permissions/permission.ts +49 -0
  210. package/src/domain/models/app/table/primary-key.ts +62 -0
  211. package/src/domain/models/app/table/table-formula-validation.ts +168 -0
  212. package/src/domain/models/app/table/table-indexes-validation.ts +38 -0
  213. package/src/domain/models/app/table/table-permissions-validation.ts +77 -0
  214. package/src/domain/models/app/table/table-primary-key-validation.ts +49 -0
  215. package/src/domain/models/app/table/table-views-validation.ts +408 -0
  216. package/src/domain/models/app/table/unique-constraints.ts +79 -0
  217. package/src/domain/models/app/table/views/fields.ts +28 -0
  218. package/src/domain/models/app/table/views/filters.ts +162 -0
  219. package/src/domain/models/app/table/views/group-by.ts +32 -0
  220. package/src/domain/models/app/table/views/id.ts +50 -0
  221. package/src/domain/models/app/table/views/index.ts +177 -0
  222. package/src/domain/models/app/table/views/name.ts +32 -0
  223. package/src/domain/models/app/table/views/permissions.ts +98 -0
  224. package/src/domain/models/app/table/views/sorts.ts +31 -0
  225. package/src/domain/models/app/tables.ts +695 -0
  226. package/src/domain/models/app/theme/animations.ts +208 -0
  227. package/src/domain/models/app/theme/border-radius.ts +58 -0
  228. package/src/domain/models/app/theme/breakpoints.ts +62 -0
  229. package/src/domain/models/app/theme/colors.ts +110 -0
  230. package/src/domain/models/app/theme/fonts.ts +164 -0
  231. package/src/domain/models/app/theme/shadows.ts +61 -0
  232. package/src/domain/models/app/theme/spacing.ts +115 -0
  233. package/src/domain/models/app/theme.ts +66 -0
  234. package/src/domain/models/app/version.ts +87 -0
  235. package/src/domain/models/record-comment.ts +91 -0
  236. package/src/domain/utils/content-parsing.ts +49 -0
  237. package/src/domain/utils/format-detection.ts +69 -0
  238. package/src/domain/utils/index.ts +9 -0
  239. package/src/domain/utils/route-matcher.ts +184 -0
  240. package/src/domain/utils/translation-resolver.ts +170 -0
  241. package/src/index.ts +208 -0
  242. package/src/infrastructure/analytics/tracking-script.ts +48 -0
  243. package/src/infrastructure/auth/better-auth/auth.ts +216 -0
  244. package/src/infrastructure/auth/better-auth/email-handlers.ts +162 -0
  245. package/src/infrastructure/auth/better-auth/index.ts +16 -0
  246. package/src/infrastructure/auth/better-auth/layer.ts +97 -0
  247. package/src/infrastructure/auth/better-auth/plugins/admin.ts +56 -0
  248. package/src/infrastructure/auth/better-auth/plugins/magic-link.ts +31 -0
  249. package/src/infrastructure/auth/better-auth/plugins/two-factor.ts +19 -0
  250. package/src/infrastructure/auth/better-auth/schema.ts +152 -0
  251. package/src/infrastructure/auth/index.ts +27 -0
  252. package/src/infrastructure/css/cache/css-cache-service.ts +130 -0
  253. package/src/infrastructure/css/compiler.ts +210 -0
  254. package/src/infrastructure/css/css-compiler-live.ts +20 -0
  255. package/src/infrastructure/css/index.ts +25 -0
  256. package/src/infrastructure/css/styles/animation-styles-generator.ts +177 -0
  257. package/src/infrastructure/css/styles/click-animations.ts +147 -0
  258. package/src/infrastructure/css/styles/component-layer-generators.ts +147 -0
  259. package/src/infrastructure/css/theme/theme-generators.ts +130 -0
  260. package/src/infrastructure/css/theme/theme-layer-generators.ts +219 -0
  261. package/src/infrastructure/css/theme/theme-token-resolver.ts +76 -0
  262. package/src/infrastructure/database/activity-queries.ts +111 -0
  263. package/src/infrastructure/database/auth/auth-validation.ts +101 -0
  264. package/src/infrastructure/database/drizzle/db-bun.ts +17 -0
  265. package/src/infrastructure/database/drizzle/db.ts +17 -0
  266. package/src/infrastructure/database/drizzle/index.ts +16 -0
  267. package/src/infrastructure/database/drizzle/layer.ts +34 -0
  268. package/src/infrastructure/database/drizzle/migrate.ts +77 -0
  269. package/src/infrastructure/database/drizzle/schema/activity-log.ts +111 -0
  270. package/src/infrastructure/database/drizzle/schema/analytics-page-views.ts +116 -0
  271. package/src/infrastructure/database/drizzle/schema/migration-audit.ts +68 -0
  272. package/src/infrastructure/database/drizzle/schema/record-comments.ts +79 -0
  273. package/src/infrastructure/database/drizzle/schema.ts +12 -0
  274. package/src/infrastructure/database/field-utils.ts +87 -0
  275. package/src/infrastructure/database/filter-operators.ts +136 -0
  276. package/src/infrastructure/database/formula/formula-trigger-generators.ts +114 -0
  277. package/src/infrastructure/database/formula/formula-utils.ts +440 -0
  278. package/src/infrastructure/database/generators/index-generators.ts +152 -0
  279. package/src/infrastructure/database/generators/trigger-generators.ts +154 -0
  280. package/src/infrastructure/database/index.ts +35 -0
  281. package/src/infrastructure/database/lookup/lookup-expression-generators.ts +356 -0
  282. package/src/infrastructure/database/lookup/lookup-expressions.ts +116 -0
  283. package/src/infrastructure/database/lookup/lookup-view-generators.ts +403 -0
  284. package/src/infrastructure/database/lookup/lookup-view-helpers.ts +65 -0
  285. package/src/infrastructure/database/lookup/lookup-view-triggers.ts +121 -0
  286. package/src/infrastructure/database/migration-audit-trail.ts +375 -0
  287. package/src/infrastructure/database/repositories/activity-log-repository-live.ts +99 -0
  288. package/src/infrastructure/database/repositories/activity-repository-live.ts +21 -0
  289. package/src/infrastructure/database/repositories/analytics-repository-live.ts +316 -0
  290. package/src/infrastructure/database/repositories/auth-repository-live.ts +42 -0
  291. package/src/infrastructure/database/repositories/batch-repository-live.ts +29 -0
  292. package/src/infrastructure/database/repositories/comment-repository-live.ts +39 -0
  293. package/src/infrastructure/database/repositories/table-repository-live.ts +38 -0
  294. package/src/infrastructure/database/schema/schema-dependency-sorting.ts +142 -0
  295. package/src/infrastructure/database/schema/schema-initializer.ts +598 -0
  296. package/src/infrastructure/database/schema-migration/column-detection.ts +286 -0
  297. package/src/infrastructure/database/schema-migration/constants.ts +31 -0
  298. package/src/infrastructure/database/schema-migration/constraint-sync.ts +288 -0
  299. package/src/infrastructure/database/schema-migration/index-sync.ts +108 -0
  300. package/src/infrastructure/database/schema-migration/index.ts +66 -0
  301. package/src/infrastructure/database/schema-migration/migration-statements.ts +106 -0
  302. package/src/infrastructure/database/schema-migration/rename-detection.ts +87 -0
  303. package/src/infrastructure/database/schema-migration/table-operations.ts +65 -0
  304. package/src/infrastructure/database/schema-migration/type-utils.ts +98 -0
  305. package/src/infrastructure/database/schema-migration/types.ts +14 -0
  306. package/src/infrastructure/database/schema-migration-helpers.ts +53 -0
  307. package/src/infrastructure/database/session-context.ts +20 -0
  308. package/src/infrastructure/database/sql/sql-check-constraints.ts +252 -0
  309. package/src/infrastructure/database/sql/sql-column-generators.ts +174 -0
  310. package/src/infrastructure/database/sql/sql-execution.ts +245 -0
  311. package/src/infrastructure/database/sql/sql-field-predicates.ts +81 -0
  312. package/src/infrastructure/database/sql/sql-generators.ts +91 -0
  313. package/src/infrastructure/database/sql/sql-junction-tables.ts +79 -0
  314. package/src/infrastructure/database/sql/sql-key-constraints.ts +210 -0
  315. package/src/infrastructure/database/sql/sql-type-mappings.ts +106 -0
  316. package/src/infrastructure/database/sql/sql-utils.ts +53 -0
  317. package/src/infrastructure/database/table-live-layers.ts +30 -0
  318. package/src/infrastructure/database/table-operations/column-generators.ts +82 -0
  319. package/src/infrastructure/database/table-operations/create-table-sql.ts +81 -0
  320. package/src/infrastructure/database/table-operations/index.ts +55 -0
  321. package/src/infrastructure/database/table-operations/migration-utils.ts +157 -0
  322. package/src/infrastructure/database/table-operations/table-effects.ts +234 -0
  323. package/src/infrastructure/database/table-operations/table-features.ts +96 -0
  324. package/src/infrastructure/database/table-operations/type-compatibility.ts +58 -0
  325. package/src/infrastructure/database/table-operations.ts +47 -0
  326. package/src/infrastructure/database/table-queries/batch/batch-create.ts +80 -0
  327. package/src/infrastructure/database/table-queries/batch/batch-delete.ts +212 -0
  328. package/src/infrastructure/database/table-queries/batch/batch-helpers.ts +124 -0
  329. package/src/infrastructure/database/table-queries/batch/batch-restore.ts +161 -0
  330. package/src/infrastructure/database/table-queries/batch/batch-update.ts +146 -0
  331. package/src/infrastructure/database/table-queries/batch/batch-upsert.ts +357 -0
  332. package/src/infrastructure/database/table-queries/batch/batch.ts +14 -0
  333. package/src/infrastructure/database/table-queries/crud/crud-read.ts +351 -0
  334. package/src/infrastructure/database/table-queries/crud/crud-write.ts +399 -0
  335. package/src/infrastructure/database/table-queries/crud/crud.ts +16 -0
  336. package/src/infrastructure/database/table-queries/index.ts +11 -0
  337. package/src/infrastructure/database/table-queries/mutation-helpers/authorship-helpers.ts +152 -0
  338. package/src/infrastructure/database/table-queries/mutation-helpers/create-record-helpers.ts +90 -0
  339. package/src/infrastructure/database/table-queries/mutation-helpers/delete-helpers.ts +163 -0
  340. package/src/infrastructure/database/table-queries/mutation-helpers/record-fetch-helpers.ts +79 -0
  341. package/src/infrastructure/database/table-queries/mutation-helpers/update-helpers.ts +74 -0
  342. package/src/infrastructure/database/table-queries/query-helpers/activity-log-helpers.ts +53 -0
  343. package/src/infrastructure/database/table-queries/query-helpers/activity-queries.ts +106 -0
  344. package/src/infrastructure/database/table-queries/query-helpers/aggregation-helpers.ts +314 -0
  345. package/src/infrastructure/database/table-queries/query-helpers/comment-queries.ts +414 -0
  346. package/src/infrastructure/database/table-queries/query-helpers/record-validation-queries.ts +126 -0
  347. package/src/infrastructure/database/table-queries/query-helpers/trash-helpers.ts +58 -0
  348. package/src/infrastructure/database/table-queries/shared/error-handling.ts +47 -0
  349. package/src/infrastructure/database/table-queries/shared/typed-execute.ts +27 -0
  350. package/src/infrastructure/database/table-queries/shared/user-join-helpers.ts +38 -0
  351. package/src/infrastructure/database/table-queries/shared/validation.ts +39 -0
  352. package/src/infrastructure/database/views/view-generators.ts +258 -0
  353. package/src/infrastructure/devtools/devtools-layer.ts +43 -0
  354. package/src/infrastructure/devtools/index.ts +8 -0
  355. package/src/infrastructure/email/email-config.ts +103 -0
  356. package/src/infrastructure/email/email-service.ts +152 -0
  357. package/src/infrastructure/email/index.ts +107 -0
  358. package/src/infrastructure/email/nodemailer.ts +125 -0
  359. package/src/infrastructure/email/templates.ts +244 -0
  360. package/src/infrastructure/errors/auth-config-required-error.ts +21 -0
  361. package/src/infrastructure/errors/auth-error.ts +16 -0
  362. package/src/infrastructure/errors/css-compilation-error.ts +14 -0
  363. package/src/infrastructure/errors/index.ts +26 -0
  364. package/src/infrastructure/errors/schema-initialization-error.ts +19 -0
  365. package/src/infrastructure/errors/server-creation-error.ts +14 -0
  366. package/src/infrastructure/filesystem/copy-directory.ts +136 -0
  367. package/src/infrastructure/layers/app-layer.ts +61 -0
  368. package/src/infrastructure/layers/page-renderer-layer.ts +41 -0
  369. package/src/infrastructure/logging/index.ts +8 -0
  370. package/src/infrastructure/logging/logger.ts +204 -0
  371. package/src/infrastructure/schema/file-loader.ts +53 -0
  372. package/src/infrastructure/schema/index.ts +15 -0
  373. package/src/infrastructure/schema/remote-loader.ts +48 -0
  374. package/src/infrastructure/server/index.ts +26 -0
  375. package/src/infrastructure/server/language-detection.ts +87 -0
  376. package/src/infrastructure/server/lifecycle.ts +67 -0
  377. package/src/infrastructure/server/route-setup/api-routes.ts +310 -0
  378. package/src/infrastructure/server/route-setup/auth-route-utils.ts +399 -0
  379. package/src/infrastructure/server/route-setup/auth-routes.ts +245 -0
  380. package/src/infrastructure/server/route-setup/openapi-routes.ts +45 -0
  381. package/src/infrastructure/server/route-setup/openapi-schema.ts +120 -0
  382. package/src/infrastructure/server/route-setup/page-routes.ts +219 -0
  383. package/src/infrastructure/server/route-setup/static-assets.ts +191 -0
  384. package/src/infrastructure/server/server-factory-live.ts +45 -0
  385. package/src/infrastructure/server/server.ts +275 -0
  386. package/src/infrastructure/server/ssg-adapter.ts +196 -0
  387. package/src/infrastructure/server/static-site-generator-live.ts +20 -0
  388. package/src/infrastructure/utils/accept-language-parser.ts +106 -0
  389. package/src/infrastructure/utils/glob-matcher.ts +50 -0
  390. package/src/presentation/api/client.ts +114 -0
  391. package/src/presentation/api/middleware/auth.ts +233 -0
  392. package/src/presentation/api/middleware/table.ts +155 -0
  393. package/src/presentation/api/middleware/validation.ts +88 -0
  394. package/src/presentation/api/routes/activity/get-activity-by-id-handler.ts +77 -0
  395. package/src/presentation/api/routes/activity/index.ts +28 -0
  396. package/src/presentation/api/routes/activity.ts +339 -0
  397. package/src/presentation/api/routes/analytics.ts +328 -0
  398. package/src/presentation/api/routes/auth.ts +169 -0
  399. package/src/presentation/api/routes/index.ts +11 -0
  400. package/src/presentation/api/routes/tables/activity-handlers.ts +57 -0
  401. package/src/presentation/api/routes/tables/batch-permission-helpers.ts +163 -0
  402. package/src/presentation/api/routes/tables/batch-routes.ts +355 -0
  403. package/src/presentation/api/routes/tables/comment-handlers.ts +377 -0
  404. package/src/presentation/api/routes/tables/create-record-helpers.ts +179 -0
  405. package/src/presentation/api/routes/tables/effect-runner.ts +58 -0
  406. package/src/presentation/api/routes/tables/error-handlers.ts +53 -0
  407. package/src/presentation/api/routes/tables/field-permission-validation.ts +167 -0
  408. package/src/presentation/api/routes/tables/filter-parser.ts +75 -0
  409. package/src/presentation/api/routes/tables/formula-parser.ts +118 -0
  410. package/src/presentation/api/routes/tables/index.ts +113 -0
  411. package/src/presentation/api/routes/tables/list-records-filter.ts +54 -0
  412. package/src/presentation/api/routes/tables/param-parsers.ts +59 -0
  413. package/src/presentation/api/routes/tables/record-handlers.ts +484 -0
  414. package/src/presentation/api/routes/tables/record-routes.ts +53 -0
  415. package/src/presentation/api/routes/tables/record-update-handler.ts +200 -0
  416. package/src/presentation/api/routes/tables/sort-validation.ts +85 -0
  417. package/src/presentation/api/routes/tables/table-routes.ts +76 -0
  418. package/src/presentation/api/routes/tables/timezone-validation.ts +41 -0
  419. package/src/presentation/api/routes/tables/upsert-helpers.ts +471 -0
  420. package/src/presentation/api/routes/tables/utils.ts +159 -0
  421. package/src/presentation/api/routes/tables/view-routes.ts +51 -0
  422. package/src/presentation/api/routes/tables.ts +9 -0
  423. package/src/presentation/api/utils/context-helpers.ts +43 -0
  424. package/src/presentation/api/utils/error-sanitizer.ts +235 -0
  425. package/src/presentation/api/utils/field-permission-validator.ts +53 -0
  426. package/src/presentation/api/utils/filter-field-validator.ts +90 -0
  427. package/src/presentation/api/utils/index.ts +13 -0
  428. package/src/presentation/api/utils/run-effect.ts +94 -0
  429. package/src/presentation/api/utils/validate-request.ts +89 -0
  430. package/src/presentation/api/validation/index.ts +29 -0
  431. package/src/presentation/api/validation/rules/field-rules.ts +158 -0
  432. package/src/presentation/api/validation/rules/record-rules.ts +73 -0
  433. package/src/presentation/cli/index.ts +19 -0
  434. package/src/presentation/cli/schema-loader.ts +172 -0
  435. package/src/presentation/hooks/use-breakpoint.ts +155 -0
  436. package/src/presentation/rendering/render-error-pages.tsx +60 -0
  437. package/src/presentation/rendering/render-homepage.tsx +137 -0
  438. package/src/presentation/scripts/script-renderers.ts +112 -0
  439. package/src/presentation/styling/animation-composer.ts +117 -0
  440. package/src/presentation/styling/index.ts +13 -0
  441. package/src/presentation/styling/parse-style.ts +243 -0
  442. package/src/presentation/styling/style-utils.ts +50 -0
  443. package/src/presentation/styling/theme-colors.ts +53 -0
  444. package/src/presentation/translations/component-utils.ts +54 -0
  445. package/src/presentation/translations/index.ts +16 -0
  446. package/src/presentation/translations/translation-resolver.ts +22 -0
  447. package/src/presentation/ui/languages/language-switcher.tsx +119 -0
  448. package/src/presentation/ui/metadata/analytics-builders.tsx +174 -0
  449. package/src/presentation/ui/metadata/analytics-head.tsx +39 -0
  450. package/src/presentation/ui/metadata/custom-elements-builders.tsx +157 -0
  451. package/src/presentation/ui/metadata/extract-component-meta.ts +108 -0
  452. package/src/presentation/ui/metadata/head-elements.tsx +164 -0
  453. package/src/presentation/ui/metadata/index.tsx +35 -0
  454. package/src/presentation/ui/metadata/meta-utils.tsx +42 -0
  455. package/src/presentation/ui/metadata/open-graph-meta.tsx +57 -0
  456. package/src/presentation/ui/metadata/structured-data-from-component.tsx +134 -0
  457. package/src/presentation/ui/metadata/structured-data.tsx +88 -0
  458. package/src/presentation/ui/metadata/twitter-card-meta.tsx +80 -0
  459. package/src/presentation/ui/pages/DefaultHomePage.tsx +43 -0
  460. package/src/presentation/ui/pages/DefaultPageConfigs.ts +220 -0
  461. package/src/presentation/ui/pages/DynamicPage.tsx +307 -0
  462. package/src/presentation/ui/pages/ErrorPage.tsx +25 -0
  463. package/src/presentation/ui/pages/NotFoundPage.tsx +25 -0
  464. package/src/presentation/ui/pages/PageBodyScripts.tsx +242 -0
  465. package/src/presentation/ui/pages/PageBodyStyles.ts +52 -0
  466. package/src/presentation/ui/pages/PageHead.tsx +380 -0
  467. package/src/presentation/ui/pages/PageLangResolver.ts +58 -0
  468. package/src/presentation/ui/pages/PageMain.tsx +58 -0
  469. package/src/presentation/ui/pages/PageMetadata.ts +168 -0
  470. package/src/presentation/ui/pages/PageMetadataI18n.ts +169 -0
  471. package/src/presentation/ui/pages/PageScripts.ts +78 -0
  472. package/src/presentation/ui/pages/SectionRenderer.tsx +67 -0
  473. package/src/presentation/ui/pages/SectionSpacing.tsx +131 -0
  474. package/src/presentation/ui/sections/component-renderer.tsx +426 -0
  475. package/src/presentation/ui/sections/component-renderer.types.ts +33 -0
  476. package/src/presentation/ui/sections/components/component-reference-handler.tsx +74 -0
  477. package/src/presentation/ui/sections/components/component-resolution.ts +65 -0
  478. package/src/presentation/ui/sections/components/index.ts +9 -0
  479. package/src/presentation/ui/sections/hero.tsx +394 -0
  480. package/src/presentation/ui/sections/props/component-builder.ts +183 -0
  481. package/src/presentation/ui/sections/props/element-props.ts +179 -0
  482. package/src/presentation/ui/sections/props/index.ts +9 -0
  483. package/src/presentation/ui/sections/props/prop-conversion.ts +171 -0
  484. package/src/presentation/ui/sections/props/props-builder-config.ts +42 -0
  485. package/src/presentation/ui/sections/props/props-builder.ts +296 -0
  486. package/src/presentation/ui/sections/renderers/element-renderers/html-element-renderer.tsx +124 -0
  487. package/src/presentation/ui/sections/renderers/element-renderers/index.ts +59 -0
  488. package/src/presentation/ui/sections/renderers/element-renderers/interactive-renderers.tsx +231 -0
  489. package/src/presentation/ui/sections/renderers/element-renderers/media-renderers.tsx +102 -0
  490. package/src/presentation/ui/sections/renderers/element-renderers/text-content-renderers.tsx +42 -0
  491. package/src/presentation/ui/sections/renderers/element-renderers.ts +53 -0
  492. package/src/presentation/ui/sections/renderers/html-element-helpers.ts +100 -0
  493. package/src/presentation/ui/sections/renderers/specialized-renderers.tsx +212 -0
  494. package/src/presentation/ui/sections/rendering/component-dispatch-config.ts +31 -0
  495. package/src/presentation/ui/sections/rendering/component-registry/index.ts +39 -0
  496. package/src/presentation/ui/sections/rendering/component-registry/interactive-components.ts +54 -0
  497. package/src/presentation/ui/sections/rendering/component-registry/media-components.ts +36 -0
  498. package/src/presentation/ui/sections/rendering/component-registry/special-components.tsx +153 -0
  499. package/src/presentation/ui/sections/rendering/component-registry/structural-components.ts +215 -0
  500. package/src/presentation/ui/sections/rendering/component-registry/text-components.ts +57 -0
  501. package/src/presentation/ui/sections/rendering/component-registry-helpers.tsx +29 -0
  502. package/src/presentation/ui/sections/rendering/component-registry.tsx +21 -0
  503. package/src/presentation/ui/sections/rendering/component-type-dispatcher.tsx +33 -0
  504. package/src/presentation/ui/sections/rendering/index.ts +9 -0
  505. package/src/presentation/ui/sections/responsive/responsive-children-builder.tsx +96 -0
  506. package/src/presentation/ui/sections/responsive/responsive-content-builder.tsx +95 -0
  507. package/src/presentation/ui/sections/responsive/responsive-props-merger.ts +195 -0
  508. package/src/presentation/ui/sections/responsive/responsive-resolver.ts +213 -0
  509. package/src/presentation/ui/sections/styling/animation-composer-wrapper.ts +65 -0
  510. package/src/presentation/ui/sections/styling/class-builders.ts +45 -0
  511. package/src/presentation/ui/sections/styling/color-resolver.ts +43 -0
  512. package/src/presentation/ui/sections/styling/hover-interaction-handler.ts +107 -0
  513. package/src/presentation/ui/sections/styling/index.ts +9 -0
  514. package/src/presentation/ui/sections/styling/interaction-props-builder.ts +55 -0
  515. package/src/presentation/ui/sections/styling/shadow-resolver.ts +83 -0
  516. package/src/presentation/ui/sections/styling/spacing-resolver.ts +104 -0
  517. package/src/presentation/ui/sections/styling/style-processor.ts +170 -0
  518. package/src/presentation/ui/sections/styling/theme-tokens.ts +184 -0
  519. package/src/presentation/ui/sections/translations/i18n-content-resolver.ts +198 -0
  520. package/src/presentation/ui/sections/translations/index.ts +9 -0
  521. package/src/presentation/ui/sections/translations/translation-handler.ts +143 -0
  522. package/src/presentation/ui/sections/translations/variable-substitution.ts +225 -0
  523. package/src/presentation/ui/sections/utils/time-parser.ts +82 -0
  524. package/src/presentation/utils/link-attributes.ts +50 -0
  525. package/src/presentation/utils/string-utils.ts +58 -0
  526. package/src/presentation/utils/styles.ts +50 -0
  527. package/tsconfig.json +46 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) 2025 ESSENTIAL SERVICES
3
+ *
4
+ * This source code is licensed under the Business Source License 1.1
5
+ * found in the LICENSE.md file in the root directory of this source tree.
6
+ */
7
+
8
+ import {
9
+ substituteVariableValues,
10
+ substituteChildrenVariables,
11
+ substitutePropsVariables,
12
+ } from '../translations/variable-substitution'
13
+ import type { Components } from '@/domain/models/app/components'
14
+ import type { Component } from '@/domain/models/app/page/sections'
15
+
16
+ /**
17
+ * Resolves a component reference to a Component with optional variable substitution
18
+ *
19
+ * Pure function that finds a component template by name, converts it to a Component,
20
+ * and applies variable substitution if vars are provided.
21
+ *
22
+ * @param componentName - Name of the component template to resolve
23
+ * @param components - Array of available component templates
24
+ * @param vars - Optional variables for substitution
25
+ * @returns Resolved component and name, or undefined if not found
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const components = [
30
+ * { name: 'hero', type: 'section', content: '$title' }
31
+ * ]
32
+ * const resolved = resolveComponent('hero', components, { title: 'Welcome' })
33
+ * // { component: { type: 'section', content: 'Welcome' }, name: 'hero' }
34
+ * ```
35
+ */
36
+ export function resolveComponent(
37
+ componentName: string,
38
+ components?: Components,
39
+ vars?: Record<string, string | number | boolean>
40
+ ): { readonly component: Component; readonly name: string } | undefined {
41
+ const template = components?.find((b) => b.name === componentName)
42
+ if (!template) {
43
+ // DEVELOPMENT WARNING: Keep console.warn for development debugging
44
+ // This warning alerts developers when a referenced component doesn't exist
45
+ // Helps identify typos or missing component definitions during development
46
+ // Safe to keep - provides helpful feedback for configuration errors
47
+ console.warn(`Component not found: ${componentName}`)
48
+ return undefined
49
+ }
50
+
51
+ // Cast template.children to Component children type for type compatibility
52
+ const templateChildren = template.children as ReadonlyArray<Component | string> | undefined
53
+
54
+ const component: Component = {
55
+ type: template.type,
56
+ props: substitutePropsVariables(template.props, vars),
57
+ children: substituteChildrenVariables(templateChildren, vars),
58
+ content:
59
+ typeof template.content === 'string'
60
+ ? (substituteVariableValues(template.content, vars) as string)
61
+ : template.content,
62
+ }
63
+
64
+ return { component, name: template.name }
65
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) 2025 ESSENTIAL SERVICES
3
+ *
4
+ * This source code is licensed under the Business Source License 1.1
5
+ * found in the LICENSE.md file in the root directory of this source tree.
6
+ */
7
+
8
+ // Barrel export for component system utilities
9
+ // Files will be added during migration
@@ -0,0 +1,394 @@
1
+ /**
2
+ * Copyright (c) 2025 ESSENTIAL SERVICES
3
+ *
4
+ * This source code is licensed under the Business Source License 1.1
5
+ * found in the LICENSE.md file in the root directory of this source tree.
6
+ */
7
+
8
+ import type { Theme } from '@/domain/models/app/theme'
9
+ import type { ReactElement, ReactNode } from 'react'
10
+
11
+ /**
12
+ * Extracted theme tokens for Hero component
13
+ */
14
+ interface HeroThemeTokens {
15
+ readonly breakpoints: {
16
+ readonly sm: number
17
+ readonly md: number
18
+ readonly lg: number
19
+ }
20
+ readonly colors: {
21
+ readonly background: string
22
+ readonly text: string
23
+ readonly primary: string
24
+ }
25
+ readonly spacing: {
26
+ readonly section: string
27
+ }
28
+ readonly borderRadius: {
29
+ readonly lg: string
30
+ }
31
+ readonly fonts: {
32
+ readonly title: {
33
+ readonly family: string
34
+ readonly weight: number
35
+ readonly size: string
36
+ }
37
+ readonly body: {
38
+ readonly family: string
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Default theme values
45
+ */
46
+ const DEFAULT_THEME = {
47
+ breakpoints: { sm: '640px', md: '768px', lg: '1024px' },
48
+ colors: { background: '#ffffff', text: '#212529', primary: '#007bff' },
49
+ spacing: { section: '4rem' },
50
+ borderRadius: { lg: '0.5rem' },
51
+ fonts: {
52
+ title: { family: 'Bely Display', weight: 700, size: '2.5rem' },
53
+ body: { family: 'Inter' },
54
+ },
55
+ } as const
56
+
57
+ /**
58
+ * Extract breakpoint values from theme
59
+ */
60
+ function extractBreakpoints(theme?: Theme): HeroThemeTokens['breakpoints'] {
61
+ return {
62
+ sm: parseInt(theme?.breakpoints?.sm ?? DEFAULT_THEME.breakpoints.sm, 10),
63
+ md: parseInt(theme?.breakpoints?.md ?? DEFAULT_THEME.breakpoints.md, 10),
64
+ lg: parseInt(theme?.breakpoints?.lg ?? DEFAULT_THEME.breakpoints.lg, 10),
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Extract color values from theme
70
+ */
71
+ function extractColors(theme?: Theme): HeroThemeTokens['colors'] {
72
+ return {
73
+ background: theme?.colors?.background ?? DEFAULT_THEME.colors.background,
74
+ text: theme?.colors?.text ?? DEFAULT_THEME.colors.text,
75
+ primary: theme?.colors?.primary ?? DEFAULT_THEME.colors.primary,
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Type helper for a single font configuration item
81
+ */
82
+ type FontItem = NonNullable<Theme['fonts']>[string]
83
+
84
+ /**
85
+ * Extract title font weight (handles both legacy and current schemas)
86
+ */
87
+ function extractTitleWeight(titleFont?: FontItem): number {
88
+ // @ts-expect-error - legacy schema support (weight as number)
89
+ const legacyWeight = titleFont?.weight as number | undefined
90
+ const currentWeight = titleFont?.weights?.[0]
91
+ return legacyWeight ?? currentWeight ?? DEFAULT_THEME.fonts.title.weight
92
+ }
93
+
94
+ /**
95
+ * Extract title font configuration
96
+ */
97
+ function extractTitleFont(titleFont?: FontItem): HeroThemeTokens['fonts']['title'] {
98
+ return {
99
+ family: titleFont?.family ?? DEFAULT_THEME.fonts.title.family,
100
+ weight: extractTitleWeight(titleFont),
101
+ size: titleFont?.size ?? DEFAULT_THEME.fonts.title.size,
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Extract font values from theme
107
+ */
108
+ function extractFonts(theme?: Theme): HeroThemeTokens['fonts'] {
109
+ return {
110
+ title: extractTitleFont(theme?.fonts?.title),
111
+ body: {
112
+ family: theme?.fonts?.body?.family ?? DEFAULT_THEME.fonts.body.family,
113
+ },
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Extract and normalize theme tokens for Hero component
119
+ */
120
+ function extractHeroTheme(theme?: Theme): HeroThemeTokens {
121
+ return {
122
+ breakpoints: extractBreakpoints(theme),
123
+ colors: extractColors(theme),
124
+ spacing: {
125
+ // Use explicit theme.spacing.section if provided, otherwise use mobile-first default
126
+ section: theme?.spacing?.section ?? '2rem',
127
+ },
128
+ borderRadius: {
129
+ lg: theme?.borderRadius?.lg ?? DEFAULT_THEME.borderRadius.lg,
130
+ },
131
+ fonts: extractFonts(theme),
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Default content demonstrating cohesive theme integration
137
+ */
138
+ function HeroDefaultContent({
139
+ themeTokens,
140
+ }: Readonly<{
141
+ readonly themeTokens: HeroThemeTokens
142
+ }>): ReactElement {
143
+ return (
144
+ <div
145
+ style={{
146
+ textAlign: 'center',
147
+ maxWidth: '800px',
148
+ }}
149
+ >
150
+ <h1
151
+ style={{
152
+ fontFamily: themeTokens.fonts.title.family,
153
+ fontWeight: themeTokens.fonts.title.weight,
154
+ fontSize: themeTokens.fonts.title.size,
155
+ color: themeTokens.colors.text,
156
+ marginBottom: '2rem',
157
+ }}
158
+ >
159
+ Welcome to Sovrium
160
+ </h1>
161
+ <button
162
+ style={{
163
+ backgroundColor: themeTokens.colors.primary,
164
+ color: '#ffffff',
165
+ fontFamily: themeTokens.fonts.body.family,
166
+ fontSize: '1rem',
167
+ padding: '0.75rem 1.5rem',
168
+ borderRadius: themeTokens.borderRadius.lg,
169
+ border: 'none',
170
+ cursor: 'pointer',
171
+ }}
172
+ >
173
+ Get Started
174
+ </button>
175
+ </div>
176
+ )
177
+ }
178
+
179
+ /**
180
+ * Generate responsive media query styles for Hero section
181
+ */
182
+ function generateHeroMediaQueries(
183
+ breakpoints: HeroThemeTokens['breakpoints'],
184
+ testId?: string
185
+ ): string {
186
+ return `
187
+ @media (min-width: ${breakpoints.sm}px) {
188
+ section[data-testid="${testId}"] {
189
+ padding: 3rem;
190
+ }
191
+ }
192
+ @media (min-width: ${breakpoints.md}px) {
193
+ section[data-testid="${testId}"] {
194
+ padding: 4rem;
195
+ }
196
+ }
197
+ @media (min-width: ${breakpoints.lg}px) {
198
+ section[data-testid="${testId}"] {
199
+ padding: 5rem;
200
+ }
201
+ }
202
+ `
203
+ }
204
+
205
+ /**
206
+ * Resolve easing token from theme
207
+ */
208
+ function resolveEasingToken(tokenName: string, theme?: Theme): string | undefined {
209
+ if (!theme?.animations) return undefined
210
+ const animations = theme.animations as Record<string, unknown>
211
+ const easingTokens = animations.easing as Record<string, unknown> | undefined
212
+ if (!easingTokens || typeof easingTokens !== 'object') return undefined
213
+ const easingValue = easingTokens[tokenName]
214
+ return easingValue ? String(easingValue) : undefined
215
+ }
216
+
217
+ /**
218
+ * Resolve color token from theme
219
+ */
220
+ function resolveColorToken(tokenName: string, theme?: Theme): string | undefined {
221
+ if (!theme?.colors) return undefined
222
+ const colorValue = theme.colors[tokenName]
223
+ return colorValue ? String(colorValue) : undefined
224
+ }
225
+
226
+ /**
227
+ * Resolve single token reference
228
+ */
229
+ function resolveSingleToken(category: string, tokenName: string, theme?: Theme): string {
230
+ if (category === 'easing') {
231
+ return resolveEasingToken(tokenName, theme) ?? `$${category}.${tokenName}`
232
+ }
233
+ if (category === 'colors') {
234
+ return resolveColorToken(tokenName, theme) ?? `$${category}.${tokenName}`
235
+ }
236
+ return `$${category}.${tokenName}`
237
+ }
238
+
239
+ /**
240
+ * Resolve token references in animation string
241
+ * Supports: $easing.smooth, $colors.primary, etc.
242
+ */
243
+ function resolveAnimationTokens(animation: string, theme?: Theme): string {
244
+ return animation.replace(/\$(\w+)\.(\w+)/g, (_match, category, tokenName) =>
245
+ resolveSingleToken(category, tokenName, theme)
246
+ )
247
+ }
248
+
249
+ /**
250
+ * Content structure for Hero section
251
+ */
252
+ interface HeroContent {
253
+ readonly button?: {
254
+ readonly text: string
255
+ readonly animation?: string
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Base section styles for Hero component
261
+ */
262
+ const heroSectionBaseStyle = {
263
+ minHeight: '200px',
264
+ display: 'flex',
265
+ alignItems: 'center',
266
+ justifyContent: 'center',
267
+ } as const
268
+
269
+ /**
270
+ * Check if theme has fadeInUp animation configured
271
+ */
272
+ function hasFadeInUpAnimation(theme?: Theme): boolean {
273
+ if (!theme?.animations) return false
274
+ const animations = theme.animations as Record<string, unknown>
275
+ return Boolean(animations.fadeInUp)
276
+ }
277
+
278
+ /**
279
+ * Build section style with theme tokens
280
+ */
281
+ function buildHeroSectionStyle(themeTokens: HeroThemeTokens): Record<string, string> {
282
+ return {
283
+ ...heroSectionBaseStyle,
284
+ backgroundColor: themeTokens.colors.background,
285
+ padding: themeTokens.spacing.section,
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Render Hero section with custom animated button
291
+ */
292
+ function HeroWithButton({
293
+ themeTokens,
294
+ buttonContent,
295
+ testId,
296
+ theme,
297
+ }: Readonly<{
298
+ readonly themeTokens: HeroThemeTokens
299
+ readonly buttonContent: NonNullable<HeroContent['button']>
300
+ readonly testId?: string
301
+ readonly theme?: Theme
302
+ }>): ReactElement {
303
+ const resolvedAnimation = buttonContent.animation
304
+ ? resolveAnimationTokens(buttonContent.animation, theme)
305
+ : undefined
306
+
307
+ return (
308
+ <section
309
+ data-testid={testId}
310
+ style={buildHeroSectionStyle(themeTokens)}
311
+ >
312
+ <button
313
+ data-testid="animated-cta"
314
+ style={{
315
+ backgroundColor: themeTokens.colors.primary,
316
+ color: '#ffffff',
317
+ fontFamily: themeTokens.fonts.body.family,
318
+ fontSize: '1rem',
319
+ padding: '0.75rem 1.5rem',
320
+ borderRadius: themeTokens.borderRadius.lg,
321
+ border: 'none',
322
+ cursor: 'pointer',
323
+ animation: resolvedAnimation,
324
+ }}
325
+ >
326
+ {buttonContent.text}
327
+ </button>
328
+ <style>{generateHeroMediaQueries(themeTokens.breakpoints, testId)}</style>
329
+ </section>
330
+ )
331
+ }
332
+
333
+ /**
334
+ * Hero Section Component
335
+ *
336
+ * Renders a hero section with full theme integration demonstrating cohesive UI.
337
+ * When no children are provided, renders default content (h1 heading + CTA button)
338
+ * that showcases all theme tokens applied together:
339
+ * - Background color (theme.colors.background)
340
+ * - Heading with theme fonts (family, size, weight, color)
341
+ * - Button with theme colors and border radius
342
+ * - Section padding (theme.spacing.section)
343
+ *
344
+ * Uses theme.breakpoints to determine responsive behavior via CSS custom properties.
345
+ * Applies progressive enhancement - padding increases as viewport grows.
346
+ *
347
+ * @param props - Component props
348
+ * @param props.theme - Theme configuration with all design tokens
349
+ * @param props.content - Structured content (button, etc.)
350
+ * @param props.children - Hero content (optional - defaults to themed heading + button)
351
+ * @param props.data-testid - Test identifier
352
+ * @returns Hero section element with cohesive theme integration
353
+ */
354
+ export function Hero({
355
+ theme,
356
+ content,
357
+ children,
358
+ ...props
359
+ }: Readonly<{
360
+ readonly theme?: Theme
361
+ readonly content?: HeroContent
362
+ readonly children?: ReactNode
363
+ readonly 'data-testid'?: string
364
+ }>): Readonly<ReactElement> {
365
+ const themeTokens = extractHeroTheme(theme)
366
+
367
+ if (content?.button) {
368
+ return (
369
+ <HeroWithButton
370
+ themeTokens={themeTokens}
371
+ buttonContent={content.button}
372
+ testId={props['data-testid']}
373
+ theme={theme}
374
+ />
375
+ )
376
+ }
377
+
378
+ const hasChildren =
379
+ children && (Array.isArray(children) ? children.length > 0 : Boolean(children))
380
+ const renderedContent = hasChildren ? children : <HeroDefaultContent themeTokens={themeTokens} />
381
+ const shouldAnimateFadeInUp = hasFadeInUpAnimation(theme)
382
+ const sectionClassName = shouldAnimateFadeInUp ? 'animate-fadeInUp' : undefined
383
+
384
+ return (
385
+ <section
386
+ data-testid={props['data-testid']}
387
+ style={buildHeroSectionStyle(themeTokens)}
388
+ className={sectionClassName}
389
+ >
390
+ {renderedContent}
391
+ <style>{generateHeroMediaQueries(themeTokens.breakpoints, props['data-testid'])}</style>
392
+ </section>
393
+ )
394
+ }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Copyright (c) 2025 ESSENTIAL SERVICES
3
+ *
4
+ * This source code is licensed under the Business Source License 1.1
5
+ * found in the LICENSE.md file in the root directory of this source tree.
6
+ */
7
+
8
+ import { buildHoverTransitionStyles } from '../styling/hover-interaction-handler'
9
+ import { applySpacingStyles } from '../styling/spacing-resolver'
10
+ import { buildFinalClassName, processComponentStyle } from '../styling/style-processor'
11
+ import { substitutePropsThemeTokens } from '../styling/theme-tokens'
12
+ import {
13
+ extractTranslationKeyFromContent,
14
+ findFirstTranslationKey,
15
+ getTranslationData,
16
+ substitutePropsTranslationTokens,
17
+ } from '../translations/translation-handler'
18
+ import { buildElementProps } from './props-builder'
19
+ import type { Languages } from '@/domain/models/app/languages'
20
+ import type { Interactions } from '@/domain/models/app/page/common/interactions/interactions'
21
+ import type { Component } from '@/domain/models/app/page/sections'
22
+ import type { Theme } from '@/domain/models/app/theme'
23
+ import type { ReactElement } from 'react'
24
+
25
+ /**
26
+ * Configuration for building component props
27
+ */
28
+ export type ComponentPropsConfig = {
29
+ readonly type: string
30
+ readonly props: Record<string, unknown> | undefined
31
+ readonly children: ReadonlyArray<Component | string> | undefined
32
+ readonly content: string | undefined
33
+ readonly componentName: string | undefined
34
+ readonly componentInstanceIndex: number | undefined
35
+ readonly theme: Theme | undefined
36
+ readonly languages: Languages | undefined
37
+ readonly currentLang: string | undefined
38
+ readonly childIndex: number | undefined
39
+ readonly interactions: Interactions | undefined
40
+ }
41
+
42
+ /**
43
+ * Result of component props building
44
+ */
45
+ export type ComponentPropsResult = {
46
+ readonly elementProps: Record<string, unknown>
47
+ readonly elementPropsWithSpacing: Record<string, unknown>
48
+ readonly renderedChildren: ReadonlyArray<ReactElement | string | null>
49
+ }
50
+
51
+ /**
52
+ * Props configuration for component rendering
53
+ */
54
+ export type RenderPropsConfig = {
55
+ readonly components?: unknown
56
+ readonly theme?: Theme
57
+ readonly languages?: Languages
58
+ readonly currentLang?: string
59
+ readonly componentInstanceIndex?: number
60
+ }
61
+
62
+ /**
63
+ * Applies token substitutions to component props
64
+ *
65
+ * @param props - Original props
66
+ * @param currentLang - Current language
67
+ * @param languages - Languages configuration
68
+ * @param theme - Theme configuration
69
+ * @returns Props with all tokens substituted
70
+ */
71
+ function applyTokenSubstitutions(
72
+ props: Record<string, unknown> | undefined,
73
+ currentLang: string | undefined,
74
+ languages: Languages | undefined,
75
+ theme: Theme | undefined
76
+ ): Record<string, unknown> | undefined {
77
+ // Translation token substitution (must happen before theme tokens)
78
+ const translationSubstitutedProps = substitutePropsTranslationTokens(
79
+ props,
80
+ currentLang,
81
+ languages
82
+ )
83
+ // Theme token substitution
84
+ return substitutePropsThemeTokens(translationSubstitutedProps, theme)
85
+ }
86
+
87
+ /**
88
+ * Prepares processed component values (tokens, translations, styles, className)
89
+ *
90
+ * @param config - Component props configuration
91
+ * @returns Processed intermediate values
92
+ */
93
+ function prepareProcessedValues(config: ComponentPropsConfig) {
94
+ const { type, props, children, content, currentLang, languages, theme, interactions } = config
95
+
96
+ const substitutedProps = applyTokenSubstitutions(props, currentLang, languages, theme)
97
+ // Check both children and content for translation keys
98
+ const firstTranslationKey =
99
+ findFirstTranslationKey(children) || extractTranslationKeyFromContent(content)
100
+ const translationData = getTranslationData(firstTranslationKey, languages)
101
+ const styleWithShadow = processComponentStyle(
102
+ type,
103
+ substitutedProps?.style,
104
+ theme,
105
+ substitutedProps
106
+ )
107
+ const hoverTransitionStyles = buildHoverTransitionStyles(interactions?.hover)
108
+ const finalClassName = buildFinalClassName({
109
+ type,
110
+ className: substitutedProps?.className,
111
+ substitutedProps,
112
+ interactions,
113
+ })
114
+
115
+ // Merge hover transition styles with existing styles
116
+ const styleWithHover = hoverTransitionStyles
117
+ ? { ...styleWithShadow, ...hoverTransitionStyles }
118
+ : styleWithShadow
119
+
120
+ return {
121
+ substitutedProps,
122
+ firstTranslationKey,
123
+ translationData,
124
+ styleWithShadow: styleWithHover,
125
+ finalClassName,
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Builds complete component props with all transformations applied
131
+ *
132
+ * Orchestrates: token substitution, translation handling, style processing,
133
+ * className finalization, element props building, and spacing styles application.
134
+ *
135
+ * @param config - Component props configuration
136
+ * @returns Complete element props with spacing
137
+ */
138
+ export function buildComponentProps(config: ComponentPropsConfig): {
139
+ readonly substitutedProps: Record<string, unknown> | undefined
140
+ readonly firstTranslationKey: string | undefined
141
+ readonly translationData: Record<string, string> | undefined
142
+ readonly styleWithShadow: Record<string, unknown> | undefined
143
+ readonly finalClassName: string | undefined
144
+ readonly elementProps: Record<string, unknown>
145
+ readonly elementPropsWithSpacing: Record<string, unknown>
146
+ } {
147
+ const { type, content, children, componentName, componentInstanceIndex, theme, childIndex } =
148
+ config
149
+
150
+ const {
151
+ substitutedProps,
152
+ firstTranslationKey,
153
+ translationData,
154
+ styleWithShadow,
155
+ finalClassName,
156
+ } = prepareProcessedValues(config)
157
+
158
+ const elementProps = buildElementProps({
159
+ type,
160
+ substitutedProps,
161
+ finalClassName,
162
+ styleWithShadow,
163
+ componentName,
164
+ componentInstanceIndex,
165
+ firstTranslationKey,
166
+ translationData,
167
+ hasContent: Boolean(content || children?.length),
168
+ hasChildren: Boolean(children?.length),
169
+ theme,
170
+ childIndex,
171
+ interactions: config.interactions,
172
+ })
173
+
174
+ return {
175
+ substitutedProps,
176
+ firstTranslationKey,
177
+ translationData,
178
+ styleWithShadow,
179
+ finalClassName,
180
+ elementProps,
181
+ elementPropsWithSpacing: applySpacingStyles(type, elementProps, theme),
182
+ }
183
+ }