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