opacacms 0.2.0 → 0.3.0

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 (187) hide show
  1. package/README.md +31 -22
  2. package/dist/admin/auth-client.d.ts +39 -39
  3. package/dist/admin/index.d.ts +2 -2
  4. package/dist/admin/index.js +15 -10520
  5. package/dist/admin/plugin-client.d.ts +65 -0
  6. package/dist/admin/react.d.ts +2 -2
  7. package/dist/admin/react.js +34 -4
  8. package/dist/admin/stores/ui.d.ts +19 -4
  9. package/dist/admin/ui/components/PluginSettingsForm.d.ts +2 -2
  10. package/dist/admin/ui/components/custom-alert.d.ts +7 -0
  11. package/dist/admin/ui/components/{DetailSheet.d.ts → detail-sheet.d.ts} +1 -2
  12. package/dist/admin/ui/components/fields/FieldLabel.d.ts +1 -1
  13. package/dist/admin/ui/components/fields/RelationshipField.d.ts +1 -1
  14. package/dist/admin/ui/components/media/AssetManagerModal.d.ts +2 -2
  15. package/dist/admin/ui/components/plugin-iframe.d.ts +7 -0
  16. package/dist/admin/ui/components/ui/accordion.d.ts +17 -7
  17. package/dist/admin/ui/components/ui/alert-dialog.d.ts +16 -12
  18. package/dist/admin/ui/components/ui/button.d.ts +11 -7
  19. package/dist/admin/ui/components/ui/relationship.d.ts +1 -1
  20. package/dist/admin/ui/components/ui/sheet.d.ts +14 -27
  21. package/dist/admin/ui/components/ui/tooltip.d.ts +7 -0
  22. package/dist/admin/ui/components/versions-sheet.d.ts +4 -5
  23. package/dist/admin/ui/views/collection-list-view.d.ts +1 -1
  24. package/dist/admin/ui/views/dashboard-view.d.ts +1 -1
  25. package/dist/admin/ui/views/media-registry-view.d.ts +3 -3
  26. package/dist/admin/ui/views/settings-view.d.ts +2 -2
  27. package/dist/admin/vue.js +27 -4
  28. package/dist/admin/webcomponent.js +20 -2
  29. package/dist/admin.css +1 -1
  30. package/dist/auth/index.d.ts +43 -43
  31. package/dist/{chunk-7y1nbmw6.js → chunk-1bd7fz7n.js} +32 -2
  32. package/dist/chunk-1qm0m8r8.js +413 -0
  33. package/dist/chunk-2k3ysje3.js +31 -0
  34. package/dist/chunk-3j9zjfmn.js +376 -0
  35. package/dist/{chunk-byq8g0rd.js → chunk-48ywpd0a.js} +16 -22
  36. package/dist/{chunk-esrg9qj0.js → chunk-5422w4eq.js} +70 -54
  37. package/dist/chunk-56n342hs.js +95 -0
  38. package/dist/chunk-5b8r0v8c.js +47 -0
  39. package/dist/chunk-63yg00vx.js +263 -0
  40. package/dist/{chunk-8sqjbsgt.js → chunk-6bywt602.js} +26 -1
  41. package/dist/{chunk-v9z61v3g.js → chunk-6qs0g65f.js} +43 -3
  42. package/dist/chunk-7rr5p01g.js +581 -0
  43. package/dist/{chunk-51z3x7kq.js → chunk-a3qae86h.js} +1 -1
  44. package/dist/{chunk-3rdhbedb.js → chunk-adq2b75c.js} +2 -2
  45. package/dist/chunk-d0tb1xjw.js +93 -0
  46. package/dist/chunk-d7cgd6vn.js +318 -0
  47. package/dist/{chunk-0bq155dy.js → chunk-e0g6gn7n.js} +89 -100
  48. package/dist/chunk-ec4jhybj.js +1137 -0
  49. package/dist/chunk-fatyf6f7.js +221 -0
  50. package/dist/{chunk-526a3gqx.js → chunk-fnsf1dfm.js} +1 -1
  51. package/dist/chunk-g9bxb6h0.js +205 -0
  52. package/dist/chunk-gyaf5kgf.js +10 -0
  53. package/dist/{chunk-9kxpbcb1.js → chunk-h6dhexzr.js} +16 -7
  54. package/dist/{chunk-dykn5hr6.js → chunk-j8js1y0h.js} +31 -74
  55. package/dist/{chunk-t0zg026p.js → chunk-jq1drsen.js} +12 -1
  56. package/dist/{chunk-b3kr8w41.js → chunk-m24yqkeq.js} +38 -26
  57. package/dist/chunk-m5ems3hh.js +410 -0
  58. package/dist/{chunk-8scgdznr.js → chunk-m83ybzf8.js} +15 -18
  59. package/dist/chunk-majsbncm.js +98 -0
  60. package/dist/chunk-mp2gt9yh.js +237 -0
  61. package/dist/chunk-n1twhqmf.js +54 -0
  62. package/dist/{chunk-gmee4mdc.js → chunk-naqcqj8n.js} +92 -106
  63. package/dist/chunk-q5sb5dcr.js +15 -0
  64. package/dist/{chunk-d1asgtke.js → chunk-qhdsjek6.js} +90 -121
  65. package/dist/{chunk-0gtxnxmd.js → chunk-qsh2nqz3.js} +85 -105
  66. package/dist/chunk-r0ms5tk1.js +76 -0
  67. package/dist/chunk-rwqwsanx.js +75 -0
  68. package/dist/chunk-sqsfk9p4.js +700 -0
  69. package/dist/{chunk-5gvbp2qa.js → chunk-x7bnzswh.js} +25 -18
  70. package/dist/{chunk-kc4jfnv7.js → chunk-z3ffn2b7.js} +851 -324
  71. package/dist/cli/commands/dev.d.ts +8 -0
  72. package/dist/cli/commands/doctor.d.ts +8 -0
  73. package/dist/cli/commands/generate.d.ts +26 -0
  74. package/dist/cli/commands/init.d.ts +13 -1
  75. package/dist/cli/commands/migrate.d.ts +33 -0
  76. package/dist/cli/commands/plugin.d.ts +13 -0
  77. package/dist/cli/commands/seed.d.ts +21 -0
  78. package/dist/cli/{commands/migrate-commands.d.ts → core/migrations/migrate-logic.d.ts} +2 -2
  79. package/dist/cli/core/migrations/schema-diff-engine.d.ts +12 -0
  80. package/dist/cli/core/migrations/schema-diff.d.ts +11 -0
  81. package/dist/cli/{seeding.d.ts → core/seeding/auto-seed.d.ts} +7 -4
  82. package/dist/cli/core/seeding/seed-logic.d.ts +2 -0
  83. package/dist/cli/index.d.ts +4 -0
  84. package/dist/cli/index.js +6 -170
  85. package/dist/client/RichText.d.ts +5 -0
  86. package/dist/client/rich-text-utils.d.ts +5 -0
  87. package/dist/client.js +3 -2
  88. package/dist/config.d.ts +3 -3
  89. package/dist/db/adapter.d.ts +2 -2
  90. package/dist/db/better-sqlite.d.ts +3 -3
  91. package/dist/db/better-sqlite.js +6 -5
  92. package/dist/db/bun-sqlite.d.ts +3 -3
  93. package/dist/db/bun-sqlite.js +6 -5
  94. package/dist/db/d1.d.ts +13 -7
  95. package/dist/db/d1.js +6 -5
  96. package/dist/db/index.d.ts +2 -2
  97. package/dist/db/index.js +10 -12
  98. package/dist/db/kysely/factory.d.ts +29 -0
  99. package/dist/db/kysely/plugins/audit-logging.d.ts +48 -0
  100. package/dist/db/kysely/plugins/auto-timestamps.d.ts +38 -0
  101. package/dist/db/kysely/plugins/cursor-pagination.d.ts +42 -0
  102. package/dist/db/kysely/plugins/deadlock-handler.d.ts +47 -0
  103. package/dist/db/kysely/plugins/draft-swapper.d.ts +33 -0
  104. package/dist/db/kysely/plugins/field-masking.d.ts +45 -0
  105. package/dist/db/kysely/plugins/fts-normalizer.d.ts +38 -0
  106. package/dist/db/kysely/plugins/i18n-fallback.d.ts +48 -0
  107. package/dist/db/kysely/plugins/id-generation.d.ts +42 -0
  108. package/dist/db/kysely/plugins/index.d.ts +16 -0
  109. package/dist/db/kysely/plugins/json-flattener.d.ts +38 -0
  110. package/dist/db/kysely/plugins/relationship-preloading.d.ts +39 -0
  111. package/dist/db/kysely/plugins/slug-generation.d.ts +37 -0
  112. package/dist/db/kysely/plugins/soft-delete.d.ts +42 -0
  113. package/dist/db/kysely/plugins/tree-resolver.d.ts +39 -0
  114. package/dist/db/kysely/plugins/virtual-field-resolver.d.ts +54 -0
  115. package/dist/db/kysely/plugins/zod-coercion.d.ts +34 -0
  116. package/dist/db/kysely/snapshot/snapshot-manager.d.ts +18 -0
  117. package/dist/db/postgres.d.ts +4 -4
  118. package/dist/db/postgres.js +6 -5
  119. package/dist/db/sqlite.d.ts +3 -3
  120. package/dist/db/sqlite.js +6 -5
  121. package/dist/index.d.ts +3 -0
  122. package/dist/index.js +161 -7
  123. package/dist/runtimes/bun.js +9 -6
  124. package/dist/runtimes/cloudflare-workers.d.ts +3 -1
  125. package/dist/runtimes/cloudflare-workers.js +36 -7
  126. package/dist/runtimes/next.js +8 -5
  127. package/dist/runtimes/node.js +9 -6
  128. package/dist/schema/collection.d.ts +116 -70
  129. package/dist/schema/compiler.d.ts +6 -0
  130. package/dist/schema/global.d.ts +38 -71
  131. package/dist/schema/index.d.ts +5 -4
  132. package/dist/schema/index.js +35 -550
  133. package/dist/schema/zod.d.ts +564 -0
  134. package/dist/server/admin-router.d.ts +1 -1
  135. package/dist/server/collection-router.d.ts +1 -1
  136. package/dist/server/graphql.d.ts +6 -0
  137. package/dist/server/handlers.d.ts +25 -7
  138. package/dist/server/middlewares/auth.d.ts +1 -1
  139. package/dist/server/plugins-loader.d.ts +1 -1
  140. package/dist/server/router.d.ts +2 -2
  141. package/dist/server/routers/admin.d.ts +1 -1
  142. package/dist/server/routers/auth.d.ts +1 -1
  143. package/dist/server/routers/collections.d.ts +4 -1
  144. package/dist/server/routers/plugins.d.ts +2 -2
  145. package/dist/server/setup-middlewares.d.ts +1 -1
  146. package/dist/server/system-router.d.ts +1 -1
  147. package/dist/server.js +11 -6
  148. package/dist/storage/adapters/cloudflare-r2.d.ts +11 -2
  149. package/dist/storage/index.js +39 -30
  150. package/dist/types.d.ts +255 -44
  151. package/dist/utils/context.d.ts +14 -0
  152. package/dist/utils/logger.d.ts +2 -0
  153. package/dist/utils/string.d.ts +10 -0
  154. package/dist/utils/webhooks-engine.d.ts +24 -0
  155. package/dist/validation.d.ts +67 -1
  156. package/dist/validator.d.ts +1 -0
  157. package/package.json +36 -33
  158. package/src/cli/index.ts +117 -0
  159. package/dist/chunk-6qq3ne6b.js +0 -288
  160. package/dist/chunk-6v1fw7q7.js +0 -126
  161. package/dist/chunk-7a9kn0np.js +0 -116
  162. package/dist/chunk-bexcv7xe.js +0 -36
  163. package/dist/chunk-d3ffeqp9.js +0 -87
  164. package/dist/chunk-fj19qccp.js +0 -78
  165. package/dist/chunk-j53pz21t.js +0 -20
  166. package/dist/chunk-mkn49zmy.js +0 -102
  167. package/dist/chunk-qb6ztvw9.js +0 -17
  168. package/dist/chunk-r39em4yj.js +0 -29
  169. package/dist/chunk-rsf0tpy1.js +0 -8
  170. package/dist/chunk-srsac177.js +0 -85
  171. package/dist/chunk-swtcpvhf.js +0 -2442
  172. package/dist/chunk-twpvxfce.js +0 -64
  173. package/dist/chunk-ywm4t2gm.js +0 -19
  174. package/dist/cli/commands/plugin-sync.d.ts +0 -1
  175. package/dist/cli/commands/seed-command.d.ts +0 -2
  176. package/dist/plugins/ui-bridge.d.ts +0 -12
  177. package/dist/schema/fields/base.d.ts +0 -84
  178. package/dist/schema/fields/index.d.ts +0 -147
  179. package/dist/schema/infer.d.ts +0 -55
  180. /package/dist/admin/ui/components/{ColumnVisibilityToggle.d.ts → column-visibility-toggle.d.ts} +0 -0
  181. /package/dist/admin/ui/components/{DataDetailView.d.ts → data-detail-view.d.ts} +0 -0
  182. /package/dist/cli/{d1-mock.d.ts → core/mocks/d1-mock.d.ts} +0 -0
  183. /package/dist/cli/{r2-mock.d.ts → core/mocks/r2-mock.d.ts} +0 -0
  184. /package/dist/cli/{commands → core/plugins}/plugin-build.d.ts +0 -0
  185. /package/dist/cli/{commands → core/plugins}/plugin-init.d.ts +0 -0
  186. /package/dist/cli/{commands → core/types}/generate-types.d.ts +0 -0
  187. /package/dist/{schema/fields/validation.test.d.ts → cli/seeding.test.d.ts} +0 -0
@@ -3,10 +3,13 @@ import {
3
3
  flattenPayload,
4
4
  pushSchema,
5
5
  unflattenRow
6
- } from "./chunk-dykn5hr6.js";
6
+ } from "./chunk-j8js1y0h.js";
7
7
  import {
8
8
  BaseDatabaseAdapter
9
9
  } from "./chunk-s8mqwnm1.js";
10
+ import {
11
+ requestContext
12
+ } from "./chunk-q5sb5dcr.js";
10
13
  import {
11
14
  flattenFields,
12
15
  getRelationalFields,
@@ -14,20 +17,25 @@ import {
14
17
  } from "./chunk-qxt9vge8.js";
15
18
  import {
16
19
  logger
17
- } from "./chunk-t0zg026p.js";
20
+ } from "./chunk-jq1drsen.js";
21
+ import {
22
+ __require
23
+ } from "./chunk-6bywt602.js";
18
24
 
19
25
  // src/db/sqlite.ts
20
26
  import fs from "node:fs/promises";
21
27
  import path from "node:path";
22
- import { createRequire } from "node:module";
23
- import { CompiledQuery, FileMigrationProvider, Kysely, Migrator, SqliteDialect } from "kysely";
24
- var require2 = createRequire(import.meta.url);
25
- var Database = require2("better-sqlite3");
26
-
28
+ import {
29
+ CompiledQuery,
30
+ FileMigrationProvider,
31
+ Migrator,
32
+ SqliteDialect
33
+ } from "kysely";
27
34
  class SQLiteAdapter extends BaseDatabaseAdapter {
35
+ path;
28
36
  name = "sqlite";
29
37
  _rawDb;
30
- _db;
38
+ _db = null;
31
39
  _collections = [];
32
40
  _globals = [];
33
41
  push;
@@ -37,70 +45,48 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
37
45
  return this._rawDb;
38
46
  }
39
47
  get db() {
48
+ if (!this._db)
49
+ throw new Error("Database not connected. Call connect() first.");
40
50
  return this._db;
41
51
  }
42
52
  constructor(path2, options) {
43
53
  super();
44
- this._rawDb = new Database(path2);
45
- this._db = new Kysely({
46
- dialect: new SqliteDialect({
47
- database: this._rawDb
48
- })
49
- });
54
+ this.path = path2;
50
55
  this.push = options?.push ?? true;
51
56
  this.pushDestructive = options?.pushDestructive ?? false;
52
57
  this.migrationDir = options?.migrationDir ?? "./migrations";
53
58
  }
54
- async connect() {}
59
+ async connect() {
60
+ if (this._db)
61
+ return;
62
+ const { createRequire } = await import("node:module");
63
+ const require2 = createRequire(import.meta.url);
64
+ const Database = require2("better-sqlite3");
65
+ this._rawDb = new Database(this.path);
66
+ const { createOpacaKysely } = await import("./chunk-sqsfk9p4.js");
67
+ this._db = createOpacaKysely({
68
+ dialect: new SqliteDialect({
69
+ database: this._rawDb
70
+ }),
71
+ config: {
72
+ collections: this._collections,
73
+ globals: this._globals,
74
+ db: { name: "sqlite" }
75
+ }
76
+ });
77
+ }
55
78
  async disconnect() {
56
- await this._db.destroy();
79
+ if (this._db)
80
+ await this.db.destroy();
57
81
  }
58
82
  async unsafe(query, params) {
59
83
  const compiled = CompiledQuery.raw(query, params || []);
60
- const result = await this._db.executeQuery(compiled);
84
+ const result = await this.db.executeQuery(compiled);
61
85
  return result.rows;
62
86
  }
63
- async coerceData(collection, data) {
64
- const colDef = this._collections.find((c) => c.slug === collection);
65
- if (!colDef)
66
- return data;
67
- const result = { ...data };
68
- const allFields = flattenFields(colDef.fields);
69
- for (const field of allFields) {
70
- const colName = toSnakeCase(field.name);
71
- if (!(colName in result))
72
- continue;
73
- const value = result[colName];
74
- if (value === undefined || value === null)
75
- continue;
76
- switch (field.type) {
77
- case "boolean":
78
- result[colName] = value ? 1 : 0;
79
- break;
80
- case "number":
81
- result[colName] = Number(value);
82
- break;
83
- case "date":
84
- if (value instanceof Date) {
85
- result[colName] = value.toISOString();
86
- } else if (typeof value === "string") {
87
- result[colName] = new Date(value).toISOString();
88
- }
89
- break;
90
- case "richtext":
91
- case "json":
92
- case "file":
93
- if (typeof value === "object") {
94
- result[colName] = JSON.stringify(value);
95
- }
96
- break;
97
- }
98
- }
99
- return result;
100
- }
101
87
  async count(collection, query) {
102
88
  const tableName = toSnakeCase(collection);
103
- let qb = this._db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
89
+ let qb = this.db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
104
90
  if (query && Object.keys(query).length > 0) {
105
91
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
106
92
  }
@@ -109,7 +95,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
109
95
  }
110
96
  async create(collection, data) {
111
97
  const tableName = toSnakeCase(collection);
112
- return this._db.transaction().execute(async (tx) => {
98
+ return this.db.transaction().execute(async (tx) => {
113
99
  const colDef = this._collections.find((c) => c.slug === collection);
114
100
  const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
115
101
  const flatData = flattenPayload(data, "", jsonFields);
@@ -127,24 +113,18 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
127
113
  delete flatData[key];
128
114
  }
129
115
  }
130
- if (!flatData.id)
131
- flatData.id = crypto.randomUUID();
132
116
  const dbFields = flattenFields(colDef?.fields || []);
133
117
  const validCols = new Set(dbFields.map((f) => toSnakeCase(f.name)));
134
118
  validCols.add("id");
135
119
  validCols.add(toSnakeCase("createdAt"));
136
120
  validCols.add(toSnakeCase("updatedAt"));
137
- const now = new Date().toISOString();
138
- flatData[toSnakeCase("createdAt")] = now;
139
- flatData[toSnakeCase("updatedAt")] = now;
140
121
  const filteredData = {};
141
122
  for (const col of Object.keys(flatData)) {
142
123
  if (validCols.has(col)) {
143
124
  filteredData[col] = flatData[col];
144
125
  }
145
126
  }
146
- const coercedData = await this.coerceData(collection, filteredData);
147
- await tx.insertInto(tableName).values(coercedData).execute();
127
+ await tx.insertInto(tableName).values(filteredData).execute();
148
128
  for (const [key, values] of Object.entries(hasManyData)) {
149
129
  const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
150
130
  if (values.length > 0) {
@@ -172,13 +152,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
172
152
  }
173
153
  }
174
154
  delete blockFlatData.blockType;
175
- const coercedBlockData = await this.coerceData(blockTableName, {
155
+ const blockData = {
176
156
  ...blockFlatData,
177
157
  _parent_id: flatData.id,
178
158
  _order: i,
179
159
  block_type: block.blockType
180
- });
181
- await tx.insertInto(blockTableName).values(coercedBlockData).execute();
160
+ };
161
+ await tx.insertInto(blockTableName).values(blockData).execute();
182
162
  }
183
163
  }
184
164
  return this.findOne(collection, { id: flatData.id }, tx);
@@ -186,7 +166,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
186
166
  }
187
167
  async findOne(collection, query, tx) {
188
168
  const tableName = toSnakeCase(collection);
189
- const executor = tx || this._db;
169
+ const executor = tx || this.db;
190
170
  let qb = executor.selectFrom(tableName).selectAll();
191
171
  if (query && Object.keys(query).length > 0) {
192
172
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -250,9 +230,17 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
250
230
  const page = options?.page || 1;
251
231
  const limit = options?.limit || 10;
252
232
  const offset = (page - 1) * limit;
233
+ const cursorColumn = options?.cursorColumn || "id";
253
234
  const total = await this.count(collection, query);
254
235
  const tableName = toSnakeCase(collection);
255
- let qb = this._db.selectFrom(tableName).selectAll().limit(limit).offset(offset);
236
+ let qb = this.db.selectFrom(tableName).selectAll().limit(limit);
237
+ if (options?.after) {
238
+ qb = qb.where(cursorColumn, ">", options.after);
239
+ } else if (options?.before) {
240
+ qb = qb.where(cursorColumn, "<", options.before);
241
+ } else {
242
+ qb = qb.offset(offset);
243
+ }
256
244
  if (query && Object.keys(query).length > 0) {
257
245
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
258
246
  }
@@ -262,11 +250,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
262
250
  qb = qb.orderBy(col, dir === "desc" ? "desc" : "asc");
263
251
  }
264
252
  } else {
265
- qb = qb.orderBy("created_at", "desc");
253
+ qb = qb.orderBy(cursorColumn, "desc");
266
254
  }
267
255
  const rows = await qb.execute();
268
256
  if (rows.length === 0) {
269
257
  const totalPages2 = Math.ceil(total / limit);
258
+ const afterAnchor = options?.after;
259
+ const beforeAnchor = options?.before;
270
260
  return {
271
261
  docs: [],
272
262
  totalDocs: total,
@@ -274,10 +264,12 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
274
264
  totalPages: totalPages2,
275
265
  page,
276
266
  pagingCounter: offset + 1,
277
- hasNextPage: page * limit < total,
278
- hasPrevPage: page > 1,
279
- prevPage: page > 1 ? page - 1 : null,
280
- nextPage: page < totalPages2 ? page + 1 : null
267
+ hasNextPage: false,
268
+ hasPrevPage: !!afterAnchor || page > 1,
269
+ prevPage: null,
270
+ nextPage: null,
271
+ nextCursor: null,
272
+ prevCursor: afterAnchor ? afterAnchor : null
281
273
  };
282
274
  }
283
275
  const rowIds = rows.map((r) => r.id);
@@ -292,7 +284,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
292
284
  if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
293
285
  const joinTableName = `${toSnakeCase(collection)}_${snakeName}_relations`.toLowerCase();
294
286
  try {
295
- const allRelations = await this._db.selectFrom(joinTableName).selectAll().where("source_id", "in", rowIds).orderBy("order", "asc").execute();
287
+ const allRelations = await this.db.selectFrom(joinTableName).selectAll().where("source_id", "in", rowIds).orderBy("order", "asc").execute();
296
288
  const relationsBySource = allRelations.reduce((acc, r) => {
297
289
  if (!acc[r.source_id])
298
290
  acc[r.source_id] = [];
@@ -316,7 +308,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
316
308
  for (const b of field.blocks) {
317
309
  const blockTableName = `${collection}_${snakeName}_${toSnakeCase(b.slug)}`.toLowerCase();
318
310
  try {
319
- const allBlocks = await this._db.selectFrom(blockTableName).selectAll().where("_parent_id", "in", rowIds).execute();
311
+ const allBlocks = await this.db.selectFrom(blockTableName).selectAll().where("_parent_id", "in", rowIds).execute();
320
312
  for (const blk of allBlocks) {
321
313
  const uf = unflattenRow(blk);
322
314
  uf.blockType = blk.block_type;
@@ -355,13 +347,15 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
355
347
  page,
356
348
  pagingCounter: offset + 1,
357
349
  hasNextPage: page * limit < total,
358
- hasPrevPage: page > 1,
350
+ hasPrevPage: page > 1 || !!options?.after || !!options?.before,
359
351
  prevPage: page > 1 ? page - 1 : null,
360
- nextPage: page < totalPages ? page + 1 : null
352
+ nextPage: page < totalPages ? page + 1 : null,
353
+ nextCursor: docs.length > 0 ? docs[docs.length - 1][cursorColumn] : null,
354
+ prevCursor: docs.length > 0 && (page > 1 || !!options?.after || !!options?.before) ? docs[0][cursorColumn] : null
361
355
  };
362
356
  }
363
357
  async update(collection, query, data) {
364
- return this._db.transaction().execute(async (tx) => {
358
+ return this.db.transaction().execute(async (tx) => {
365
359
  let normalizedQuery = query;
366
360
  if (typeof query !== "object" || query === null) {
367
361
  normalizedQuery = { id: query };
@@ -369,6 +363,9 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
369
363
  const current = await this.findOne(collection, normalizedQuery, tx);
370
364
  if (!current)
371
365
  throw new Error("Document not found");
366
+ const store = requestContext.getStore();
367
+ if (store)
368
+ store.previousData = current;
372
369
  const colDef = this._collections.find((c) => c.slug === collection);
373
370
  const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
374
371
  const flatData = flattenPayload(data, "", jsonFields);
@@ -386,16 +383,9 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
386
383
  delete flatData[key];
387
384
  }
388
385
  }
389
- const ts = colDef?.timestamps !== false;
390
- if (ts) {
391
- const config = typeof colDef?.timestamps === "object" ? colDef.timestamps : {};
392
- const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
393
- flatData[updatedField] = new Date().toISOString();
394
- }
395
386
  const tableName = toSnakeCase(collection);
396
387
  if (Object.keys(flatData).length > 0) {
397
- const coercedData = await this.coerceData(collection, flatData);
398
- await tx.updateTable(tableName).set(coercedData).where("id", "=", current.id).execute();
388
+ await tx.updateTable(tableName).set(flatData).where("id", "=", current.id).execute();
399
389
  }
400
390
  for (const [key, values] of Object.entries(hasManyData)) {
401
391
  const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
@@ -433,13 +423,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
433
423
  }
434
424
  }
435
425
  delete blockFlatData.blockType;
436
- const coercedBlockData = await this.coerceData(blockTableName, {
426
+ const blockData = {
437
427
  ...blockFlatData,
438
428
  _parent_id: current.id,
439
429
  _order: i,
440
430
  block_type: block.blockType
441
- });
442
- await tx.insertInto(blockTableName).values(coercedBlockData).execute();
431
+ };
432
+ await tx.insertInto(blockTableName).values(blockData).execute();
443
433
  }
444
434
  }
445
435
  return this.findOne(collection, { id: current.id }, tx);
@@ -454,7 +444,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
454
444
  if (!current)
455
445
  return false;
456
446
  const tableName = toSnakeCase(collection);
457
- await this._db.transaction().execute(async (tx) => {
447
+ await this.db.transaction().execute(async (tx) => {
458
448
  const colDef = this._collections.find((c) => c.slug === collection);
459
449
  if (colDef) {
460
450
  const relationalFields = getRelationalFields(colDef.fields);
@@ -483,7 +473,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
483
473
  }
484
474
  async updateMany(collection, query, data) {
485
475
  const tableName = toSnakeCase(collection);
486
- return this._db.transaction().execute(async (tx) => {
476
+ return this.db.transaction().execute(async (tx) => {
487
477
  let qb = tx.updateTable(tableName);
488
478
  if (query && Object.keys(query).length > 0) {
489
479
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -503,8 +493,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
503
493
  flatData[updatedField] = new Date().toISOString();
504
494
  }
505
495
  if (Object.keys(flatData).length > 0) {
506
- const coercedData = await this.coerceData(collection, flatData);
507
- const result = await qb.set(coercedData).executeTakeFirst();
496
+ const result = await qb.set(flatData).executeTakeFirst();
508
497
  return Number(result.numUpdatedRows || 0);
509
498
  }
510
499
  return 0;
@@ -512,7 +501,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
512
501
  }
513
502
  async deleteMany(collection, query) {
514
503
  const tableName = toSnakeCase(collection);
515
- return this._db.transaction().execute(async (tx) => {
504
+ return this.db.transaction().execute(async (tx) => {
516
505
  let selectQb = tx.selectFrom(tableName).select("id");
517
506
  if (query && Object.keys(query).length > 0) {
518
507
  selectQb = selectQb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -549,7 +538,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
549
538
  }
550
539
  async findGlobal(slug) {
551
540
  const tableName = toSnakeCase(slug);
552
- const row = await this._db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
541
+ const row = await this.db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
553
542
  return row ? unflattenRow(row) : null;
554
543
  }
555
544
  async updateGlobal(slug, data) {
@@ -562,15 +551,15 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
562
551
  if (!flatData.id)
563
552
  flatData.id = "global";
564
553
  flatData[toSnakeCase("createdAt")] = now;
565
- await this._db.insertInto(tableName).values(flatData).execute();
554
+ await this.db.insertInto(tableName).values(flatData).execute();
566
555
  } else {
567
- await this._db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
556
+ await this.db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
568
557
  }
569
558
  return this.findGlobal(slug);
570
559
  }
571
560
  async runMigrations() {
572
561
  const migrator = new Migrator({
573
- db: this._db,
562
+ db: this.db,
574
563
  provider: new FileMigrationProvider({
575
564
  fs,
576
565
  path,
@@ -593,7 +582,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
593
582
  this._collections = collections;
594
583
  this._globals = globals;
595
584
  if (this.push) {
596
- await pushSchema(this._db, "sqlite", collections, globals, {
585
+ await pushSchema(this.db, "sqlite", collections, globals, {
597
586
  pushDestructive: this.pushDestructive
598
587
  });
599
588
  }