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,14 @@
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 { createTaggedError } from '@/domain/errors/create-tagged-error'
9
+
10
+ /**
11
+ * Error class for app validation failures
12
+ */
13
+ export const AppValidationError = createTaggedError('AppValidationError')
14
+ export type AppValidationError = InstanceType<typeof AppValidationError>
@@ -0,0 +1,16 @@
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 { Data } from 'effect'
9
+
10
+ /**
11
+ * Error class for static site generation failures
12
+ */
13
+ export class StaticGenerationError extends Data.TaggedError('StaticGenerationError')<{
14
+ readonly message: string
15
+ readonly cause?: unknown
16
+ }> {}
@@ -0,0 +1,127 @@
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 { FaviconSet } from '@/domain/models/app/page/meta/favicon-set'
9
+ import type { FaviconsConfig } from '@/domain/models/app/page/meta/favicons-config'
10
+
11
+ /**
12
+ * Normalizes a favicon path to ensure it starts with './'
13
+ *
14
+ * @param href - Favicon path (with or without './' prefix)
15
+ * @returns Path guaranteed to start with './'
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * normalizeFaviconPath('/icon.svg') // './icon.svg'
20
+ * normalizeFaviconPath('./icon.svg') // './icon.svg'
21
+ * normalizeFaviconPath('icon.svg') // './icon.svg'
22
+ * ```
23
+ */
24
+ function normalizeFaviconPath(href: string): string {
25
+ return href.startsWith('./') ? href : `.${href}`
26
+ }
27
+
28
+ /**
29
+ * Transforms FaviconsConfig (object format) to FaviconSet (array format)
30
+ *
31
+ * This function converts the simplified object-based configuration format
32
+ * into the array-based FaviconSet format expected by the rendering components.
33
+ *
34
+ * Transformation rules:
35
+ * - icon → { rel: 'icon', type: 'image/svg+xml', href: icon }
36
+ * - appleTouchIcon → { rel: 'apple-touch-icon', href: appleTouchIcon }
37
+ * - sizes → { rel: 'icon', type: 'image/png', sizes: size, href: href }
38
+ *
39
+ * @param config - FaviconsConfig object with named properties
40
+ * @returns FaviconSet array with favicon items
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const config = {
45
+ * icon: '/icon.svg',
46
+ * appleTouchIcon: '/apple-touch-icon.png',
47
+ * sizes: [
48
+ * { size: '32x32', href: '/favicon-32x32.png' },
49
+ * { size: '16x16', href: '/favicon-16x16.png' }
50
+ * ]
51
+ * }
52
+ *
53
+ * const faviconSet = transformFaviconsConfigToSet(config)
54
+ * // [
55
+ * // { rel: 'icon', type: 'image/svg+xml', href: './icon.svg' },
56
+ * // { rel: 'apple-touch-icon', href: './apple-touch-icon.png' },
57
+ * // { rel: 'icon', type: 'image/png', sizes: '32x32', href: './favicon-32x32.png' },
58
+ * // { rel: 'icon', type: 'image/png', sizes: '16x16', href: './favicon-16x16.png' }
59
+ * // ]
60
+ * ```
61
+ */
62
+ export function transformFaviconsConfigToSet(config: FaviconsConfig): FaviconSet {
63
+ // Transform icon
64
+ const iconItems = config.icon
65
+ ? [
66
+ {
67
+ rel: 'icon' as const,
68
+ type: 'image/svg+xml' as const,
69
+ href: normalizeFaviconPath(config.icon),
70
+ },
71
+ ]
72
+ : []
73
+
74
+ // Transform appleTouchIcon
75
+ const appleTouchIconItems = config.appleTouchIcon
76
+ ? [
77
+ {
78
+ rel: 'apple-touch-icon' as const,
79
+ href: normalizeFaviconPath(config.appleTouchIcon),
80
+ },
81
+ ]
82
+ : []
83
+
84
+ // Transform sizes
85
+ const sizeItems =
86
+ config.sizes?.map((sizeItem) => ({
87
+ rel: 'icon' as const,
88
+ type: 'image/png' as const,
89
+ sizes: sizeItem.size,
90
+ href: normalizeFaviconPath(sizeItem.href),
91
+ })) ?? []
92
+
93
+ return [...iconItems, ...appleTouchIconItems, ...sizeItems]
94
+ }
95
+
96
+ /**
97
+ * Type guard to check if favicons is FaviconsConfig (object format)
98
+ */
99
+ export function isFaviconsConfig(
100
+ favicons: FaviconSet | FaviconsConfig | undefined
101
+ ): favicons is FaviconsConfig {
102
+ if (!favicons) return false
103
+ return (
104
+ !Array.isArray(favicons) &&
105
+ typeof favicons === 'object' &&
106
+ ('icon' in favicons || 'appleTouchIcon' in favicons || 'sizes' in favicons)
107
+ )
108
+ }
109
+
110
+ /**
111
+ * Normalizes favicons to FaviconSet array format
112
+ *
113
+ * Accepts both FaviconSet (array) and FaviconsConfig (object) formats,
114
+ * returning a normalized FaviconSet array.
115
+ *
116
+ * @param favicons - Favicons in either format
117
+ * @returns FaviconSet array or undefined
118
+ */
119
+ export function normalizeFavicons(
120
+ favicons: FaviconSet | FaviconsConfig | undefined
121
+ ): FaviconSet | undefined {
122
+ if (!favicons) return undefined
123
+ if (isFaviconsConfig(favicons)) {
124
+ return transformFaviconsConfigToSet(favicons)
125
+ }
126
+ return favicons as FaviconSet
127
+ }
@@ -0,0 +1,27 @@
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 { Effect } from 'effect'
9
+ import type { Hono } from 'hono'
10
+
11
+ /**
12
+ * Running server instance with stop capability
13
+ *
14
+ * This represents a domain concept of a running web server
15
+ * that can be controlled (stopped) through Effect operations.
16
+ *
17
+ * The actual server implementation (Bun.serve) is hidden
18
+ * behind this interface to maintain layer separation.
19
+ *
20
+ * The Hono app is exposed for static site generation (SSG) purposes.
21
+ */
22
+ export interface ServerInstance {
23
+ readonly server: ReturnType<typeof Bun.serve>
24
+ readonly url: string
25
+ readonly stop: Effect.Effect<void>
26
+ readonly app: Readonly<Hono>
27
+ }
@@ -0,0 +1,36 @@
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
+ * Minimal user metadata embedded in domain records
10
+ *
11
+ * Represents the common shape returned by user-joined queries
12
+ * (activity logs, comments, activity history). Defined at the
13
+ * application boundary so both application and infrastructure
14
+ * layers can reference the same contract.
15
+ *
16
+ * Variants:
17
+ * - `UserMetadata` — core fields (id, name, email)
18
+ * - `UserMetadataWithImage` — adds optional image (comments, activity history)
19
+ */
20
+ export interface UserMetadata {
21
+ readonly id: string
22
+ readonly name: string
23
+ readonly email: string
24
+ }
25
+
26
+ export interface UserMetadataWithImage extends UserMetadata {
27
+ readonly image: string | null | undefined
28
+ }
29
+
30
+ /**
31
+ * Variant with image typed as `string | undefined` only (no null).
32
+ * Used by comment queries where infrastructure converts null → undefined.
33
+ */
34
+ export interface UserMetadataWithOptionalImage extends UserMetadata {
35
+ readonly image: string | undefined
36
+ }
@@ -0,0 +1,34 @@
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
+ * User session interface for application layer
10
+ *
11
+ * Structurally compatible with Better Auth's Session type
12
+ * so infrastructure implementations can accept it without conversion.
13
+ * Application layer uses this instead of importing from infrastructure.
14
+ */
15
+ export interface UserSession {
16
+ readonly id: string
17
+ readonly userId: string
18
+ readonly token: string
19
+ readonly expiresAt: Date
20
+ readonly createdAt: Date
21
+ readonly updatedAt: Date
22
+ readonly ipAddress: string | null
23
+ readonly userAgent: string | null
24
+ readonly impersonatedBy: string | null
25
+ }
26
+
27
+ /**
28
+ * Session type alias for backward compatibility
29
+ *
30
+ * Allows presentation layer to import Session from the application
31
+ * boundary instead of reaching into infrastructure. Structurally
32
+ * compatible with the Drizzle-inferred Session type from Better Auth.
33
+ */
34
+ export type Session = UserSession
@@ -0,0 +1,68 @@
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 { Context, Data } from 'effect'
9
+ import type { UserMetadata } from '@/application/ports/models/user-metadata'
10
+ import type { Effect } from 'effect'
11
+
12
+ /**
13
+ * Activity Log record type (port-level definition)
14
+ *
15
+ * Structurally compatible with the Drizzle schema inference.
16
+ * Defined here to avoid application→infrastructure dependency.
17
+ */
18
+ export interface ActivityLog {
19
+ readonly id: string
20
+ readonly createdAt: Date
21
+ readonly userId: string | null
22
+ readonly sessionId: string | null
23
+ readonly action: 'create' | 'update' | 'delete' | 'restore'
24
+ readonly tableName: string
25
+ readonly tableId: string | null
26
+ readonly recordId: string
27
+ readonly changes: {
28
+ readonly before?: Record<string, unknown>
29
+ readonly after?: Record<string, unknown>
30
+ } | null
31
+ readonly ipAddress: string | null
32
+ readonly userAgent: string | null
33
+ readonly user?: UserMetadata | null | undefined
34
+ }
35
+
36
+ /**
37
+ * Database error for activity log operations
38
+ */
39
+ export class ActivityLogDatabaseError extends Data.TaggedError('ActivityLogDatabaseError')<{
40
+ readonly cause: unknown
41
+ }> {}
42
+
43
+ /**
44
+ * Activity Log Repository Port
45
+ *
46
+ * Provides type-safe database operations for activity logs.
47
+ * Implementation lives in infrastructure layer (activity-log-repository-live.ts).
48
+ */
49
+ export class ActivityLogRepository extends Context.Tag('ActivityLogRepository')<
50
+ ActivityLogRepository,
51
+ {
52
+ readonly listAll: () => Effect.Effect<readonly ActivityLog[], ActivityLogDatabaseError>
53
+ readonly create: (log: {
54
+ readonly userId: string
55
+ readonly action: 'create' | 'update' | 'delete' | 'restore'
56
+ readonly tableName: string
57
+ readonly tableId: string
58
+ readonly recordId: string
59
+ readonly changes: {
60
+ readonly before?: Record<string, unknown>
61
+ readonly after?: Record<string, unknown>
62
+ }
63
+ readonly sessionId?: string
64
+ readonly ipAddress?: string
65
+ readonly userAgent?: string
66
+ }) => Effect.Effect<ActivityLog, ActivityLogDatabaseError>
67
+ }
68
+ >() {}
@@ -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
+ import { Context } from 'effect'
9
+ import type { UserMetadataWithImage } from '@/application/ports/models/user-metadata'
10
+ import type { UserSession } from '@/application/ports/models/user-session'
11
+ import type { SessionContextError } from '@/domain/errors'
12
+ import type { Effect } from 'effect'
13
+
14
+ /**
15
+ * Activity history entry with user metadata
16
+ */
17
+ export interface ActivityHistoryEntry {
18
+ readonly action: string
19
+ readonly createdAt: Date
20
+ readonly changes: unknown
21
+ readonly user: UserMetadataWithImage | undefined
22
+ }
23
+
24
+ /**
25
+ * Activity Repository Port
26
+ */
27
+ export class ActivityRepository extends Context.Tag('ActivityRepository')<
28
+ ActivityRepository,
29
+ {
30
+ readonly getRecordHistory: (config: {
31
+ readonly session: Readonly<UserSession>
32
+ readonly tableName: string
33
+ readonly recordId: string
34
+ readonly limit?: number
35
+ readonly offset?: number
36
+ }) => Effect.Effect<
37
+ {
38
+ readonly entries: readonly ActivityHistoryEntry[]
39
+ readonly total: number
40
+ },
41
+ SessionContextError
42
+ >
43
+ readonly checkRecordExists: (config: {
44
+ readonly session: Readonly<UserSession>
45
+ readonly tableName: string
46
+ readonly recordId: string
47
+ }) => Effect.Effect<boolean, SessionContextError>
48
+ }
49
+ >() {}
@@ -0,0 +1,164 @@
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 { Context, Data } from 'effect'
9
+ import type { Effect } from 'effect'
10
+
11
+ // ============================================================================
12
+ // Port-level types (avoid infrastructure dependency)
13
+ // ============================================================================
14
+
15
+ /**
16
+ * Page view input for recording a new event
17
+ */
18
+ export interface PageViewInput {
19
+ readonly appName: string
20
+ readonly pagePath: string
21
+ readonly pageTitle?: string
22
+ readonly visitorHash: string
23
+ readonly sessionHash: string
24
+ readonly isEntrance: boolean
25
+ readonly referrerUrl?: string
26
+ readonly referrerDomain?: string
27
+ readonly utmSource?: string
28
+ readonly utmMedium?: string
29
+ readonly utmCampaign?: string
30
+ readonly utmContent?: string
31
+ readonly utmTerm?: string
32
+ readonly deviceType?: string
33
+ readonly browserName?: string
34
+ readonly osName?: string
35
+ readonly language?: string
36
+ readonly screenWidth?: number
37
+ readonly screenHeight?: number
38
+ }
39
+
40
+ /**
41
+ * Query parameters for analytics data retrieval
42
+ */
43
+ export interface AnalyticsQueryParams {
44
+ readonly appName: string
45
+ readonly from: Date
46
+ readonly to: Date
47
+ readonly granularity: 'hour' | 'day' | 'week' | 'month'
48
+ }
49
+
50
+ /**
51
+ * Time series data point
52
+ */
53
+ export interface TimeSeriesPoint {
54
+ readonly period: string
55
+ readonly pageViews: number
56
+ readonly uniqueVisitors: number
57
+ readonly sessions: number
58
+ }
59
+
60
+ /**
61
+ * Summary metrics
62
+ */
63
+ export interface AnalyticsSummary {
64
+ readonly pageViews: number
65
+ readonly uniqueVisitors: number
66
+ readonly sessions: number
67
+ }
68
+
69
+ /**
70
+ * Top page entry
71
+ */
72
+ export interface TopPage {
73
+ readonly path: string
74
+ readonly pageViews: number
75
+ readonly uniqueVisitors: number
76
+ }
77
+
78
+ /**
79
+ * Top referrer entry
80
+ */
81
+ export interface TopReferrer {
82
+ readonly domain: string | null
83
+ readonly pageViews: number
84
+ readonly uniqueVisitors: number
85
+ }
86
+
87
+ /**
88
+ * Breakdown entry (device type, browser, OS)
89
+ */
90
+ export interface BreakdownEntry {
91
+ readonly name: string
92
+ readonly count: number
93
+ readonly percentage: number
94
+ }
95
+
96
+ /**
97
+ * Device breakdown result
98
+ */
99
+ export interface DeviceBreakdown {
100
+ readonly deviceTypes: readonly BreakdownEntry[]
101
+ readonly browsers: readonly BreakdownEntry[]
102
+ readonly operatingSystems: readonly BreakdownEntry[]
103
+ }
104
+
105
+ /**
106
+ * Campaign entry
107
+ */
108
+ export interface CampaignEntry {
109
+ readonly source: string | null
110
+ readonly medium: string | null
111
+ readonly campaign: string | null
112
+ readonly pageViews: number
113
+ readonly uniqueVisitors: number
114
+ }
115
+
116
+ // ============================================================================
117
+ // Error type
118
+ // ============================================================================
119
+
120
+ /**
121
+ * Database error for analytics operations
122
+ */
123
+ export class AnalyticsDatabaseError extends Data.TaggedError('AnalyticsDatabaseError')<{
124
+ readonly cause: unknown
125
+ }> {}
126
+
127
+ // ============================================================================
128
+ // Repository port
129
+ // ============================================================================
130
+
131
+ /**
132
+ * Analytics Repository Port
133
+ *
134
+ * Provides type-safe database operations for analytics page views.
135
+ * Implementation lives in infrastructure layer (analytics-repository-live.ts).
136
+ */
137
+ export class AnalyticsRepository extends Context.Tag('AnalyticsRepository')<
138
+ AnalyticsRepository,
139
+ {
140
+ readonly recordPageView: (input: PageViewInput) => Effect.Effect<void, AnalyticsDatabaseError>
141
+ readonly getTimeSeries: (
142
+ params: AnalyticsQueryParams
143
+ ) => Effect.Effect<readonly TimeSeriesPoint[], AnalyticsDatabaseError>
144
+ readonly getSummary: (
145
+ params: AnalyticsQueryParams
146
+ ) => Effect.Effect<AnalyticsSummary, AnalyticsDatabaseError>
147
+ readonly getTopPages: (
148
+ params: AnalyticsQueryParams
149
+ ) => Effect.Effect<readonly TopPage[], AnalyticsDatabaseError>
150
+ readonly getTopReferrers: (
151
+ params: AnalyticsQueryParams
152
+ ) => Effect.Effect<readonly TopReferrer[], AnalyticsDatabaseError>
153
+ readonly getDevices: (
154
+ params: AnalyticsQueryParams
155
+ ) => Effect.Effect<DeviceBreakdown, AnalyticsDatabaseError>
156
+ readonly getCampaigns: (
157
+ params: AnalyticsQueryParams
158
+ ) => Effect.Effect<readonly CampaignEntry[], AnalyticsDatabaseError>
159
+ readonly deleteOlderThan: (
160
+ appName: string,
161
+ cutoff: Date
162
+ ) => Effect.Effect<number, AnalyticsDatabaseError>
163
+ }
164
+ >() {}
@@ -0,0 +1,33 @@
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 { Context, Data } from 'effect'
9
+ import type { Effect } from 'effect'
10
+
11
+ /**
12
+ * Database error for auth operations (users table)
13
+ */
14
+ export class AuthDatabaseError extends Data.TaggedError('AuthDatabaseError')<{
15
+ readonly cause: unknown
16
+ }> {}
17
+
18
+ /**
19
+ * Auth Repository Port
20
+ *
21
+ * Provides type-safe database operations for authentication-related
22
+ * user management (email verification, role lookup).
23
+ * Both methods operate on the Better Auth `users` table.
24
+ *
25
+ * Implementation lives in infrastructure layer (auth-repository-live.ts).
26
+ */
27
+ export class AuthRepository extends Context.Tag('AuthRepository')<
28
+ AuthRepository,
29
+ {
30
+ readonly verifyUserEmail: (userId: string) => Effect.Effect<void, AuthDatabaseError>
31
+ readonly getUserRole: (userId: string) => Effect.Effect<string | undefined, AuthDatabaseError>
32
+ }
33
+ >() {}
@@ -0,0 +1,86 @@
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 { Context } from 'effect'
9
+ import type { UserSession } from '@/application/ports/models/user-session'
10
+ import type { SessionContextError, ValidationError } from '@/domain/errors'
11
+ import type { Effect } from 'effect'
12
+
13
+ /**
14
+ * Batch validation error interface
15
+ *
16
+ * Structurally compatible with infrastructure's BatchValidationError
17
+ * (Data.TaggedError). Defined here so application layer doesn't need
18
+ * to import from infrastructure.
19
+ */
20
+ export interface BatchValidationError extends Error {
21
+ readonly _tag: 'BatchValidationError'
22
+ readonly message: string
23
+ readonly details?: readonly string[]
24
+ }
25
+
26
+ /**
27
+ * Upsert operation result
28
+ */
29
+ export interface UpsertResult {
30
+ readonly records: readonly Record<string, unknown>[]
31
+ readonly created: number
32
+ readonly updated: number
33
+ }
34
+
35
+ /**
36
+ * Batch Repository port for batch operations
37
+ *
38
+ * Defines the contract for bulk create, update, delete, restore, and upsert.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const program = Effect.gen(function* () {
43
+ * const batch = yield* BatchRepository
44
+ * const result = yield* batch.batchCreate(session, 'users', records)
45
+ * })
46
+ * ```
47
+ */
48
+ export class BatchRepository extends Context.Tag('BatchRepository')<
49
+ BatchRepository,
50
+ {
51
+ readonly batchCreate: (
52
+ session: Readonly<UserSession>,
53
+ tableName: string,
54
+ recordsData: readonly Record<string, unknown>[]
55
+ ) => Effect.Effect<readonly Record<string, unknown>[], SessionContextError | ValidationError>
56
+
57
+ readonly batchUpdate: (
58
+ session: Readonly<UserSession>,
59
+ tableName: string,
60
+ updates: readonly {
61
+ readonly id: string
62
+ readonly fields?: Record<string, unknown>
63
+ }[]
64
+ ) => Effect.Effect<readonly Record<string, unknown>[], SessionContextError | ValidationError>
65
+
66
+ readonly batchDelete: (
67
+ session: Readonly<UserSession>,
68
+ tableName: string,
69
+ recordIds: readonly string[],
70
+ permanent?: boolean
71
+ ) => Effect.Effect<number, SessionContextError>
72
+
73
+ readonly batchRestore: (
74
+ session: Readonly<UserSession>,
75
+ tableName: string,
76
+ recordIds: readonly string[]
77
+ ) => Effect.Effect<number, SessionContextError>
78
+
79
+ readonly upsert: (
80
+ session: Readonly<UserSession>,
81
+ tableName: string,
82
+ recordsData: readonly Record<string, unknown>[],
83
+ fieldsToMergeOn: readonly string[]
84
+ ) => Effect.Effect<UpsertResult, SessionContextError | BatchValidationError | ValidationError>
85
+ }
86
+ >() {}