@sonicjs-cms/core 2.19.0 → 3.0.0-beta.3

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 (224) hide show
  1. package/README.md +4 -3
  2. package/dist/admin-documents-form.template-KN7JF66Q.cjs +19 -0
  3. package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-KN7JF66Q.cjs.map} +1 -1
  4. package/dist/admin-documents-form.template-NLSI6Z42.js +6 -0
  5. package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-NLSI6Z42.js.map} +1 -1
  6. package/dist/admin-layout-catalyst.template-WHJGSWWD.js +7 -0
  7. package/dist/admin-layout-catalyst.template-WHJGSWWD.js.map +1 -0
  8. package/dist/admin-layout-catalyst.template-ZK5HD545.cjs +17 -0
  9. package/dist/admin-layout-catalyst.template-ZK5HD545.cjs.map +1 -0
  10. package/dist/app-Bo0X1OWX.d.ts +1268 -0
  11. package/dist/app-Do66yCcV.d.cts +1268 -0
  12. package/dist/cache-DDARE4QE.js +4 -0
  13. package/dist/cache-DDARE4QE.js.map +1 -0
  14. package/dist/cache-LVYS4BPL.cjs +33 -0
  15. package/dist/cache-LVYS4BPL.cjs.map +1 -0
  16. package/dist/chunk-2CB4KY7I.cjs +771 -0
  17. package/dist/chunk-2CB4KY7I.cjs.map +1 -0
  18. package/dist/chunk-2JTWQZHG.cjs +276 -0
  19. package/dist/chunk-2JTWQZHG.cjs.map +1 -0
  20. package/dist/{chunk-55RDMDOP.js → chunk-3TB6AT6X.js} +148 -55
  21. package/dist/chunk-3TB6AT6X.js.map +1 -0
  22. package/dist/{chunk-E4YFJBM2.cjs → chunk-673S7EBY.cjs} +621 -829
  23. package/dist/chunk-673S7EBY.cjs.map +1 -0
  24. package/dist/{chunk-ON5ZMSU4.js → chunk-6JQOUUOB.js} +3 -3
  25. package/dist/chunk-6JQOUUOB.js.map +1 -0
  26. package/dist/chunk-7LHUVREV.cjs +158 -0
  27. package/dist/chunk-7LHUVREV.cjs.map +1 -0
  28. package/dist/chunk-AI663NBO.js +821 -0
  29. package/dist/chunk-AI663NBO.js.map +1 -0
  30. package/dist/chunk-BDDABDAB.cjs +1149 -0
  31. package/dist/chunk-BDDABDAB.cjs.map +1 -0
  32. package/dist/chunk-BLMTL57B.js +767 -0
  33. package/dist/chunk-BLMTL57B.js.map +1 -0
  34. package/dist/{chunk-ABB34XUS.cjs → chunk-CHCBHIBM.cjs} +667 -19
  35. package/dist/chunk-CHCBHIBM.cjs.map +1 -0
  36. package/dist/chunk-DNQCEKUK.cjs +327 -0
  37. package/dist/chunk-DNQCEKUK.cjs.map +1 -0
  38. package/dist/chunk-EF2NQUIQ.js +323 -0
  39. package/dist/chunk-EF2NQUIQ.js.map +1 -0
  40. package/dist/chunk-GCDZZNIN.js +192 -0
  41. package/dist/chunk-GCDZZNIN.js.map +1 -0
  42. package/dist/{chunk-XWIA3HVX.js → chunk-HDWE5FRJ.js} +6 -1249
  43. package/dist/chunk-HDWE5FRJ.js.map +1 -0
  44. package/dist/chunk-HIKBY7MS.cjs +70 -0
  45. package/dist/chunk-HIKBY7MS.cjs.map +1 -0
  46. package/dist/chunk-IESEVHXL.js +66 -0
  47. package/dist/chunk-IESEVHXL.js.map +1 -0
  48. package/dist/chunk-IVPRUGTY.js +242 -0
  49. package/dist/chunk-IVPRUGTY.js.map +1 -0
  50. package/dist/{chunk-JZVHLLSI.cjs → chunk-IXUHXTHW.cjs} +2 -151
  51. package/dist/chunk-IXUHXTHW.cjs.map +1 -0
  52. package/dist/{chunk-7A4CB7T3.cjs → chunk-J5DCX3F6.cjs} +509 -91
  53. package/dist/chunk-J5DCX3F6.cjs.map +1 -0
  54. package/dist/chunk-J6JTWD2A.cjs +100 -0
  55. package/dist/chunk-J6JTWD2A.cjs.map +1 -0
  56. package/dist/chunk-JEQ7FLOD.cjs +199 -0
  57. package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
  58. package/dist/chunk-K25XHMM3.js +566 -0
  59. package/dist/chunk-K25XHMM3.js.map +1 -0
  60. package/dist/{chunk-R4FOLLFB.cjs → chunk-LO6MEPRW.cjs} +8730 -11520
  61. package/dist/chunk-LO6MEPRW.cjs.map +1 -0
  62. package/dist/chunk-MHP7HYTT.js +273 -0
  63. package/dist/chunk-MHP7HYTT.js.map +1 -0
  64. package/dist/chunk-MP3Q2W76.js +387 -0
  65. package/dist/chunk-MP3Q2W76.js.map +1 -0
  66. package/dist/{chunk-OHYBNCVL.cjs → chunk-MVIZJOO5.cjs} +10 -1256
  67. package/dist/chunk-MVIZJOO5.cjs.map +1 -0
  68. package/dist/{chunk-UYJ6TJHX.cjs → chunk-NAVPFIG5.cjs} +148 -55
  69. package/dist/chunk-NAVPFIG5.cjs.map +1 -0
  70. package/dist/chunk-NUKJ54GA.cjs +245 -0
  71. package/dist/chunk-NUKJ54GA.cjs.map +1 -0
  72. package/dist/{chunk-BU7SFHGP.js → chunk-QZGABF2M.js} +3 -149
  73. package/dist/chunk-QZGABF2M.js.map +1 -0
  74. package/dist/{chunk-JZV22DEV.js → chunk-RJV6UXLZ.js} +611 -817
  75. package/dist/chunk-RJV6UXLZ.js.map +1 -0
  76. package/dist/chunk-RNZFGN4R.js +88 -0
  77. package/dist/chunk-RNZFGN4R.js.map +1 -0
  78. package/dist/{chunk-TFNTM3OA.js → chunk-SL6XS6YT.js} +645 -15
  79. package/dist/chunk-SL6XS6YT.js.map +1 -0
  80. package/dist/{chunk-OCL3HMEG.js → chunk-SO2T3OXR.js} +7004 -9807
  81. package/dist/chunk-SO2T3OXR.js.map +1 -0
  82. package/dist/chunk-VQHAJUZZ.cjs +408 -0
  83. package/dist/chunk-VQHAJUZZ.cjs.map +1 -0
  84. package/dist/{chunk-4NPCDK6B.js → chunk-VZ3NHR5Z.js} +505 -90
  85. package/dist/chunk-VZ3NHR5Z.js.map +1 -0
  86. package/dist/{chunk-4ZSNJDLS.cjs → chunk-WULONYGB.cjs} +9 -9
  87. package/dist/chunk-WULONYGB.cjs.map +1 -0
  88. package/dist/chunk-XFQHK64T.js +154 -0
  89. package/dist/chunk-XFQHK64T.js.map +1 -0
  90. package/dist/chunk-YA3TJ65D.cjs +575 -0
  91. package/dist/chunk-YA3TJ65D.cjs.map +1 -0
  92. package/dist/chunk-YP7GW2G5.cjs +866 -0
  93. package/dist/chunk-YP7GW2G5.cjs.map +1 -0
  94. package/dist/{chunk-QFWHAFEO.js → chunk-ZEZ245PW.js} +148 -858
  95. package/dist/chunk-ZEZ245PW.js.map +1 -0
  96. package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
  97. package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
  98. package/dist/config-HFXANXCC.js +6 -0
  99. package/dist/config-HFXANXCC.js.map +1 -0
  100. package/dist/config-ON6FNMYX.cjs +19 -0
  101. package/dist/config-ON6FNMYX.cjs.map +1 -0
  102. package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
  103. package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
  104. package/dist/document-projection-TDWRJX3Z.cjs +13 -0
  105. package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
  106. package/dist/document-projection-YYMC6I4U.js +4 -0
  107. package/dist/document-projection-YYMC6I4U.js.map +1 -0
  108. package/dist/index.cjs +13734 -4328
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.d.cts +329 -492
  111. package/dist/index.d.ts +329 -492
  112. package/dist/index.js +13385 -3998
  113. package/dist/index.js.map +1 -1
  114. package/dist/middleware.cjs +36 -32
  115. package/dist/middleware.d.cts +50 -7
  116. package/dist/middleware.d.ts +50 -7
  117. package/dist/middleware.js +7 -3
  118. package/dist/migrations-DK2YFPLR.js +4 -0
  119. package/dist/{migrations-H5IXZNCO.js.map → migrations-DK2YFPLR.js.map} +1 -1
  120. package/dist/migrations-YHNHTJOO.cjs +13 -0
  121. package/dist/{migrations-566IIPS2.cjs.map → migrations-YHNHTJOO.cjs.map} +1 -1
  122. package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
  123. package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
  124. package/dist/plugins.cjs +171 -12
  125. package/dist/plugins.d.cts +36 -2
  126. package/dist/plugins.d.ts +36 -2
  127. package/dist/plugins.js +5 -2
  128. package/dist/rbac-O73MFKDA.js +5 -0
  129. package/dist/rbac-O73MFKDA.js.map +1 -0
  130. package/dist/rbac-VONLJJKB.cjs +14 -0
  131. package/dist/rbac-VONLJJKB.cjs.map +1 -0
  132. package/dist/routes.cjs +41 -45
  133. package/dist/routes.d.cts +56 -146
  134. package/dist/routes.d.ts +56 -146
  135. package/dist/routes.js +17 -9
  136. package/dist/services.cjs +39 -72
  137. package/dist/services.d.cts +79 -54
  138. package/dist/services.d.ts +79 -54
  139. package/dist/services.js +6 -3
  140. package/dist/templates.cjs +17 -29
  141. package/dist/templates.d.cts +1 -66
  142. package/dist/templates.d.ts +1 -66
  143. package/dist/templates.js +3 -3
  144. package/dist/types-Dea1eNxU.d.cts +286 -0
  145. package/dist/types-Dea1eNxU.d.ts +286 -0
  146. package/dist/types.d.cts +1 -1
  147. package/dist/types.d.ts +1 -1
  148. package/dist/utils.cjs +18 -17
  149. package/dist/utils.d.cts +1 -1
  150. package/dist/utils.d.ts +1 -1
  151. package/dist/utils.js +2 -1
  152. package/migrations/0001_core.sql +184 -0
  153. package/migrations/0002_documents.sql +163 -0
  154. package/package.json +12 -7
  155. package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
  156. package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
  157. package/dist/app-C9esKLmh.d.cts +0 -112
  158. package/dist/app-C9esKLmh.d.ts +0 -112
  159. package/dist/chunk-4NPCDK6B.js.map +0 -1
  160. package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
  161. package/dist/chunk-55RDMDOP.js.map +0 -1
  162. package/dist/chunk-635JAMSE.cjs +0 -653
  163. package/dist/chunk-635JAMSE.cjs.map +0 -1
  164. package/dist/chunk-7A4CB7T3.cjs.map +0 -1
  165. package/dist/chunk-ABB34XUS.cjs.map +0 -1
  166. package/dist/chunk-BU7SFHGP.js.map +0 -1
  167. package/dist/chunk-E4YFJBM2.cjs.map +0 -1
  168. package/dist/chunk-EXNEW5US.js +0 -648
  169. package/dist/chunk-EXNEW5US.js.map +0 -1
  170. package/dist/chunk-JZV22DEV.js.map +0 -1
  171. package/dist/chunk-JZVHLLSI.cjs.map +0 -1
  172. package/dist/chunk-OCL3HMEG.js.map +0 -1
  173. package/dist/chunk-OHYBNCVL.cjs.map +0 -1
  174. package/dist/chunk-ON5ZMSU4.js.map +0 -1
  175. package/dist/chunk-QFWHAFEO.js.map +0 -1
  176. package/dist/chunk-R4FOLLFB.cjs.map +0 -1
  177. package/dist/chunk-RLMUFFUD.cjs +0 -2219
  178. package/dist/chunk-RLMUFFUD.cjs.map +0 -1
  179. package/dist/chunk-TFNTM3OA.js.map +0 -1
  180. package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
  181. package/dist/chunk-WAEQXGCX.cjs +0 -1898
  182. package/dist/chunk-WAEQXGCX.cjs.map +0 -1
  183. package/dist/chunk-XWIA3HVX.js.map +0 -1
  184. package/dist/chunk-ZYAYUIZE.js +0 -2217
  185. package/dist/chunk-ZYAYUIZE.js.map +0 -1
  186. package/dist/migrations-566IIPS2.cjs +0 -13
  187. package/dist/migrations-H5IXZNCO.js +0 -4
  188. package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
  189. package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
  190. package/migrations/001_initial_schema.sql +0 -170
  191. package/migrations/002_faq_plugin.sql +0 -86
  192. package/migrations/003_stage5_enhancements.sql +0 -121
  193. package/migrations/004_stage6_user_management.sql +0 -183
  194. package/migrations/005_stage7_workflow_automation.sql +0 -294
  195. package/migrations/006_plugin_system.sql +0 -155
  196. package/migrations/007_demo_login_plugin.sql +0 -23
  197. package/migrations/008_fix_slug_validation.sql +0 -22
  198. package/migrations/009_system_logging.sql +0 -57
  199. package/migrations/011_config_managed_collections.sql +0 -15
  200. package/migrations/012_testimonials_plugin.sql +0 -80
  201. package/migrations/013_code_examples_plugin.sql +0 -177
  202. package/migrations/014_fix_plugin_registry.sql +0 -88
  203. package/migrations/015_add_remaining_plugins.sql +0 -89
  204. package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
  205. package/migrations/017_auth_configurable_fields.sql +0 -49
  206. package/migrations/018_settings_table.sql +0 -23
  207. package/migrations/019_remove_blog_posts_collection.sql +0 -15
  208. package/migrations/020_add_email_plugin.sql +0 -22
  209. package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
  210. package/migrations/022_add_tinymce_plugin.sql +0 -25
  211. package/migrations/023_add_easy_mdx_plugin.sql +0 -25
  212. package/migrations/024_add_quill_editor_plugin.sql +0 -25
  213. package/migrations/025_add_easymde_plugin.sql +0 -25
  214. package/migrations/026_add_otp_login.sql +0 -42
  215. package/migrations/027_fix_slug_field_type.sql +0 -18
  216. package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
  217. package/migrations/029_add_forms_system.sql +0 -184
  218. package/migrations/030_add_turnstile_to_forms.sql +0 -14
  219. package/migrations/031_ai_search_plugin.sql +0 -45
  220. package/migrations/032_user_profiles.sql +0 -37
  221. package/migrations/033_form_content_integration.sql +0 -19
  222. package/migrations/034_security_audit_plugin.sql +0 -27
  223. package/migrations/035_user_profiles_data_column.sql +0 -16
  224. package/migrations/036_analytics_events.sql +0 -22
@@ -1,713 +1,10 @@
1
+ import { getCacheService } from './chunk-K25XHMM3.js';
2
+ import { systemLogs, logConfig } from './chunk-AI663NBO.js';
1
3
  import { getTelemetryConfig, sanitizeErrorMessage, sanitizeRoute, generateInstallationId, generateProjectId } from './chunk-X7ZAEI5S.js';
2
- import { __export } from './chunk-V4OQ3NZ2.js';
3
- import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
4
- import { z } from 'zod/v4';
5
- import { isTable, getTableColumns, getViewSelectedFields, is, Column, SQL, isView, inArray, eq, like, gte, lte, and, count, asc, desc } from 'drizzle-orm';
6
4
  import { drizzle } from 'drizzle-orm/d1';
5
+ import { inArray, eq, like, gte, lte, and, count, asc, desc } from 'drizzle-orm';
7
6
  import { inspectRoutes } from 'hono/dev';
8
7
 
9
- // src/db/schema.ts
10
- var schema_exports = {};
11
- __export(schema_exports, {
12
- apiTokens: () => apiTokens,
13
- collections: () => collections,
14
- content: () => content,
15
- contentVersions: () => contentVersions,
16
- formFiles: () => formFiles,
17
- formSubmissions: () => formSubmissions,
18
- forms: () => forms,
19
- insertCollectionSchema: () => insertCollectionSchema,
20
- insertContentSchema: () => insertContentSchema,
21
- insertFormFileSchema: () => insertFormFileSchema,
22
- insertFormSchema: () => insertFormSchema,
23
- insertFormSubmissionSchema: () => insertFormSubmissionSchema,
24
- insertLogConfigSchema: () => insertLogConfigSchema,
25
- insertMediaSchema: () => insertMediaSchema,
26
- insertPluginActivityLogSchema: () => insertPluginActivityLogSchema,
27
- insertPluginAssetSchema: () => insertPluginAssetSchema,
28
- insertPluginHookSchema: () => insertPluginHookSchema,
29
- insertPluginRouteSchema: () => insertPluginRouteSchema,
30
- insertPluginSchema: () => insertPluginSchema,
31
- insertSecurityEventSchema: () => insertSecurityEventSchema,
32
- insertSystemLogSchema: () => insertSystemLogSchema,
33
- insertUserSchema: () => insertUserSchema,
34
- insertWorkflowHistorySchema: () => insertWorkflowHistorySchema,
35
- logConfig: () => logConfig,
36
- media: () => media,
37
- pluginActivityLog: () => pluginActivityLog,
38
- pluginAssets: () => pluginAssets,
39
- pluginHooks: () => pluginHooks,
40
- pluginRoutes: () => pluginRoutes,
41
- plugins: () => plugins,
42
- securityEvents: () => securityEvents,
43
- selectCollectionSchema: () => selectCollectionSchema,
44
- selectContentSchema: () => selectContentSchema,
45
- selectFormFileSchema: () => selectFormFileSchema,
46
- selectFormSchema: () => selectFormSchema,
47
- selectFormSubmissionSchema: () => selectFormSubmissionSchema,
48
- selectLogConfigSchema: () => selectLogConfigSchema,
49
- selectMediaSchema: () => selectMediaSchema,
50
- selectPluginActivityLogSchema: () => selectPluginActivityLogSchema,
51
- selectPluginAssetSchema: () => selectPluginAssetSchema,
52
- selectPluginHookSchema: () => selectPluginHookSchema,
53
- selectPluginRouteSchema: () => selectPluginRouteSchema,
54
- selectPluginSchema: () => selectPluginSchema,
55
- selectSecurityEventSchema: () => selectSecurityEventSchema,
56
- selectSystemLogSchema: () => selectSystemLogSchema,
57
- selectUserSchema: () => selectUserSchema,
58
- selectWorkflowHistorySchema: () => selectWorkflowHistorySchema,
59
- systemLogs: () => systemLogs,
60
- users: () => users,
61
- workflowHistory: () => workflowHistory
62
- });
63
- var CONSTANTS = {
64
- INT8_MIN: -128,
65
- INT8_MAX: 127,
66
- INT8_UNSIGNED_MAX: 255,
67
- INT16_MIN: -32768,
68
- INT16_MAX: 32767,
69
- INT16_UNSIGNED_MAX: 65535,
70
- INT24_MIN: -8388608,
71
- INT24_MAX: 8388607,
72
- INT24_UNSIGNED_MAX: 16777215,
73
- INT32_MIN: -2147483648,
74
- INT32_MAX: 2147483647,
75
- INT32_UNSIGNED_MAX: 4294967295,
76
- INT48_MIN: -140737488355328,
77
- INT48_MAX: 140737488355327,
78
- INT48_UNSIGNED_MAX: 281474976710655,
79
- INT64_MIN: -9223372036854775808n,
80
- INT64_MAX: 9223372036854775807n,
81
- INT64_UNSIGNED_MAX: 18446744073709551615n
82
- };
83
- function isColumnType(column, columnTypes) {
84
- return columnTypes.includes(column.columnType);
85
- }
86
- function isWithEnum(column) {
87
- return "enumValues" in column && Array.isArray(column.enumValues) && column.enumValues.length > 0;
88
- }
89
- var isPgEnum = isWithEnum;
90
- var literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
91
- var jsonSchema = z.union([
92
- literalSchema,
93
- z.record(z.string(), z.any()),
94
- z.array(z.any())
95
- ]);
96
- var bufferSchema = z.custom((v) => v instanceof Buffer);
97
- function columnToSchema(column, factory) {
98
- const z$1 = z;
99
- const coerce = {};
100
- let schema;
101
- if (isWithEnum(column)) {
102
- schema = column.enumValues.length ? z$1.enum(column.enumValues) : z$1.string();
103
- }
104
- if (!schema) {
105
- if (isColumnType(column, ["PgGeometry", "PgPointTuple"])) {
106
- schema = z$1.tuple([z$1.number(), z$1.number()]);
107
- } else if (isColumnType(column, ["PgGeometryObject", "PgPointObject"])) {
108
- schema = z$1.object({ x: z$1.number(), y: z$1.number() });
109
- } else if (isColumnType(column, ["PgHalfVector", "PgVector"])) {
110
- schema = z$1.array(z$1.number());
111
- schema = column.dimensions ? schema.length(column.dimensions) : schema;
112
- } else if (isColumnType(column, ["PgLine"])) {
113
- schema = z$1.tuple([z$1.number(), z$1.number(), z$1.number()]);
114
- } else if (isColumnType(column, ["PgLineABC"])) {
115
- schema = z$1.object({
116
- a: z$1.number(),
117
- b: z$1.number(),
118
- c: z$1.number()
119
- });
120
- } else if (isColumnType(column, ["PgArray"])) {
121
- schema = z$1.array(columnToSchema(column.baseColumn));
122
- schema = column.size ? schema.length(column.size) : schema;
123
- } else if (column.dataType === "array") {
124
- schema = z$1.array(z$1.any());
125
- } else if (column.dataType === "number") {
126
- schema = numberColumnToSchema(column, z$1, coerce);
127
- } else if (column.dataType === "bigint") {
128
- schema = bigintColumnToSchema(column, z$1, coerce);
129
- } else if (column.dataType === "boolean") {
130
- schema = coerce === true || coerce.boolean ? z$1.coerce.boolean() : z$1.boolean();
131
- } else if (column.dataType === "date") {
132
- schema = coerce === true || coerce.date ? z$1.coerce.date() : z$1.date();
133
- } else if (column.dataType === "string") {
134
- schema = stringColumnToSchema(column, z$1, coerce);
135
- } else if (column.dataType === "json") {
136
- schema = jsonSchema;
137
- } else if (column.dataType === "custom") {
138
- schema = z$1.any();
139
- } else if (column.dataType === "buffer") {
140
- schema = bufferSchema;
141
- }
142
- }
143
- if (!schema) {
144
- schema = z$1.any();
145
- }
146
- return schema;
147
- }
148
- function numberColumnToSchema(column, z2, coerce) {
149
- let unsigned = column.getSQLType().includes("unsigned");
150
- let min;
151
- let max;
152
- let integer2 = false;
153
- if (isColumnType(column, ["MySqlTinyInt", "SingleStoreTinyInt"])) {
154
- min = unsigned ? 0 : CONSTANTS.INT8_MIN;
155
- max = unsigned ? CONSTANTS.INT8_UNSIGNED_MAX : CONSTANTS.INT8_MAX;
156
- integer2 = true;
157
- } else if (isColumnType(column, [
158
- "PgSmallInt",
159
- "PgSmallSerial",
160
- "MySqlSmallInt",
161
- "SingleStoreSmallInt"
162
- ])) {
163
- min = unsigned ? 0 : CONSTANTS.INT16_MIN;
164
- max = unsigned ? CONSTANTS.INT16_UNSIGNED_MAX : CONSTANTS.INT16_MAX;
165
- integer2 = true;
166
- } else if (isColumnType(column, [
167
- "PgReal",
168
- "MySqlFloat",
169
- "MySqlMediumInt",
170
- "SingleStoreMediumInt",
171
- "SingleStoreFloat"
172
- ])) {
173
- min = unsigned ? 0 : CONSTANTS.INT24_MIN;
174
- max = unsigned ? CONSTANTS.INT24_UNSIGNED_MAX : CONSTANTS.INT24_MAX;
175
- integer2 = isColumnType(column, ["MySqlMediumInt", "SingleStoreMediumInt"]);
176
- } else if (isColumnType(column, [
177
- "PgInteger",
178
- "PgSerial",
179
- "MySqlInt",
180
- "SingleStoreInt"
181
- ])) {
182
- min = unsigned ? 0 : CONSTANTS.INT32_MIN;
183
- max = unsigned ? CONSTANTS.INT32_UNSIGNED_MAX : CONSTANTS.INT32_MAX;
184
- integer2 = true;
185
- } else if (isColumnType(column, [
186
- "PgDoublePrecision",
187
- "MySqlReal",
188
- "MySqlDouble",
189
- "SingleStoreReal",
190
- "SingleStoreDouble",
191
- "SQLiteReal"
192
- ])) {
193
- min = unsigned ? 0 : CONSTANTS.INT48_MIN;
194
- max = unsigned ? CONSTANTS.INT48_UNSIGNED_MAX : CONSTANTS.INT48_MAX;
195
- } else if (isColumnType(column, [
196
- "PgBigInt53",
197
- "PgBigSerial53",
198
- "MySqlBigInt53",
199
- "MySqlSerial",
200
- "SingleStoreBigInt53",
201
- "SingleStoreSerial",
202
- "SQLiteInteger"
203
- ])) {
204
- unsigned = unsigned || isColumnType(column, ["MySqlSerial", "SingleStoreSerial"]);
205
- min = unsigned ? 0 : Number.MIN_SAFE_INTEGER;
206
- max = Number.MAX_SAFE_INTEGER;
207
- integer2 = true;
208
- } else if (isColumnType(column, ["MySqlYear", "SingleStoreYear"])) {
209
- min = 1901;
210
- max = 2155;
211
- integer2 = true;
212
- } else {
213
- min = Number.MIN_SAFE_INTEGER;
214
- max = Number.MAX_SAFE_INTEGER;
215
- }
216
- let schema = coerce === true || coerce?.number ? integer2 ? z2.coerce.number() : z2.coerce.number().int() : integer2 ? z2.int() : z2.number();
217
- schema = schema.gte(min).lte(max);
218
- return schema;
219
- }
220
- function bigintColumnToSchema(column, z2, coerce) {
221
- const unsigned = column.getSQLType().includes("unsigned");
222
- const min = unsigned ? 0n : CONSTANTS.INT64_MIN;
223
- const max = unsigned ? CONSTANTS.INT64_UNSIGNED_MAX : CONSTANTS.INT64_MAX;
224
- const schema = coerce === true || coerce?.bigint ? z2.coerce.bigint() : z2.bigint();
225
- return schema.gte(min).lte(max);
226
- }
227
- function stringColumnToSchema(column, z2, coerce) {
228
- if (isColumnType(column, ["PgUUID"])) {
229
- return z2.uuid();
230
- }
231
- let max;
232
- let regex;
233
- let fixed = false;
234
- if (isColumnType(column, ["PgVarchar", "SQLiteText"])) {
235
- max = column.length;
236
- } else if (isColumnType(column, ["MySqlVarChar", "SingleStoreVarChar"])) {
237
- max = column.length ?? CONSTANTS.INT16_UNSIGNED_MAX;
238
- } else if (isColumnType(column, ["MySqlText", "SingleStoreText"])) {
239
- if (column.textType === "longtext") {
240
- max = CONSTANTS.INT32_UNSIGNED_MAX;
241
- } else if (column.textType === "mediumtext") {
242
- max = CONSTANTS.INT24_UNSIGNED_MAX;
243
- } else if (column.textType === "text") {
244
- max = CONSTANTS.INT16_UNSIGNED_MAX;
245
- } else {
246
- max = CONSTANTS.INT8_UNSIGNED_MAX;
247
- }
248
- }
249
- if (isColumnType(column, [
250
- "PgChar",
251
- "MySqlChar",
252
- "SingleStoreChar"
253
- ])) {
254
- max = column.length;
255
- fixed = true;
256
- }
257
- if (isColumnType(column, ["PgBinaryVector"])) {
258
- regex = /^[01]+$/;
259
- max = column.dimensions;
260
- }
261
- let schema = coerce === true || coerce?.string ? z2.coerce.string() : z2.string();
262
- schema = regex ? schema.regex(regex) : schema;
263
- return max && fixed ? schema.length(max) : max ? schema.max(max) : schema;
264
- }
265
- function getColumns(tableLike) {
266
- return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike);
267
- }
268
- function handleColumns(columns, refinements, conditions, factory) {
269
- const columnSchemas = {};
270
- for (const [key, selected] of Object.entries(columns)) {
271
- if (!is(selected, Column) && !is(selected, SQL) && !is(selected, SQL.Aliased) && typeof selected === "object") {
272
- const columns2 = isTable(selected) || isView(selected) ? getColumns(selected) : selected;
273
- columnSchemas[key] = handleColumns(columns2, refinements[key] ?? {}, conditions);
274
- continue;
275
- }
276
- const refinement = refinements[key];
277
- if (refinement !== void 0 && typeof refinement !== "function") {
278
- columnSchemas[key] = refinement;
279
- continue;
280
- }
281
- const column = is(selected, Column) ? selected : void 0;
282
- const schema = column ? columnToSchema(column) : z.any();
283
- const refined = typeof refinement === "function" ? refinement(schema) : schema;
284
- if (conditions.never(column)) {
285
- continue;
286
- } else {
287
- columnSchemas[key] = refined;
288
- }
289
- if (column) {
290
- if (conditions.nullable(column)) {
291
- columnSchemas[key] = columnSchemas[key].nullable();
292
- }
293
- if (conditions.optional(column)) {
294
- columnSchemas[key] = columnSchemas[key].optional();
295
- }
296
- }
297
- }
298
- return z.object(columnSchemas);
299
- }
300
- function handleEnum(enum_, factory) {
301
- const zod = z;
302
- return zod.enum(enum_.enumValues);
303
- }
304
- var selectConditions = {
305
- never: () => false,
306
- optional: () => false,
307
- nullable: (column) => !column.notNull
308
- };
309
- var insertConditions = {
310
- never: (column) => column?.generated?.type === "always" || column?.generatedIdentity?.type === "always",
311
- optional: (column) => !column.notNull || column.notNull && column.hasDefault,
312
- nullable: (column) => !column.notNull
313
- };
314
- var createSelectSchema = (entity, refine) => {
315
- if (isPgEnum(entity)) {
316
- return handleEnum(entity);
317
- }
318
- const columns = getColumns(entity);
319
- return handleColumns(columns, {}, selectConditions);
320
- };
321
- var createInsertSchema = (entity, refine) => {
322
- const columns = getColumns(entity);
323
- return handleColumns(columns, refine ?? {}, insertConditions);
324
- };
325
-
326
- // src/db/schema.ts
327
- var users = sqliteTable("users", {
328
- id: text("id").primaryKey(),
329
- email: text("email").notNull().unique(),
330
- username: text("username").notNull().unique(),
331
- firstName: text("first_name").notNull(),
332
- lastName: text("last_name").notNull(),
333
- passwordHash: text("password_hash"),
334
- // Hashed password, nullable for OAuth users
335
- role: text("role").notNull().default("viewer"),
336
- // 'admin', 'editor', 'author', 'viewer'
337
- avatar: text("avatar"),
338
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
339
- lastLoginAt: integer("last_login_at"),
340
- createdAt: integer("created_at").notNull(),
341
- updatedAt: integer("updated_at").notNull()
342
- });
343
- var collections = sqliteTable("collections", {
344
- id: text("id").primaryKey(),
345
- name: text("name").notNull().unique(),
346
- displayName: text("display_name").notNull(),
347
- description: text("description"),
348
- schema: text("schema", { mode: "json" }).notNull(),
349
- // JSON schema definition
350
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
351
- managed: integer("managed", { mode: "boolean" }).notNull().default(false),
352
- // Config-managed collections cannot be edited in UI
353
- sourceType: text("source_type").default("user"),
354
- // 'user' (normal), 'form' (form-derived)
355
- sourceId: text("source_id"),
356
- // stores the form ID for form-derived collections
357
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
358
- updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
359
- });
360
- var content = sqliteTable("content", {
361
- id: text("id").primaryKey(),
362
- collectionId: text("collection_id").notNull().references(() => collections.id),
363
- slug: text("slug").notNull(),
364
- title: text("title").notNull(),
365
- data: text("data", { mode: "json" }).notNull(),
366
- // JSON content data
367
- status: text("status").notNull().default("draft"),
368
- // 'draft', 'published', 'archived'
369
- publishedAt: integer("published_at", { mode: "timestamp" }),
370
- authorId: text("author_id").notNull().references(() => users.id),
371
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
372
- updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
373
- });
374
- var contentVersions = sqliteTable("content_versions", {
375
- id: text("id").primaryKey(),
376
- contentId: text("content_id").notNull().references(() => content.id),
377
- version: integer("version").notNull(),
378
- data: text("data", { mode: "json" }).notNull(),
379
- authorId: text("author_id").notNull().references(() => users.id),
380
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
381
- });
382
- var media = sqliteTable("media", {
383
- id: text("id").primaryKey(),
384
- filename: text("filename").notNull(),
385
- originalName: text("original_name").notNull(),
386
- mimeType: text("mime_type").notNull(),
387
- size: integer("size").notNull(),
388
- width: integer("width"),
389
- height: integer("height"),
390
- folder: text("folder").notNull().default("uploads"),
391
- r2Key: text("r2_key").notNull(),
392
- // R2 storage key
393
- publicUrl: text("public_url").notNull(),
394
- // CDN URL
395
- thumbnailUrl: text("thumbnail_url"),
396
- alt: text("alt"),
397
- caption: text("caption"),
398
- tags: text("tags", { mode: "json" }),
399
- // JSON array of tags
400
- uploadedBy: text("uploaded_by").notNull().references(() => users.id),
401
- uploadedAt: integer("uploaded_at").notNull(),
402
- updatedAt: integer("updated_at"),
403
- publishedAt: integer("published_at"),
404
- scheduledAt: integer("scheduled_at"),
405
- archivedAt: integer("archived_at"),
406
- deletedAt: integer("deleted_at")
407
- });
408
- var apiTokens = sqliteTable("api_tokens", {
409
- id: text("id").primaryKey(),
410
- name: text("name").notNull(),
411
- token: text("token").notNull().unique(),
412
- userId: text("user_id").notNull().references(() => users.id),
413
- permissions: text("permissions", { mode: "json" }).notNull(),
414
- // Array of permissions
415
- expiresAt: integer("expires_at", { mode: "timestamp" }),
416
- lastUsedAt: integer("last_used_at", { mode: "timestamp" }),
417
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
418
- });
419
- var workflowHistory = sqliteTable("workflow_history", {
420
- id: text("id").primaryKey(),
421
- contentId: text("content_id").notNull().references(() => content.id),
422
- action: text("action").notNull(),
423
- fromStatus: text("from_status").notNull(),
424
- toStatus: text("to_status").notNull(),
425
- userId: text("user_id").notNull().references(() => users.id),
426
- comment: text("comment"),
427
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
428
- });
429
- var plugins = sqliteTable("plugins", {
430
- id: text("id").primaryKey(),
431
- name: text("name").notNull().unique(),
432
- displayName: text("display_name").notNull(),
433
- description: text("description"),
434
- version: text("version").notNull(),
435
- author: text("author").notNull(),
436
- category: text("category").notNull(),
437
- icon: text("icon"),
438
- status: text("status").notNull().default("inactive"),
439
- // 'active', 'inactive', 'error'
440
- isCore: integer("is_core", { mode: "boolean" }).notNull().default(false),
441
- settings: text("settings", { mode: "json" }),
442
- permissions: text("permissions", { mode: "json" }),
443
- dependencies: text("dependencies", { mode: "json" }),
444
- downloadCount: integer("download_count").notNull().default(0),
445
- rating: integer("rating").notNull().default(0),
446
- installedAt: integer("installed_at").notNull(),
447
- activatedAt: integer("activated_at"),
448
- lastUpdated: integer("last_updated").notNull(),
449
- errorMessage: text("error_message"),
450
- createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3)),
451
- updatedAt: integer("updated_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
452
- });
453
- var pluginHooks = sqliteTable("plugin_hooks", {
454
- id: text("id").primaryKey(),
455
- pluginId: text("plugin_id").notNull().references(() => plugins.id),
456
- hookName: text("hook_name").notNull(),
457
- handlerName: text("handler_name").notNull(),
458
- priority: integer("priority").notNull().default(10),
459
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
460
- createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
461
- });
462
- var pluginRoutes = sqliteTable("plugin_routes", {
463
- id: text("id").primaryKey(),
464
- pluginId: text("plugin_id").notNull().references(() => plugins.id),
465
- path: text("path").notNull(),
466
- method: text("method").notNull(),
467
- handlerName: text("handler_name").notNull(),
468
- middleware: text("middleware", { mode: "json" }),
469
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
470
- createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
471
- });
472
- var pluginAssets = sqliteTable("plugin_assets", {
473
- id: text("id").primaryKey(),
474
- pluginId: text("plugin_id").notNull().references(() => plugins.id),
475
- assetType: text("asset_type").notNull(),
476
- // 'css', 'js', 'image', 'font'
477
- assetPath: text("asset_path").notNull(),
478
- loadOrder: integer("load_order").notNull().default(100),
479
- loadLocation: text("load_location").notNull().default("footer"),
480
- // 'header', 'footer'
481
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
482
- createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
483
- });
484
- var pluginActivityLog = sqliteTable("plugin_activity_log", {
485
- id: text("id").primaryKey(),
486
- pluginId: text("plugin_id").notNull().references(() => plugins.id),
487
- action: text("action").notNull(),
488
- userId: text("user_id"),
489
- details: text("details", { mode: "json" }),
490
- timestamp: integer("timestamp").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
491
- });
492
- var insertUserSchema = createInsertSchema(users, {
493
- email: (schema) => schema.email(),
494
- firstName: (schema) => schema.min(1),
495
- lastName: (schema) => schema.min(1),
496
- username: (schema) => schema.min(3)
497
- });
498
- var selectUserSchema = createSelectSchema(users);
499
- var insertCollectionSchema = createInsertSchema(collections, {
500
- name: (schema) => schema.min(1).regex(/^[a-z0-9_]+$/, "Collection name must be lowercase with underscores"),
501
- displayName: (schema) => schema.min(1)
502
- });
503
- var selectCollectionSchema = createSelectSchema(collections);
504
- var insertContentSchema = createInsertSchema(content, {
505
- slug: (schema) => schema.min(1).regex(/^[a-zA-Z0-9_-]+$/, "Slug must contain only letters, numbers, underscores, and hyphens"),
506
- title: (schema) => schema.min(1),
507
- status: (schema) => schema
508
- });
509
- var selectContentSchema = createSelectSchema(content);
510
- var insertMediaSchema = createInsertSchema(media, {
511
- filename: (schema) => schema.min(1),
512
- originalName: (schema) => schema.min(1),
513
- mimeType: (schema) => schema.min(1),
514
- size: (schema) => schema.positive(),
515
- r2Key: (schema) => schema.min(1),
516
- publicUrl: (schema) => schema.url(),
517
- folder: (schema) => schema.min(1)
518
- });
519
- var selectMediaSchema = createSelectSchema(media);
520
- var insertWorkflowHistorySchema = createInsertSchema(workflowHistory, {
521
- action: (schema) => schema.min(1),
522
- fromStatus: (schema) => schema.min(1),
523
- toStatus: (schema) => schema.min(1)
524
- });
525
- var selectWorkflowHistorySchema = createSelectSchema(workflowHistory);
526
- var insertPluginSchema = createInsertSchema(plugins, {
527
- name: (schema) => schema.min(1),
528
- displayName: (schema) => schema.min(1),
529
- version: (schema) => schema.min(1),
530
- author: (schema) => schema.min(1),
531
- category: (schema) => schema.min(1)
532
- });
533
- var selectPluginSchema = createSelectSchema(plugins);
534
- var insertPluginHookSchema = createInsertSchema(pluginHooks, {
535
- hookName: (schema) => schema.min(1),
536
- handlerName: (schema) => schema.min(1)
537
- });
538
- var selectPluginHookSchema = createSelectSchema(pluginHooks);
539
- var insertPluginRouteSchema = createInsertSchema(pluginRoutes, {
540
- path: (schema) => schema.min(1),
541
- method: (schema) => schema.min(1),
542
- handlerName: (schema) => schema.min(1)
543
- });
544
- var selectPluginRouteSchema = createSelectSchema(pluginRoutes);
545
- var insertPluginAssetSchema = createInsertSchema(pluginAssets, {
546
- assetType: (schema) => schema.min(1),
547
- assetPath: (schema) => schema.min(1)
548
- });
549
- var selectPluginAssetSchema = createSelectSchema(pluginAssets);
550
- var insertPluginActivityLogSchema = createInsertSchema(pluginActivityLog, {
551
- action: (schema) => schema.min(1)
552
- });
553
- var selectPluginActivityLogSchema = createSelectSchema(pluginActivityLog);
554
- var systemLogs = sqliteTable("system_logs", {
555
- id: text("id").primaryKey(),
556
- level: text("level").notNull(),
557
- // 'debug', 'info', 'warn', 'error', 'fatal'
558
- category: text("category").notNull(),
559
- // 'auth', 'api', 'workflow', 'plugin', 'media', 'system', etc.
560
- message: text("message").notNull(),
561
- data: text("data", { mode: "json" }),
562
- // Additional structured data
563
- userId: text("user_id").references(() => users.id),
564
- sessionId: text("session_id"),
565
- requestId: text("request_id"),
566
- ipAddress: text("ip_address"),
567
- userAgent: text("user_agent"),
568
- method: text("method"),
569
- // HTTP method for API logs
570
- url: text("url"),
571
- // Request URL for API logs
572
- statusCode: integer("status_code"),
573
- // HTTP status code for API logs
574
- duration: integer("duration"),
575
- // Request duration in milliseconds
576
- stackTrace: text("stack_trace"),
577
- // Error stack trace for error logs
578
- tags: text("tags", { mode: "json" }),
579
- // Array of tags for categorization
580
- source: text("source"),
581
- // Source component/module that generated the log
582
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
583
- });
584
- var logConfig = sqliteTable("log_config", {
585
- id: text("id").primaryKey(),
586
- category: text("category").notNull().unique(),
587
- enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
588
- level: text("level").notNull().default("info"),
589
- // minimum log level to store
590
- retention: integer("retention").notNull().default(30),
591
- // days to keep logs
592
- maxSize: integer("max_size").default(1e4),
593
- // max number of logs per category
594
- createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
595
- updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
596
- });
597
- var insertSystemLogSchema = createInsertSchema(systemLogs, {
598
- level: (schema) => schema.min(1),
599
- category: (schema) => schema.min(1),
600
- message: (schema) => schema.min(1)
601
- });
602
- var selectSystemLogSchema = createSelectSchema(systemLogs);
603
- var insertLogConfigSchema = createInsertSchema(logConfig, {
604
- category: (schema) => schema.min(1),
605
- level: (schema) => schema.min(1)
606
- });
607
- var selectLogConfigSchema = createSelectSchema(logConfig);
608
- var securityEvents = sqliteTable("security_events", {
609
- id: text("id").primaryKey(),
610
- eventType: text("event_type").notNull(),
611
- severity: text("severity").notNull().default("info"),
612
- userId: text("user_id"),
613
- email: text("email"),
614
- ipAddress: text("ip_address"),
615
- userAgent: text("user_agent"),
616
- countryCode: text("country_code"),
617
- requestPath: text("request_path"),
618
- requestMethod: text("request_method"),
619
- details: text("details", { mode: "json" }),
620
- fingerprint: text("fingerprint"),
621
- blocked: integer("blocked").notNull().default(0),
622
- createdAt: integer("created_at").notNull().$defaultFn(() => Date.now())
623
- });
624
- var insertSecurityEventSchema = createInsertSchema(securityEvents, {
625
- eventType: (schema) => schema.min(1),
626
- severity: (schema) => schema.min(1)
627
- });
628
- var selectSecurityEventSchema = createSelectSchema(securityEvents);
629
- var forms = sqliteTable("forms", {
630
- id: text("id").primaryKey(),
631
- name: text("name").notNull().unique(),
632
- // Machine name (e.g., "contact-form")
633
- displayName: text("display_name").notNull(),
634
- // Human name (e.g., "Contact Form")
635
- description: text("description"),
636
- category: text("category").notNull().default("general"),
637
- // contact, survey, registration, etc.
638
- // Form.io schema (JSON)
639
- formioSchema: text("formio_schema", { mode: "json" }).notNull(),
640
- // Complete Form.io JSON schema
641
- // Settings (JSON)
642
- settings: text("settings", { mode: "json" }),
643
- // emailNotifications, successMessage, etc.
644
- // Status & Management
645
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
646
- isPublic: integer("is_public", { mode: "boolean" }).notNull().default(true),
647
- managed: integer("managed", { mode: "boolean" }).notNull().default(false),
648
- // Metadata
649
- icon: text("icon"),
650
- color: text("color"),
651
- tags: text("tags", { mode: "json" }),
652
- // JSON array
653
- // Stats
654
- submissionCount: integer("submission_count").notNull().default(0),
655
- viewCount: integer("view_count").notNull().default(0),
656
- // Ownership
657
- createdBy: text("created_by").references(() => users.id),
658
- updatedBy: text("updated_by").references(() => users.id),
659
- // Timestamps
660
- createdAt: integer("created_at").notNull(),
661
- updatedAt: integer("updated_at").notNull()
662
- });
663
- var formSubmissions = sqliteTable("form_submissions", {
664
- id: text("id").primaryKey(),
665
- formId: text("form_id").notNull().references(() => forms.id, { onDelete: "cascade" }),
666
- // Submission data
667
- submissionData: text("submission_data", { mode: "json" }).notNull(),
668
- // The actual form data
669
- // Submission metadata
670
- status: text("status").notNull().default("pending"),
671
- // pending, reviewed, approved, rejected, spam
672
- submissionNumber: integer("submission_number"),
673
- // User information
674
- userId: text("user_id").references(() => users.id),
675
- userEmail: text("user_email"),
676
- // Tracking
677
- ipAddress: text("ip_address"),
678
- userAgent: text("user_agent"),
679
- referrer: text("referrer"),
680
- utmSource: text("utm_source"),
681
- utmMedium: text("utm_medium"),
682
- utmCampaign: text("utm_campaign"),
683
- // Review/Processing
684
- reviewedBy: text("reviewed_by").references(() => users.id),
685
- reviewedAt: integer("reviewed_at"),
686
- reviewNotes: text("review_notes"),
687
- // Flags
688
- isSpam: integer("is_spam", { mode: "boolean" }).notNull().default(false),
689
- isArchived: integer("is_archived", { mode: "boolean" }).notNull().default(false),
690
- // Content integration
691
- contentId: text("content_id").references(() => content.id),
692
- // Links submission to its content item
693
- // Timestamps
694
- submittedAt: integer("submitted_at").notNull(),
695
- updatedAt: integer("updated_at").notNull()
696
- });
697
- var formFiles = sqliteTable("form_files", {
698
- id: text("id").primaryKey(),
699
- submissionId: text("submission_id").notNull().references(() => formSubmissions.id, { onDelete: "cascade" }),
700
- mediaId: text("media_id").notNull().references(() => media.id, { onDelete: "cascade" }),
701
- fieldName: text("field_name").notNull(),
702
- // Form field that uploaded this file
703
- uploadedAt: integer("uploaded_at").notNull()
704
- });
705
- var insertFormSchema = createInsertSchema(forms);
706
- var selectFormSchema = createSelectSchema(forms);
707
- var insertFormSubmissionSchema = createInsertSchema(formSubmissions);
708
- var selectFormSubmissionSchema = createSelectSchema(formSubmissions);
709
- var insertFormFileSchema = createInsertSchema(formFiles);
710
- var selectFormFileSchema = createSelectSchema(formFiles);
711
8
  var Logger = class {
712
9
  db;
713
10
  enabled = true;
@@ -1017,104 +314,82 @@ function initLogger(database) {
1017
314
  }
1018
315
 
1019
316
  // src/services/cache.ts
317
+ function toPluginConfig(config) {
318
+ return {
319
+ ttl: config.ttl,
320
+ namespace: config.keyPrefix,
321
+ // KV survives isolate evictions — required for the dashboard to show non-zero
322
+ // counts across requests in production. Falls back to memory-only when the
323
+ // CACHE_KV binding is missing (cache plugin handles the null case).
324
+ kvEnabled: true,
325
+ memoryEnabled: true,
326
+ invalidateOn: [],
327
+ version: "v1"
328
+ };
329
+ }
1020
330
  var CacheService = class {
1021
331
  config;
1022
- memoryCache = /* @__PURE__ */ new Map();
332
+ inner;
333
+ // Tracks expiry times so getWithSource can distinguish 'none' vs 'expired'.
334
+ // The plugin returns source:'miss' for both cases; we differentiate here.
335
+ keyExpiry = /* @__PURE__ */ new Map();
1023
336
  constructor(config) {
1024
337
  this.config = config;
338
+ this.inner = getCacheService(toPluginConfig(config));
1025
339
  }
1026
- /**
1027
- * Generate cache key with prefix
1028
- */
1029
340
  generateKey(type, identifier) {
1030
341
  const parts = [this.config.keyPrefix, type];
1031
- if (identifier) {
1032
- parts.push(identifier);
1033
- }
342
+ if (identifier !== void 0 && identifier !== "") parts.push(identifier);
1034
343
  return parts.join(":");
1035
344
  }
1036
- /**
1037
- * Get value from cache
1038
- */
1039
345
  async get(key) {
1040
- const cached = this.memoryCache.get(key);
1041
- if (!cached) {
1042
- return null;
1043
- }
1044
- if (Date.now() > cached.expires) {
1045
- this.memoryCache.delete(key);
1046
- return null;
1047
- }
1048
- return cached.value;
346
+ return this.inner.get(key);
1049
347
  }
1050
- /**
1051
- * Get value from cache with source information
1052
- */
1053
348
  async getWithSource(key) {
1054
- const cached = this.memoryCache.get(key);
1055
- if (!cached) {
1056
- return {
1057
- hit: false,
1058
- data: null,
1059
- source: "none"
349
+ const result = await this.inner.getWithSource(key);
350
+ if (result.hit) {
351
+ const out = {
352
+ hit: true,
353
+ data: result.data,
354
+ source: result.source
1060
355
  };
356
+ if (result.ttl !== void 0) out.ttl = result.ttl;
357
+ return out;
1061
358
  }
1062
- if (Date.now() > cached.expires) {
1063
- this.memoryCache.delete(key);
1064
- return {
1065
- hit: false,
1066
- data: null,
1067
- source: "expired"
1068
- };
359
+ const expiry = this.keyExpiry.get(key);
360
+ if (expiry !== void 0) {
361
+ this.keyExpiry.delete(key);
362
+ return { hit: false, data: null, source: "expired" };
1069
363
  }
1070
- return {
1071
- hit: true,
1072
- data: cached.value,
1073
- source: "memory",
1074
- ttl: (cached.expires - Date.now()) / 1e3
1075
- // TTL in seconds
1076
- };
364
+ return { hit: false, data: null, source: "none" };
1077
365
  }
1078
- /**
1079
- * Set value in cache
1080
- */
1081
366
  async set(key, value, ttl) {
1082
- const expires = Date.now() + (ttl || this.config.ttl) * 1e3;
1083
- this.memoryCache.set(key, { value, expires });
367
+ const effectiveTtl = ttl ?? this.config.ttl;
368
+ this.keyExpiry.set(key, Date.now() + effectiveTtl * 1e3);
369
+ await this.inner.set(key, value, ttl !== void 0 ? { ttl } : void 0);
1084
370
  }
1085
- /**
1086
- * Delete specific key from cache
1087
- */
1088
371
  async delete(key) {
1089
- this.memoryCache.delete(key);
372
+ this.keyExpiry.delete(key);
373
+ await this.inner.delete(key);
1090
374
  }
1091
- /**
1092
- * Invalidate cache keys matching a pattern
1093
- * For memory cache, we do simple string matching
1094
- */
1095
375
  async invalidate(pattern) {
1096
- const regexPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");
1097
- const regex = new RegExp(`^${regexPattern}$`);
1098
- for (const key of this.memoryCache.keys()) {
1099
- if (regex.test(key)) {
1100
- this.memoryCache.delete(key);
376
+ if (pattern.includes("*") || pattern.includes("?")) {
377
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$");
378
+ for (const k of this.keyExpiry.keys()) {
379
+ if (regex.test(k)) this.keyExpiry.delete(k);
1101
380
  }
381
+ } else {
382
+ this.keyExpiry.delete(pattern);
1102
383
  }
384
+ await this.inner.invalidate(pattern);
1103
385
  }
1104
- /**
1105
- * Clear all cache
1106
- */
1107
386
  async clear() {
1108
- this.memoryCache.clear();
387
+ this.keyExpiry.clear();
388
+ await this.inner.clear();
1109
389
  }
1110
- /**
1111
- * Get value from cache or set it using a callback
1112
- */
1113
390
  async getOrSet(key, callback, ttl) {
1114
391
  const cached = await this.get(key);
1115
- if (cached !== null) {
1116
- return cached;
1117
- }
392
+ if (cached !== null) return cached;
1118
393
  const value = await callback();
1119
394
  await this.set(key, value, ttl);
1120
395
  return value;
@@ -1142,86 +417,96 @@ var CACHE_CONFIGS = {
1142
417
  keyPrefix: "collection"
1143
418
  }
1144
419
  };
1145
- function getCacheService(config) {
420
+ function getCacheService2(config) {
1146
421
  return new CacheService(config);
1147
422
  }
1148
423
 
1149
424
  // src/services/settings.ts
425
+ var TYPE_ID = "site_settings";
426
+ var TENANT = "default";
1150
427
  var SettingsService = class {
1151
428
  constructor(db) {
1152
429
  this.db = db;
1153
430
  }
1154
431
  /**
1155
- * Get a setting value by category and key
432
+ * Get settings document for a category (general or security)
1156
433
  */
1157
- async getSetting(category, key) {
434
+ async getSettingsDocument(category) {
1158
435
  try {
1159
- const result = await this.db.prepare("SELECT value FROM settings WHERE category = ? AND key = ?").bind(category, key).first();
1160
- if (!result) {
436
+ const row = await this.db.prepare(`
437
+ SELECT data FROM documents
438
+ WHERE type_id = ? AND slug = ? AND tenant_id = ? AND is_current_draft = 1 AND deleted_at IS NULL
439
+ `).bind(TYPE_ID, category, TENANT).first();
440
+ if (!row) {
1161
441
  return null;
1162
442
  }
1163
- return JSON.parse(result.value);
443
+ return JSON.parse(row.data);
1164
444
  } catch (error) {
1165
- console.error(`Error getting setting ${category}.${key}:`, error);
445
+ console.error(`Error getting settings document for ${category}:`, error);
1166
446
  return null;
1167
447
  }
1168
448
  }
1169
449
  /**
1170
- * Get all settings for a category
450
+ * Save settings document for a category (general or security)
1171
451
  */
1172
- async getCategorySettings(category) {
452
+ async saveSettingsDocument(category, data) {
1173
453
  try {
1174
- const { results } = await this.db.prepare("SELECT key, value FROM settings WHERE category = ?").bind(category).all();
1175
- const settings = {};
1176
- for (const row of results || []) {
1177
- const r = row;
1178
- settings[r.key] = JSON.parse(r.value);
1179
- }
1180
- return settings;
1181
- } catch (error) {
1182
- console.error(`Error getting category settings for ${category}:`, error);
1183
- return {};
1184
- }
1185
- }
1186
- /**
1187
- * Set a setting value
1188
- */
1189
- async setSetting(category, key, value) {
1190
- try {
1191
- const now = Date.now();
1192
- const jsonValue = JSON.stringify(value);
454
+ const now = Math.floor(Date.now() / 1e3);
455
+ const jsonData = JSON.stringify(data);
1193
456
  await this.db.prepare(`
1194
- INSERT INTO settings (id, category, key, value, created_at, updated_at)
1195
- VALUES (?, ?, ?, ?, ?, ?)
1196
- ON CONFLICT(category, key) DO UPDATE SET
1197
- value = excluded.value,
1198
- updated_at = excluded.updated_at
1199
- `).bind(crypto.randomUUID(), category, key, jsonValue, now, now).run();
1200
- return true;
1201
- } catch (error) {
1202
- console.error(`Error setting ${category}.${key}:`, error);
1203
- return false;
1204
- }
1205
- }
1206
- /**
1207
- * Set multiple settings at once
1208
- */
1209
- async setMultipleSettings(category, settings) {
1210
- try {
1211
- const now = Date.now();
1212
- for (const [key, value] of Object.entries(settings)) {
1213
- const jsonValue = JSON.stringify(value);
457
+ INSERT OR IGNORE INTO document_types (id, name, display_name, description, schema, source, is_system, is_active, created_at, updated_at)
458
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
459
+ `).bind(
460
+ TYPE_ID,
461
+ TYPE_ID,
462
+ "Site Settings",
463
+ "Global site configuration settings",
464
+ "{}",
465
+ "system",
466
+ 1,
467
+ 1,
468
+ now,
469
+ now
470
+ ).run();
471
+ const existing = await this.db.prepare(`
472
+ SELECT id FROM documents
473
+ WHERE type_id = ? AND slug = ? AND tenant_id = ? AND is_current_draft = 1 AND deleted_at IS NULL
474
+ `).bind(TYPE_ID, category, TENANT).first();
475
+ if (existing) {
1214
476
  await this.db.prepare(`
1215
- INSERT INTO settings (id, category, key, value, created_at, updated_at)
1216
- VALUES (?, ?, ?, ?, ?, ?)
1217
- ON CONFLICT(category, key) DO UPDATE SET
1218
- value = excluded.value,
1219
- updated_at = excluded.updated_at
1220
- `).bind(crypto.randomUUID(), category, key, jsonValue, now, now).run();
477
+ UPDATE documents
478
+ SET data = ?, updated_at = ?
479
+ WHERE id = ? AND is_current_draft = 1
480
+ `).bind(jsonData, now, existing.id).run();
481
+ } else {
482
+ const docId = crypto.randomUUID();
483
+ const rootId = docId;
484
+ const title = category === "general" ? "General Settings" : "Security Settings";
485
+ await this.db.prepare(`
486
+ INSERT INTO documents (
487
+ id, root_id, type_id, version_number, is_current_draft, is_published, status,
488
+ parent_root_id, slug, title, tenant_id, locale, translation_group_id,
489
+ data, metadata, created_at, updated_at
490
+ ) VALUES (
491
+ ?, ?, ?, 1, 1, 1, 'published',
492
+ '', ?, ?, ?, 'default', '',
493
+ ?, '{}', ?, ?
494
+ )
495
+ `).bind(
496
+ docId,
497
+ rootId,
498
+ TYPE_ID,
499
+ category,
500
+ title,
501
+ TENANT,
502
+ jsonData,
503
+ now,
504
+ now
505
+ ).run();
1221
506
  }
1222
507
  return true;
1223
508
  } catch (error) {
1224
- console.error(`Error setting multiple settings for ${category}:`, error);
509
+ console.error(`Error saving settings document for ${category}:`, error);
1225
510
  return false;
1226
511
  }
1227
512
  }
@@ -1229,48 +514,41 @@ var SettingsService = class {
1229
514
  * Get general settings with defaults
1230
515
  */
1231
516
  async getGeneralSettings(userEmail) {
1232
- const settings = await this.getCategorySettings("general");
517
+ const settings = await this.getSettingsDocument("general");
1233
518
  return {
1234
- siteName: settings.siteName || "SonicJS AI",
1235
- siteDescription: settings.siteDescription || "A modern headless CMS powered by AI",
1236
- adminEmail: settings.adminEmail || userEmail || "admin@example.com",
1237
- timezone: settings.timezone || "UTC",
1238
- language: settings.language || "en",
1239
- maintenanceMode: settings.maintenanceMode || false
519
+ siteName: settings?.siteName || "SonicJS AI",
520
+ siteDescription: settings?.siteDescription || "A modern headless CMS powered by AI",
521
+ adminEmail: settings?.adminEmail || userEmail || "admin@example.com",
522
+ timezone: settings?.timezone || "UTC",
523
+ language: settings?.language || "en",
524
+ maintenanceMode: settings?.maintenanceMode || false
1240
525
  };
1241
526
  }
1242
527
  /**
1243
528
  * Save general settings
1244
529
  */
1245
530
  async saveGeneralSettings(settings) {
1246
- const settingsToSave = {};
1247
- if (settings.siteName !== void 0) settingsToSave.siteName = settings.siteName;
1248
- if (settings.siteDescription !== void 0) settingsToSave.siteDescription = settings.siteDescription;
1249
- if (settings.adminEmail !== void 0) settingsToSave.adminEmail = settings.adminEmail;
1250
- if (settings.timezone !== void 0) settingsToSave.timezone = settings.timezone;
1251
- if (settings.language !== void 0) settingsToSave.language = settings.language;
1252
- if (settings.maintenanceMode !== void 0) settingsToSave.maintenanceMode = settings.maintenanceMode;
1253
- return await this.setMultipleSettings("general", settingsToSave);
531
+ const existing = await this.getSettingsDocument("general");
532
+ const merged = { ...existing, ...settings };
533
+ return await this.saveSettingsDocument("general", merged);
1254
534
  }
1255
535
  /**
1256
536
  * Get security settings with defaults
1257
537
  */
1258
538
  async getSecuritySettings() {
1259
- const settings = await this.getCategorySettings("security");
539
+ const settings = await this.getSettingsDocument("security");
1260
540
  return {
1261
- jwtExpiresIn: settings.jwtExpiresIn || "30d",
1262
- jwtRefreshGraceSeconds: typeof settings.jwtRefreshGraceSeconds === "number" ? settings.jwtRefreshGraceSeconds : 60 * 60 * 24 * 7
541
+ jwtExpiresIn: settings?.jwtExpiresIn || "30d",
542
+ jwtRefreshGraceSeconds: typeof settings?.jwtRefreshGraceSeconds === "number" ? settings.jwtRefreshGraceSeconds : 60 * 60 * 24 * 7
1263
543
  };
1264
544
  }
1265
545
  /**
1266
546
  * Save security settings
1267
547
  */
1268
548
  async saveSecuritySettings(settings) {
1269
- const settingsToSave = {};
1270
- if (settings.jwtExpiresIn !== void 0) settingsToSave.jwtExpiresIn = settings.jwtExpiresIn;
1271
- if (settings.jwtRefreshGraceSeconds !== void 0)
1272
- settingsToSave.jwtRefreshGraceSeconds = settings.jwtRefreshGraceSeconds;
1273
- return await this.setMultipleSettings("security", settingsToSave);
549
+ const existing = await this.getSettingsDocument("security");
550
+ const merged = { ...existing, ...settings };
551
+ return await this.saveSettingsDocument("security", merged);
1274
552
  }
1275
553
  };
1276
554
 
@@ -1567,6 +845,11 @@ var CATEGORY_INFO = {
1567
845
  title: "Files",
1568
846
  description: "File serving from R2 storage",
1569
847
  icon: "📁"
848
+ },
849
+ "Collections": {
850
+ title: "Collections",
851
+ description: "Per-collection REST endpoints (auto-generated from registered collections)",
852
+ icon: "📚"
1570
853
  }
1571
854
  };
1572
855
  var ROUTE_METADATA = {
@@ -1611,7 +894,7 @@ var ROUTE_METADATA = {
1611
894
  "DELETE /admin/api/collections/:id/fields/:fieldId": { description: "Remove a field from a collection", category: "Admin", authentication: true },
1612
895
  "POST /admin/api/collections/:id/fields/reorder": { description: "Reorder fields in a collection", category: "Admin", authentication: true },
1613
896
  "GET /admin/api/migrations/status": { description: "Get database migration status", category: "Admin", authentication: true },
1614
- "POST /admin/api/migrations/run": { description: "Run pending database migrations", category: "Admin", authentication: true },
897
+ "POST /admin/api/migrations/run": { description: "Explain how to run D1 migrations with Wrangler", category: "Admin", authentication: true },
1615
898
  "GET /admin/api/content": { description: "List content items with filtering and pagination", category: "Admin", authentication: true },
1616
899
  "GET /admin/api/content/:id": { description: "Get a content item for admin editing", category: "Admin", authentication: true },
1617
900
  "POST /admin/api/content": { description: "Create content via admin API", category: "Admin", authentication: true },
@@ -1699,6 +982,12 @@ var ROUTE_METADATA = {
1699
982
  "GET /api": { description: "API root - returns API information and available endpoints", category: "System", authentication: false },
1700
983
  "GET /api/system/info": { description: "Get system information and version", category: "System", authentication: false },
1701
984
  "GET /api/system/schema": { description: "Get database schema information", category: "System", authentication: false },
985
+ // Collection shorthand routes
986
+ "GET /api/:collection": { description: "List items from a collection (shorthand route)", category: "Collections", authentication: false },
987
+ "GET /api/:collection/:id": { description: "Get a single item by ID from a collection", category: "Collections", authentication: false },
988
+ "POST /api/:collection": { description: "Create an item in a collection", category: "Collections", authentication: true },
989
+ "PUT /api/:collection/:id": { description: "Update an item in a collection", category: "Collections", authentication: true },
990
+ "DELETE /api/:collection/:id": { description: "Delete an item from a collection", category: "Collections", authentication: true },
1702
991
  // File serving
1703
992
  "GET /files/*": { description: "Serve files from R2 storage (public access)", category: "Files", authentication: false },
1704
993
  // Database tools
@@ -1776,6 +1065,7 @@ function inferCategory(path) {
1776
1065
  if (path.startsWith("/forms/")) return "Forms";
1777
1066
  if (path.startsWith("/files/")) return "Files";
1778
1067
  if (path === "/health" || path.startsWith("/api")) return "System";
1068
+ if (path.match(/^\/api\/[^/]+(\/:id)?$/) && !path.startsWith("/api/content") && !path.startsWith("/api/collections") && !path.startsWith("/api/media") && !path.startsWith("/api/search") && !path.startsWith("/api/system") && !path.startsWith("/api/health") && !path.startsWith("/api/documents") && !path.startsWith("/api/forms")) return "Collections";
1779
1069
  return "Other";
1780
1070
  }
1781
1071
  function inferAuth(path) {
@@ -1838,6 +1128,6 @@ function buildRouteList(app) {
1838
1128
  }
1839
1129
  }
1840
1130
 
1841
- export { CACHE_CONFIGS, CATEGORY_INFO, CacheService, Logger, SettingsService, TelemetryService, apiTokens, buildRouteList, collections, content, contentVersions, createInstallationIdentity, getAppInstance, getCacheService, getLogger, getTelemetryService, initLogger, initTelemetry, insertCollectionSchema, insertContentSchema, insertLogConfigSchema, insertMediaSchema, insertPluginActivityLogSchema, insertPluginAssetSchema, insertPluginHookSchema, insertPluginRouteSchema, insertPluginSchema, insertSystemLogSchema, insertUserSchema, insertWorkflowHistorySchema, logConfig, media, pluginActivityLog, pluginAssets, pluginHooks, pluginRoutes, plugins, schema_exports, selectCollectionSchema, selectContentSchema, selectLogConfigSchema, selectMediaSchema, selectPluginActivityLogSchema, selectPluginAssetSchema, selectPluginHookSchema, selectPluginRouteSchema, selectPluginSchema, selectSystemLogSchema, selectUserSchema, selectWorkflowHistorySchema, setAppInstance, systemLogs, users, workflowHistory };
1842
- //# sourceMappingURL=chunk-QFWHAFEO.js.map
1843
- //# sourceMappingURL=chunk-QFWHAFEO.js.map
1131
+ export { CACHE_CONFIGS, CATEGORY_INFO, CacheService, Logger, SettingsService, TelemetryService, buildRouteList, createInstallationIdentity, getAppInstance, getCacheService2 as getCacheService, getLogger, getTelemetryService, initLogger, initTelemetry, setAppInstance };
1132
+ //# sourceMappingURL=chunk-ZEZ245PW.js.map
1133
+ //# sourceMappingURL=chunk-ZEZ245PW.js.map