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,247 @@
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 { SchemaOrgContext, schemaType } from './common-fields'
10
+ import { PostalAddressSchema } from './postal-address'
11
+
12
+ /**
13
+ * Day of week for opening hours
14
+ *
15
+ * 7 days of the week (full names, capitalized).
16
+ * Used in openingHoursSpecification to specify which days hours apply to.
17
+ */
18
+ export const DayOfWeekSchema = Schema.Literal(
19
+ 'Monday',
20
+ 'Tuesday',
21
+ 'Wednesday',
22
+ 'Thursday',
23
+ 'Friday',
24
+ 'Saturday',
25
+ 'Sunday'
26
+ ).annotations({
27
+ description: 'Day of the week',
28
+ })
29
+
30
+ /**
31
+ * Time in HH:MM format (24-hour)
32
+ *
33
+ * Pattern: ^[0-9]{2}:[0-9]{2}$ (e.g., "09:00", "18:30", "23:59")
34
+ * Examples: "09:00" (9 AM), "13:30" (1:30 PM), "18:00" (6 PM)
35
+ */
36
+ export const TimeSchema = Schema.String.pipe(
37
+ Schema.pattern(/^[0-9]{2}:[0-9]{2}$/, {
38
+ message: () => 'Time must be in HH:MM format (24-hour, e.g., 09:00, 18:30, 23:59)',
39
+ })
40
+ ).annotations({
41
+ description: 'Time in HH:MM format',
42
+ examples: ['09:00', '18:00'],
43
+ })
44
+
45
+ /**
46
+ * Opening hours specification
47
+ *
48
+ * Defines opening hours for specific days of the week.
49
+ * - @type: "OpeningHoursSpecification"
50
+ * - dayOfWeek: Array of days these hours apply to (e.g., ["Monday", "Tuesday", "Wednesday"])
51
+ * - opens: Opening time in HH:MM format (e.g., "09:00")
52
+ * - closes: Closing time in HH:MM format (e.g., "18:00")
53
+ */
54
+ export const OpeningHoursSpecificationSchema = Schema.Struct({
55
+ '@type': schemaType('OpeningHoursSpecification'),
56
+ dayOfWeek: Schema.optional(
57
+ Schema.Array(DayOfWeekSchema).annotations({
58
+ description: 'Days these hours apply to',
59
+ })
60
+ ),
61
+ opens: Schema.optional(TimeSchema.annotations({ description: 'Opening time' })),
62
+ closes: Schema.optional(TimeSchema.annotations({ description: 'Closing time' })),
63
+ }).annotations({
64
+ description: 'Opening hours specification',
65
+ })
66
+
67
+ /**
68
+ * Geographic coordinates
69
+ *
70
+ * Latitude and longitude for precise map location.
71
+ * - @type: "GeoCoordinates"
72
+ * - latitude: Latitude as string (e.g., "48.5734", "-37.8136")
73
+ * - longitude: Longitude as string (e.g., "7.7521", "144.9631")
74
+ */
75
+ export const GeoCoordinatesSchema = Schema.Struct({
76
+ '@type': schemaType('GeoCoordinates'),
77
+ latitude: Schema.optional(
78
+ Schema.String.annotations({
79
+ description: 'Latitude',
80
+ })
81
+ ),
82
+ longitude: Schema.optional(
83
+ Schema.String.annotations({
84
+ description: 'Longitude',
85
+ })
86
+ ),
87
+ }).annotations({
88
+ description: 'Geographic coordinates',
89
+ })
90
+
91
+ /**
92
+ * Schema.org LocalBusiness structured data
93
+ *
94
+ * Represents a local business with physical location for local SEO and map display.
95
+ * Enables Google Business Profile rich results with map pins, directions, opening hours,
96
+ * and contact information directly in search results.
97
+ *
98
+ * Required properties:
99
+ * - @context: "https://schema.org" (Schema.org vocabulary)
100
+ * - @type: "LocalBusiness" (Schema.org type identifier)
101
+ * - name: Business name (e.g., "Joe's Pizza", "Acme Hardware Store")
102
+ *
103
+ * Optional properties:
104
+ * - description: Business description
105
+ * - url: Business website URL
106
+ * - logo: Business logo URL
107
+ * - image: Business image(s) - string or array (storefront, products, interior)
108
+ * - email: Contact email address
109
+ * - telephone: Contact phone number
110
+ * - priceRange: Price level indicator (e.g., "$", "$$", "$$$", "$$$$")
111
+ * - address: Physical address (PostalAddress object) - CRITICAL for local SEO
112
+ * - geo: Geographic coordinates (GeoCoordinates object) - enables map pin
113
+ * - sameAs: Array of social media profile URLs
114
+ * - openingHoursSpecification: Array of opening hours for each day/day range
115
+ *
116
+ * Local SEO impact:
117
+ * - **Map display**: Address + geo coordinates enable map pin in search results
118
+ * - **Directions**: "Get directions" button in search results
119
+ * - **Opening hours**: Shows current open/closed status and hours
120
+ * - **Local pack**: Appears in local 3-pack for "near me" searches
121
+ * - **Mobile optimization**: Click-to-call phone number, one-tap directions
122
+ * - **Rich snippets**: Business info shown prominently in search results
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const localBusiness = {
127
+ * "@context": "https://schema.org",
128
+ * "@type": "LocalBusiness",
129
+ * name: "Joe's Pizza",
130
+ * description: "Authentic Italian pizza restaurant",
131
+ * url: "https://joespizza.com",
132
+ * telephone: "+1-555-123-4567",
133
+ * priceRange: "$$",
134
+ * address: {
135
+ * "@type": "PostalAddress",
136
+ * streetAddress: "123 Main St",
137
+ * addressLocality: "Strasbourg",
138
+ * addressRegion: "Grand Est",
139
+ * postalCode: "67000",
140
+ * addressCountry: "FR"
141
+ * },
142
+ * geo: {
143
+ * "@type": "GeoCoordinates",
144
+ * latitude: "48.5734",
145
+ * longitude: "7.7521"
146
+ * },
147
+ * openingHoursSpecification: [
148
+ * {
149
+ * "@type": "OpeningHoursSpecification",
150
+ * dayOfWeek: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
151
+ * opens: "11:00",
152
+ * closes: "22:00"
153
+ * },
154
+ * {
155
+ * "@type": "OpeningHoursSpecification",
156
+ * dayOfWeek: ["Saturday", "Sunday"],
157
+ * opens: "12:00",
158
+ * closes: "23:00"
159
+ * }
160
+ * ]
161
+ * }
162
+ * ```
163
+ *
164
+ * @see specs/app/pages/meta/structured-data/local-business.schema.json
165
+ */
166
+ export const LocalBusinessSchema = Schema.Struct({
167
+ '@context': SchemaOrgContext,
168
+ '@type': schemaType('LocalBusiness'),
169
+ name: Schema.String.annotations({
170
+ description: 'Business name',
171
+ }),
172
+ description: Schema.optional(
173
+ Schema.String.annotations({
174
+ description: 'Business description',
175
+ })
176
+ ),
177
+ url: Schema.optional(
178
+ Schema.String.annotations({
179
+ description: 'Business website URL',
180
+ format: 'uri',
181
+ })
182
+ ),
183
+ logo: Schema.optional(
184
+ Schema.String.annotations({
185
+ description: 'Business logo URL',
186
+ format: 'uri',
187
+ })
188
+ ),
189
+ image: Schema.optional(
190
+ Schema.Union(
191
+ Schema.String.annotations({
192
+ description: 'Business image URL',
193
+ format: 'uri',
194
+ }),
195
+ Schema.Array(
196
+ Schema.String.annotations({
197
+ description: 'Business image URL',
198
+ format: 'uri',
199
+ })
200
+ )
201
+ ).annotations({
202
+ description: 'Business image(s)',
203
+ })
204
+ ),
205
+ email: Schema.optional(
206
+ Schema.String.annotations({
207
+ description: 'Contact email',
208
+ format: 'email',
209
+ })
210
+ ),
211
+ telephone: Schema.optional(
212
+ Schema.String.annotations({
213
+ description: 'Contact phone number',
214
+ })
215
+ ),
216
+ priceRange: Schema.optional(
217
+ Schema.String.annotations({
218
+ description: "Price range (e.g., '$-$$$$')",
219
+ })
220
+ ),
221
+ address: Schema.optional(PostalAddressSchema),
222
+ geo: Schema.optional(GeoCoordinatesSchema),
223
+ sameAs: Schema.optional(
224
+ Schema.Array(
225
+ Schema.String.annotations({
226
+ description: 'Social media profile URL',
227
+ format: 'uri',
228
+ })
229
+ ).annotations({
230
+ description: 'Social media profile URLs',
231
+ })
232
+ ),
233
+ openingHoursSpecification: Schema.optional(
234
+ Schema.Array(OpeningHoursSpecificationSchema).annotations({
235
+ description: 'Opening hours specifications',
236
+ })
237
+ ),
238
+ }).annotations({
239
+ title: 'Local Business Schema',
240
+ description: 'Schema.org LocalBusiness structured data',
241
+ })
242
+
243
+ export type DayOfWeek = Schema.Schema.Type<typeof DayOfWeekSchema>
244
+ export type Time = Schema.Schema.Type<typeof TimeSchema>
245
+ export type OpeningHoursSpecification = Schema.Schema.Type<typeof OpeningHoursSpecificationSchema>
246
+ export type GeoCoordinates = Schema.Schema.Type<typeof GeoCoordinatesSchema>
247
+ export type LocalBusiness = Schema.Schema.Type<typeof LocalBusinessSchema>
@@ -0,0 +1,171 @@
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 { SchemaOrgContext, schemaType } from './common-fields'
10
+ import { EducationEventSchema } from './education-event'
11
+ import { PostalAddressSchema } from './postal-address'
12
+
13
+ /**
14
+ * Schema.org Organization structured data
15
+ *
16
+ * Represents a company, business, or organization for knowledge graphs and rich results.
17
+ * Enables Google Knowledge Graph panel with company information, logo, and social profiles.
18
+ *
19
+ * Required properties:
20
+ * - @context: "https://schema.org" (Schema.org vocabulary)
21
+ * - @type: "Organization" (Schema.org type identifier)
22
+ * - name: Organization name (e.g., "Acme Inc", "Google")
23
+ *
24
+ * Optional properties:
25
+ * - description: Organization description/tagline
26
+ * - url: Organization website URL
27
+ * - logo: Organization logo URL (shown in Knowledge Graph)
28
+ * - image: Organization image(s) - string or array (photos, headquarters, products)
29
+ * - email: Contact email address
30
+ * - telephone: Contact phone number
31
+ * - address: Mailing address (PostalAddress object)
32
+ * - sameAs: Array of social media profile URLs (Facebook, Twitter, LinkedIn, etc.)
33
+ * - founder: Founder name
34
+ * - foundingDate: Date organization was founded (YYYY-MM-DD format)
35
+ * - employees: Number of employees (integer)
36
+ * - event: Associated event hosted or organized by the organization (EducationEvent object)
37
+ *
38
+ * Common use cases:
39
+ * - **Knowledge Graph**: Company information panel in Google search results
40
+ * - **Publisher attribution**: Link articles to publishing organization
41
+ * - **Brand identity**: Establish company presence across search results
42
+ * - **Social verification**: Link organization to official social profiles
43
+ *
44
+ * SEO impact:
45
+ * - **Knowledge Graph panel**: Rich company information panel in search results (right side)
46
+ * - **Logo display**: Organization logo shown in search results and Knowledge Graph
47
+ * - **Social profiles**: sameAs links verify official social media accounts
48
+ * - **Brand search**: Improves brand search results with structured information
49
+ * - **Publisher credibility**: Used in Article schema for publisher attribution
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const organization = {
54
+ * "@context": "https://schema.org",
55
+ * "@type": "Organization",
56
+ * name: "Acme Inc",
57
+ * description: "Leading provider of business software solutions",
58
+ * url: "https://acme.com",
59
+ * logo: "https://acme.com/logo.png",
60
+ * email: "contact@acme.com",
61
+ * telephone: "+1-555-123-4567",
62
+ * address: {
63
+ * "@type": "PostalAddress",
64
+ * streetAddress: "123 Main St",
65
+ * addressLocality: "San Francisco",
66
+ * addressRegion: "CA",
67
+ * postalCode: "94105",
68
+ * addressCountry: "US"
69
+ * },
70
+ * sameAs: [
71
+ * "https://facebook.com/acmeinc",
72
+ * "https://twitter.com/acmeinc",
73
+ * "https://linkedin.com/company/acmeinc"
74
+ * ],
75
+ * founder: "Jane Doe",
76
+ * foundingDate: "2015-01-15",
77
+ * employees: 150
78
+ * }
79
+ * ```
80
+ *
81
+ * @see specs/app/pages/meta/structured-data/organization.schema.json
82
+ */
83
+ export const OrganizationSchema = Schema.Struct({
84
+ '@context': SchemaOrgContext,
85
+ '@type': schemaType('Organization'),
86
+ name: Schema.String.annotations({
87
+ description: 'Organization name',
88
+ }),
89
+ description: Schema.optional(
90
+ Schema.String.annotations({
91
+ description: 'Organization description',
92
+ })
93
+ ),
94
+ url: Schema.optional(
95
+ Schema.String.annotations({
96
+ description: 'Organization website URL',
97
+ format: 'uri',
98
+ })
99
+ ),
100
+ logo: Schema.optional(
101
+ Schema.String.annotations({
102
+ description: 'Organization logo URL',
103
+ format: 'uri',
104
+ })
105
+ ),
106
+ image: Schema.optional(
107
+ Schema.Union(
108
+ Schema.String.annotations({
109
+ description: 'Organization image URL',
110
+ format: 'uri',
111
+ }),
112
+ Schema.Array(
113
+ Schema.String.annotations({
114
+ description: 'Organization image URL',
115
+ format: 'uri',
116
+ })
117
+ )
118
+ ).annotations({
119
+ description: 'Organization image(s)',
120
+ })
121
+ ),
122
+ email: Schema.optional(
123
+ Schema.String.annotations({
124
+ description: 'Contact email',
125
+ format: 'email',
126
+ })
127
+ ),
128
+ telephone: Schema.optional(
129
+ Schema.String.annotations({
130
+ description: 'Contact phone number',
131
+ })
132
+ ),
133
+ address: Schema.optional(PostalAddressSchema),
134
+ sameAs: Schema.optional(
135
+ Schema.Array(
136
+ Schema.String.annotations({
137
+ description: 'Social media profile URL',
138
+ format: 'uri',
139
+ })
140
+ ).annotations({
141
+ description: 'Social media profile URLs',
142
+ examples: [['https://facebook.com/myorg', 'https://twitter.com/myorg']],
143
+ })
144
+ ),
145
+ founder: Schema.optional(
146
+ Schema.String.annotations({
147
+ description: 'Organization founder name',
148
+ })
149
+ ),
150
+ foundingDate: Schema.optional(
151
+ Schema.String.annotations({
152
+ description: 'Date organization was founded',
153
+ format: 'date',
154
+ })
155
+ ),
156
+ employees: Schema.optional(
157
+ Schema.Int.pipe(Schema.greaterThanOrEqualTo(1)).annotations({
158
+ description: 'Number of employees',
159
+ })
160
+ ),
161
+ event: Schema.optional(
162
+ EducationEventSchema.annotations({
163
+ description: 'Associated event hosted or organized by the organization',
164
+ })
165
+ ),
166
+ }).annotations({
167
+ title: 'Organization Schema',
168
+ description: 'Schema.org Organization structured data',
169
+ })
170
+
171
+ export type Organization = Schema.Schema.Type<typeof OrganizationSchema>
@@ -0,0 +1,138 @@
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 {
10
+ SchemaOrgContext,
11
+ SchemaOrgEmail,
12
+ SchemaOrgImageUrl,
13
+ SchemaOrgSameAs,
14
+ SchemaOrgTelephone,
15
+ SchemaOrgUrl,
16
+ schemaType,
17
+ } from './common-fields'
18
+ import { PostalAddressSchema } from './postal-address'
19
+
20
+ /**
21
+ * Organization reference for Person's employer
22
+ *
23
+ * Simplified Organization object with @type and name.
24
+ * Links person to their employer organization.
25
+ */
26
+ export const PersonWorksForSchema = Schema.Struct({
27
+ '@type': schemaType('Organization'),
28
+ name: Schema.optional(
29
+ Schema.String.annotations({
30
+ description: 'Organization name',
31
+ })
32
+ ),
33
+ }).annotations({
34
+ description: "Person's employer organization",
35
+ })
36
+
37
+ /**
38
+ * Schema.org Person structured data
39
+ *
40
+ * Represents an individual person with contact information, professional details,
41
+ * and social profiles. Used for author attribution, knowledge graphs, and notable persons.
42
+ *
43
+ * Required properties:
44
+ * - @context: "https://schema.org" (Schema.org vocabulary)
45
+ * - @type: "Person" (Schema.org type identifier)
46
+ * - name: Person's full name (e.g., "John Doe")
47
+ *
48
+ * Optional properties:
49
+ * - givenName: First name (e.g., "John")
50
+ * - familyName: Last name (e.g., "Doe")
51
+ * - email: Email address (format validated)
52
+ * - telephone: Phone number
53
+ * - url: Personal website or profile URL
54
+ * - image: Photo URL (headshot, profile picture)
55
+ * - jobTitle: Professional role (e.g., "CEO", "Software Engineer")
56
+ * - worksFor: Employer organization (Organization object with name)
57
+ * - sameAs: Array of social media profile URLs (LinkedIn, Twitter, GitHub, etc.)
58
+ * - address: Mailing address (PostalAddress object)
59
+ *
60
+ * Common use cases:
61
+ * - **Author attribution**: Link articles to specific authors (article.author)
62
+ * - **Knowledge Graph**: Enable Google Knowledge Graph panel for notable persons
63
+ * - **Contact information**: Provide structured contact details for business persons
64
+ * - **Social profiles**: Link person to their social media presence
65
+ *
66
+ * SEO impact:
67
+ * - Author attribution: Improves content credibility and E-E-A-T signals
68
+ * - Knowledge Graph: Notable persons get rich panel in search results
69
+ * - Social verification: sameAs links verify person's online identity
70
+ * - Professional context: jobTitle and worksFor provide professional context
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const person = {
75
+ * "@context": "https://schema.org",
76
+ * "@type": "Person",
77
+ * name: "John Doe",
78
+ * givenName: "John",
79
+ * familyName: "Doe",
80
+ * jobTitle: "CEO",
81
+ * email: "john@example.com",
82
+ * url: "https://johndoe.com",
83
+ * worksFor: {
84
+ * "@type": "Organization",
85
+ * name: "Acme Inc"
86
+ * },
87
+ * sameAs: [
88
+ * "https://linkedin.com/in/johndoe",
89
+ * "https://twitter.com/johndoe"
90
+ * ]
91
+ * }
92
+ * ```
93
+ *
94
+ * @see specs/app/pages/meta/structured-data/person.schema.json
95
+ */
96
+ export const PersonSchema = Schema.Struct({
97
+ '@context': SchemaOrgContext,
98
+ '@type': schemaType('Person'),
99
+ name: Schema.String.annotations({
100
+ description: "Person's full name",
101
+ }),
102
+ givenName: Schema.optional(
103
+ Schema.String.annotations({
104
+ description: 'First name',
105
+ })
106
+ ),
107
+ familyName: Schema.optional(
108
+ Schema.String.annotations({
109
+ description: 'Last name',
110
+ })
111
+ ),
112
+ email: Schema.optional(SchemaOrgEmail),
113
+ telephone: Schema.optional(SchemaOrgTelephone),
114
+ url: Schema.optional(
115
+ SchemaOrgUrl.annotations({
116
+ description: "Person's website or profile",
117
+ })
118
+ ),
119
+ image: Schema.optional(
120
+ SchemaOrgImageUrl.annotations({
121
+ description: "Person's photo URL",
122
+ })
123
+ ),
124
+ jobTitle: Schema.optional(
125
+ Schema.String.annotations({
126
+ description: 'Professional role',
127
+ })
128
+ ),
129
+ worksFor: Schema.optional(PersonWorksForSchema),
130
+ sameAs: Schema.optional(SchemaOrgSameAs),
131
+ address: Schema.optional(PostalAddressSchema),
132
+ }).annotations({
133
+ title: 'Person Schema',
134
+ description: 'Schema.org Person structured data',
135
+ })
136
+
137
+ export type PersonWorksFor = Schema.Schema.Type<typeof PersonWorksForSchema>
138
+ export type Person = Schema.Schema.Type<typeof PersonSchema>
@@ -0,0 +1,106 @@
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 { schemaType } from './common-fields'
10
+
11
+ /**
12
+ * ISO 3166-1 alpha-2 country code
13
+ *
14
+ * Two-letter country code format (uppercase).
15
+ * - Pattern: ^[A-Z]{2}$ (exactly 2 uppercase letters)
16
+ * - Examples: US (United States), FR (France), GB (United Kingdom), DE (Germany), JP (Japan)
17
+ * - Standard: ISO 3166-1 alpha-2 (international standard for country codes)
18
+ */
19
+ export const CountryCodeSchema = Schema.String.pipe(
20
+ Schema.pattern(/^[A-Z]{2}$/, {
21
+ message: () =>
22
+ 'Country code must be ISO 3166-1 alpha-2 format (2 uppercase letters, e.g., US, FR, GB, DE, JP)',
23
+ })
24
+ ).annotations({
25
+ description: 'ISO 3166-1 alpha-2 country code',
26
+ examples: ['US', 'FR', 'GB', 'DE'],
27
+ })
28
+
29
+ /**
30
+ * Schema.org PostalAddress structured data
31
+ *
32
+ * Represents a physical mailing address for organizations, businesses, and persons.
33
+ * Used in LocalBusiness, Organization, and Person schemas to provide location information
34
+ * for local SEO and map display in search results.
35
+ *
36
+ * Required properties:
37
+ * - @type: Must be "PostalAddress" (Schema.org type identifier)
38
+ *
39
+ * Optional properties:
40
+ * - streetAddress: Street address (e.g., "123 Main St", "45 Rue de la Paix")
41
+ * - addressLocality: City or locality name (e.g., "Strasbourg", "Paris", "San Francisco")
42
+ * - addressRegion: State, province, or region (e.g., "Grand Est", "California", "Ontario")
43
+ * - postalCode: Postal or ZIP code (e.g., "67000", "94105", "SW1A 1AA")
44
+ * - addressCountry: ISO 3166-1 alpha-2 country code (e.g., "FR", "US", "GB")
45
+ *
46
+ * Address format examples:
47
+ * - US: "123 Main St, San Francisco, CA 94105, US"
48
+ * - FR: "45 Rue de la Paix, Strasbourg, Grand Est 67000, FR"
49
+ * - GB: "10 Downing St, London, England SW1A 1AA, GB"
50
+ *
51
+ * Use cases:
52
+ * - **LocalBusiness**: Enable map display and directions in search results
53
+ * - **Organization**: Provide company headquarters address for Knowledge Graph
54
+ * - **Person**: Include contact address for notable persons
55
+ * - **EducationEvent**: Specify venue address for event listings
56
+ *
57
+ * SEO impact:
58
+ * - Local search ranking: Complete addresses improve local SEO
59
+ * - Map visibility: Address + geo coordinates enable map pins in search results
60
+ * - Rich snippets: Address shown in business listings and Knowledge Graph panels
61
+ * - Mobile search: "Near me" searches prioritize businesses with addresses
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const address = {
66
+ * "@type": "PostalAddress",
67
+ * streetAddress: "123 Main St",
68
+ * addressLocality: "Strasbourg",
69
+ * addressRegion: "Grand Est",
70
+ * postalCode: "67000",
71
+ * addressCountry: "FR"
72
+ * }
73
+ * ```
74
+ *
75
+ * @see specs/app/pages/meta/structured-data/postal-address.schema.json
76
+ */
77
+ export const PostalAddressSchema = Schema.Struct({
78
+ '@type': schemaType('PostalAddress'),
79
+ streetAddress: Schema.optional(
80
+ Schema.String.annotations({
81
+ description: 'Street address',
82
+ })
83
+ ),
84
+ addressLocality: Schema.optional(
85
+ Schema.String.annotations({
86
+ description: 'City or locality',
87
+ })
88
+ ),
89
+ addressRegion: Schema.optional(
90
+ Schema.String.annotations({
91
+ description: 'State or region',
92
+ })
93
+ ),
94
+ postalCode: Schema.optional(
95
+ Schema.String.annotations({
96
+ description: 'Postal or ZIP code',
97
+ })
98
+ ),
99
+ addressCountry: Schema.optional(CountryCodeSchema),
100
+ }).annotations({
101
+ title: 'Postal Address',
102
+ description: 'Schema.org PostalAddress structured data',
103
+ })
104
+
105
+ export type CountryCode = Schema.Schema.Type<typeof CountryCodeSchema>
106
+ export type PostalAddress = Schema.Schema.Type<typeof PostalAddressSchema>