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,18 +17,20 @@ 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/bun-sqlite.ts
20
- import { Database } from "bun:sqlite";
21
26
  import fs from "node:fs/promises";
22
27
  import path from "node:path";
23
- import { FileMigrationProvider, Kysely, Migrator, sql } from "kysely";
24
- import { BunSqliteDialect } from "kysely-bun-sqlite";
28
+ import { FileMigrationProvider, Migrator, sql } from "kysely";
25
29
  class BunSQLiteAdapter extends BaseDatabaseAdapter {
30
+ path;
26
31
  name = "bun-sqlite";
27
32
  _rawDb;
28
- _db;
33
+ _db = null;
29
34
  _collections = [];
30
35
  _globals = [];
31
36
  push;
@@ -35,73 +40,47 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
35
40
  return this._rawDb;
36
41
  }
37
42
  get db() {
43
+ if (!this._db)
44
+ throw new Error("Database not connected. Call connect() first.");
38
45
  return this._db;
39
46
  }
40
47
  constructor(path2, options) {
41
48
  super();
42
- this._rawDb = new Database(path2);
43
- this._db = new Kysely({
44
- dialect: new BunSqliteDialect({
45
- database: this._rawDb
46
- })
47
- });
49
+ this.path = path2;
48
50
  this.push = options?.push ?? true;
49
51
  this.pushDestructive = options?.pushDestructive ?? false;
50
52
  this.migrationDir = options?.migrationDir ?? "./migrations";
51
53
  }
52
- async connect() {}
54
+ async connect() {
55
+ if (this._db)
56
+ return;
57
+ const { Database } = await import("bun:sqlite");
58
+ const { BunSqliteDialect } = await import("kysely-bun-sqlite");
59
+ this._rawDb = new Database(this.path);
60
+ const { createOpacaKysely } = await import("./chunk-sqsfk9p4.js");
61
+ this._db = createOpacaKysely({
62
+ dialect: new BunSqliteDialect({
63
+ database: this._rawDb
64
+ }),
65
+ config: {
66
+ collections: this._collections,
67
+ globals: this._globals,
68
+ db: { name: "bun-sqlite" }
69
+ }
70
+ });
71
+ }
53
72
  async disconnect() {
54
- await this._db.destroy();
73
+ if (this._db)
74
+ await this.db.destroy();
55
75
  }
56
76
  async unsafe(query, params) {
57
77
  const compiled = sql.raw(query);
58
- const result = await compiled.execute(this._db);
78
+ const result = await compiled.execute(this.db);
59
79
  return result.rows;
60
80
  }
61
- async coerceData(collection, data) {
62
- const colDef = this._collections.find((c) => c.slug === collection);
63
- if (!colDef)
64
- return data;
65
- const result = { ...data };
66
- const allFields = flattenFields(colDef.fields);
67
- for (const field of allFields) {
68
- const colName = toSnakeCase(field.name);
69
- if (!(colName in result))
70
- continue;
71
- const value = result[colName];
72
- if (value === undefined || value === null)
73
- continue;
74
- switch (field.type) {
75
- case "boolean":
76
- result[colName] = value ? 1 : 0;
77
- break;
78
- case "number":
79
- result[colName] = Number(value);
80
- break;
81
- case "date":
82
- if (value instanceof Date) {
83
- result[colName] = value.toISOString();
84
- } else if (typeof value === "string") {
85
- const d = new Date(value);
86
- if (!isNaN(d.getTime())) {
87
- result[colName] = d.toISOString();
88
- }
89
- }
90
- break;
91
- case "richtext":
92
- case "json":
93
- case "file":
94
- if (typeof value === "object") {
95
- result[colName] = JSON.stringify(value);
96
- }
97
- break;
98
- }
99
- }
100
- return result;
101
- }
102
81
  async count(collection, query) {
103
82
  const tableName = toSnakeCase(collection);
104
- let qb = this._db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
83
+ let qb = this.db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
105
84
  if (query && Object.keys(query).length > 0) {
106
85
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
107
86
  }
@@ -111,13 +90,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
111
90
  async create(collection, data) {
112
91
  const tableName = toSnakeCase(collection);
113
92
  const colDef = this._collections.find((c) => c.slug === collection);
114
- const jsonFields = colDef?.fields.filter((f) => f.name && ["richtext", "json", "file"].includes(f.type)).map((f) => toSnakeCase(f.name)) || [];
115
- const flatData = flattenPayload(data, "", jsonFields);
116
- for (const field of jsonFields) {
117
- if (flatData[field] && typeof flatData[field] === "object") {
118
- flatData[field] = JSON.stringify(flatData[field]);
119
- }
120
- }
93
+ const flatData = flattenPayload(data);
121
94
  const relationalFields = getRelationalFields(colDef?.fields || []);
122
95
  const hasManyData = {};
123
96
  const blocksData = {};
@@ -132,24 +105,18 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
132
105
  delete flatData[key];
133
106
  }
134
107
  }
135
- if (!flatData.id)
136
- flatData.id = crypto.randomUUID();
137
108
  const dbFields = flattenFields(colDef?.fields || []);
138
109
  const validCols = new Set(dbFields.map((f) => toSnakeCase(f.name)));
139
110
  validCols.add("id");
140
111
  validCols.add(toSnakeCase("createdAt"));
141
112
  validCols.add(toSnakeCase("updatedAt"));
142
- const now = new Date().toISOString();
143
- flatData[toSnakeCase("createdAt")] = now;
144
- flatData[toSnakeCase("updatedAt")] = now;
145
113
  const filteredData = {};
146
114
  for (const col of Object.keys(flatData)) {
147
115
  if (validCols.has(col)) {
148
116
  filteredData[col] = flatData[col];
149
117
  }
150
118
  }
151
- const coercedData = await this.coerceData(collection, filteredData);
152
- await this._db.insertInto(tableName).values(coercedData).execute();
119
+ await this.db.insertInto(tableName).values(filteredData).execute();
153
120
  for (const [key, values] of Object.entries(hasManyData)) {
154
121
  const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
155
122
  if (values.length > 0) {
@@ -157,7 +124,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
157
124
  const tId = typeof val === "object" ? val.id : val;
158
125
  return { id: crypto.randomUUID(), source_id: flatData.id, target_id: tId, order: idx };
159
126
  });
160
- await this._db.insertInto(joinTableName).values(joinData).execute();
127
+ await this.db.insertInto(joinTableName).values(joinData).execute();
161
128
  }
162
129
  }
163
130
  for (const [key, blocks] of Object.entries(blocksData)) {
@@ -177,20 +144,20 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
177
144
  }
178
145
  }
179
146
  delete blockFlatData.blockType;
180
- const coercedBlockData = await this.coerceData(blockTableName, {
147
+ const blockData = {
181
148
  ...blockFlatData,
182
149
  _parent_id: flatData.id,
183
150
  _order: i,
184
151
  block_type: block.blockType
185
- });
186
- await this._db.insertInto(blockTableName).values(coercedBlockData).execute();
152
+ };
153
+ await this.db.insertInto(blockTableName).values(blockData).execute();
187
154
  }
188
155
  }
189
- return this.findOne(collection, { id: flatData.id }, this._db);
156
+ return this.findOne(collection, { id: flatData.id }, this.db);
190
157
  }
191
158
  async findOne(collection, query, tx) {
192
159
  const tableName = toSnakeCase(collection);
193
- const executor = tx || this._db;
160
+ const executor = tx || this.db;
194
161
  let qb = executor.selectFrom(tableName).selectAll();
195
162
  if (query && Object.keys(query).length > 0) {
196
163
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -254,9 +221,17 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
254
221
  const page = options?.page || 1;
255
222
  const limit = options?.limit || 10;
256
223
  const offset = (page - 1) * limit;
224
+ const cursorColumn = options?.cursorColumn || "id";
257
225
  const total = await this.count(collection, query);
258
226
  const tableName = toSnakeCase(collection);
259
- let qb = this._db.selectFrom(tableName).selectAll().limit(limit).offset(offset);
227
+ let qb = this.db.selectFrom(tableName).selectAll().limit(limit);
228
+ if (options?.after) {
229
+ qb = qb.where(cursorColumn, ">", options.after);
230
+ } else if (options?.before) {
231
+ qb = qb.where(cursorColumn, "<", options.before);
232
+ } else {
233
+ qb = qb.offset(offset);
234
+ }
260
235
  if (query && Object.keys(query).length > 0) {
261
236
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
262
237
  }
@@ -266,11 +241,13 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
266
241
  qb = qb.orderBy(col, dir === "desc" ? "desc" : "asc");
267
242
  }
268
243
  } else {
269
- qb = qb.orderBy("created_at", "desc");
244
+ qb = qb.orderBy(cursorColumn, "desc");
270
245
  }
271
246
  const rows = await qb.execute();
272
247
  if (rows.length === 0) {
273
248
  const totalPages2 = Math.ceil(total / limit);
249
+ const afterAnchor = options?.after;
250
+ const beforeAnchor = options?.before;
274
251
  return {
275
252
  docs: [],
276
253
  totalDocs: total,
@@ -278,10 +255,12 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
278
255
  totalPages: totalPages2,
279
256
  page,
280
257
  pagingCounter: offset + 1,
281
- hasNextPage: page * limit < total,
282
- hasPrevPage: page > 1,
283
- prevPage: page > 1 ? page - 1 : null,
284
- nextPage: page < totalPages2 ? page + 1 : null
258
+ hasNextPage: false,
259
+ hasPrevPage: !!afterAnchor || page > 1,
260
+ prevPage: null,
261
+ nextPage: null,
262
+ nextCursor: null,
263
+ prevCursor: afterAnchor ? afterAnchor : null
285
264
  };
286
265
  }
287
266
  const rowIds = rows.map((r) => r.id);
@@ -296,7 +275,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
296
275
  if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
297
276
  const joinTableName = `${toSnakeCase(collection)}_${snakeName}_relations`.toLowerCase();
298
277
  try {
299
- const allRelations = await this._db.selectFrom(joinTableName).selectAll().where("source_id", "in", rowIds).orderBy("order", "asc").execute();
278
+ const allRelations = await this.db.selectFrom(joinTableName).selectAll().where("source_id", "in", rowIds).orderBy("order", "asc").execute();
300
279
  const relationsBySource = allRelations.reduce((acc, r) => {
301
280
  if (!acc[r.source_id])
302
281
  acc[r.source_id] = [];
@@ -320,7 +299,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
320
299
  for (const b of field.blocks) {
321
300
  const blockTableName = `${collection}_${snakeName}_${toSnakeCase(b.slug)}`.toLowerCase();
322
301
  try {
323
- const allBlocks = await this._db.selectFrom(blockTableName).selectAll().where("_parent_id", "in", rowIds).execute();
302
+ const allBlocks = await this.db.selectFrom(blockTableName).selectAll().where("_parent_id", "in", rowIds).execute();
324
303
  for (const blk of allBlocks) {
325
304
  const uf = unflattenRow(blk);
326
305
  uf.blockType = blk.block_type;
@@ -359,13 +338,15 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
359
338
  page,
360
339
  pagingCounter: offset + 1,
361
340
  hasNextPage: page * limit < total,
362
- hasPrevPage: page > 1,
341
+ hasPrevPage: page > 1 || !!options?.after || !!options?.before,
363
342
  prevPage: page > 1 ? page - 1 : null,
364
- nextPage: page < totalPages ? page + 1 : null
343
+ nextPage: page < totalPages ? page + 1 : null,
344
+ nextCursor: docs.length > 0 ? docs[docs.length - 1][cursorColumn] : null,
345
+ prevCursor: docs.length > 0 && (page > 1 || !!options?.after || !!options?.before) ? docs[0][cursorColumn] : null
365
346
  };
366
347
  }
367
348
  async update(collection, query, data) {
368
- return this._db.transaction().execute(async (tx) => {
349
+ return this.db.transaction().execute(async (tx) => {
369
350
  let normalizedQuery = query;
370
351
  if (typeof query !== "object" || query === null) {
371
352
  normalizedQuery = { id: query };
@@ -373,6 +354,9 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
373
354
  const current = await this.findOne(collection, normalizedQuery, tx);
374
355
  if (!current)
375
356
  throw new Error("Document not found");
357
+ const store = requestContext.getStore();
358
+ if (store)
359
+ store.previousData = current;
376
360
  const colDef = this._collections.find((c) => c.slug === collection);
377
361
  const jsonFields = colDef?.fields.filter((f) => ["richtext", "json", "file"].includes(f.type)).map((f) => f.name) || [];
378
362
  const flatData = flattenPayload(data, "", jsonFields);
@@ -395,10 +379,8 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
395
379
  delete flatData[key];
396
380
  }
397
381
  }
398
- flatData.updated_at = new Date().toISOString();
399
382
  if (Object.keys(flatData).length > 0) {
400
- const coercedData = await this.coerceData(collection, flatData);
401
- await tx.updateTable(toSnakeCase(collection)).set(coercedData).where("id", "=", current.id).execute();
383
+ await tx.updateTable(toSnakeCase(collection)).set(flatData).where("id", "=", current.id).execute();
402
384
  }
403
385
  for (const [key, values] of Object.entries(hasManyData)) {
404
386
  const joinTableName = `${toSnakeCase(collection)}_${toSnakeCase(key)}_relations`.toLowerCase();
@@ -436,20 +418,20 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
436
418
  }
437
419
  }
438
420
  delete blockFlatData.blockType;
439
- const coercedBlockData = await this.coerceData(blockTableName, {
421
+ const blockData = {
440
422
  ...blockFlatData,
441
423
  _parent_id: current.id,
442
424
  _order: i,
443
425
  block_type: block.blockType
444
- });
445
- await this._db.insertInto(blockTableName).values(coercedBlockData).execute();
426
+ };
427
+ await this.db.insertInto(blockTableName).values(blockData).execute();
446
428
  }
447
429
  }
448
430
  return this.findOne(collection, { id: current.id }, tx);
449
431
  });
450
432
  }
451
433
  async updateMany(collection, query, data) {
452
- return this._db.transaction().execute(async (tx) => {
434
+ return this.db.transaction().execute(async (tx) => {
453
435
  let qb = tx.updateTable(toSnakeCase(collection));
454
436
  if (query && Object.keys(query).length > 0) {
455
437
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -467,10 +449,8 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
467
449
  delete flatData[key];
468
450
  }
469
451
  }
470
- flatData.updated_at = new Date().toISOString();
471
452
  if (Object.keys(flatData).length > 0) {
472
- const coercedData = await this.coerceData(collection, flatData);
473
- const result = await qb.set(coercedData).executeTakeFirst();
453
+ const result = await qb.set(flatData).executeTakeFirst();
474
454
  return Number(result.numUpdatedRows || 0);
475
455
  }
476
456
  return 0;
@@ -484,7 +464,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
484
464
  const current = await this.findOne(collection, normalizedQuery);
485
465
  if (!current)
486
466
  return false;
487
- await this._db.transaction().execute(async (tx) => {
467
+ await this.db.transaction().execute(async (tx) => {
488
468
  const colDef = this._collections.find((c) => c.slug === collection);
489
469
  if (colDef) {
490
470
  const relationalFields = getRelationalFields(colDef.fields);
@@ -512,7 +492,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
512
492
  return true;
513
493
  }
514
494
  async deleteMany(collection, query) {
515
- return this._db.transaction().execute(async (tx) => {
495
+ return this.db.transaction().execute(async (tx) => {
516
496
  let selectQb = tx.selectFrom(toSnakeCase(collection)).select("id");
517
497
  if (query && Object.keys(query).length > 0) {
518
498
  selectQb = selectQb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
@@ -549,7 +529,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
549
529
  }
550
530
  async findGlobal(slug) {
551
531
  const tableName = toSnakeCase(slug);
552
- const row = await this._db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
532
+ const row = await this.db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
553
533
  return row ? unflattenRow(row) : null;
554
534
  }
555
535
  async updateGlobal(slug, data) {
@@ -563,15 +543,15 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
563
543
  if (!flatData.id)
564
544
  flatData.id = "global";
565
545
  flatData[toSnakeCase("createdAt")] = now;
566
- await this._db.insertInto(tableName).values(flatData).execute();
546
+ await this.db.insertInto(tableName).values(flatData).execute();
567
547
  } else {
568
- await this._db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
548
+ await this.db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
569
549
  }
570
550
  return this.findGlobal(slug);
571
551
  }
572
552
  async runMigrations() {
573
553
  const migrator = new Migrator({
574
- db: this._db,
554
+ db: this.db,
575
555
  provider: new FileMigrationProvider({
576
556
  fs,
577
557
  path,
@@ -594,7 +574,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
594
574
  this._collections = collections;
595
575
  this._globals = globals;
596
576
  if (this.push) {
597
- await pushSchema(this._db, "sqlite", collections, globals, {
577
+ await pushSchema(this.db, "sqlite", collections, globals, {
598
578
  pushDestructive: this.pushDestructive
599
579
  });
600
580
  }
@@ -0,0 +1,76 @@
1
+ import {
2
+ require_picocolors
3
+ } from "./chunk-rwqwsanx.js";
4
+ import {
5
+ Gt,
6
+ R,
7
+ Vt,
8
+ Wt
9
+ } from "./chunk-ec4jhybj.js";
10
+ import {
11
+ defineCommand
12
+ } from "./chunk-1qm0m8r8.js";
13
+ import {
14
+ __toESM
15
+ } from "./chunk-6bywt602.js";
16
+
17
+ // src/cli/commands/dev.ts
18
+ import { spawn } from "node:child_process";
19
+ import fs from "node:fs";
20
+ import { resolve } from "node:path";
21
+ var import_picocolors = __toESM(require_picocolors(), 1);
22
+ var dev_default = defineCommand({
23
+ meta: {
24
+ name: "dev",
25
+ description: "Start the OpacaCMS development server"
26
+ },
27
+ args: {
28
+ entry: {
29
+ type: "string",
30
+ description: "Path to your entry point (default: index.ts)",
31
+ default: "index.ts"
32
+ }
33
+ },
34
+ async run({ args }) {
35
+ console.log();
36
+ Wt(import_picocolors.default.bgBlue(import_picocolors.default.white(" OpacaCMS Dev Server ")));
37
+ const entryPath = resolve(process.cwd(), args.entry);
38
+ if (!fs.existsSync(entryPath)) {
39
+ R.error(import_picocolors.default.red(`Entry file not found at ${entryPath}`));
40
+ R.info("Try specifying the entry file: opacacms dev --entry src/index.ts");
41
+ process.exit(1);
42
+ }
43
+ Vt(`Watching for changes...`, "Status");
44
+ const isD1 = fs.readFileSync(entryPath, "utf-8").includes("createCloudflareWorkersHandler");
45
+ let cmd = "bun";
46
+ let cmdArgs = ["run", "--watch", args.entry];
47
+ if (isD1) {
48
+ cmd = "bun";
49
+ cmdArgs = ["x", "wrangler", "dev", args.entry];
50
+ }
51
+ const child = spawn(cmd, cmdArgs, {
52
+ stdio: "inherit",
53
+ cwd: process.cwd(),
54
+ env: process.env
55
+ });
56
+ child.on("error", (err) => {
57
+ R.error(import_picocolors.default.red(`Failed to start server: ${err.message}`));
58
+ });
59
+ child.on("exit", (code) => {
60
+ if (code !== 0) {
61
+ R.warn(`Server exited with code ${code}`);
62
+ }
63
+ Gt("Goodbye!");
64
+ process.exit(code || 0);
65
+ });
66
+ process.on("SIGINT", () => {
67
+ child.kill("SIGINT");
68
+ });
69
+ process.on("SIGTERM", () => {
70
+ child.kill("SIGTERM");
71
+ });
72
+ }
73
+ });
74
+ export {
75
+ dev_default as default
76
+ };
@@ -0,0 +1,75 @@
1
+ import {
2
+ __commonJS
3
+ } from "./chunk-6bywt602.js";
4
+
5
+ // ../../node_modules/picocolors/picocolors.js
6
+ var require_picocolors = __commonJS((exports, module) => {
7
+ var p = process || {};
8
+ var argv = p.argv || [];
9
+ var env = p.env || {};
10
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
11
+ var formatter = (open, close, replace = open) => (input) => {
12
+ let string = "" + input, index = string.indexOf(close, open.length);
13
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
14
+ };
15
+ var replaceClose = (string, close, replace, index) => {
16
+ let result = "", cursor = 0;
17
+ do {
18
+ result += string.substring(cursor, index) + replace;
19
+ cursor = index + close.length;
20
+ index = string.indexOf(close, cursor);
21
+ } while (~index);
22
+ return result + string.substring(cursor);
23
+ };
24
+ var createColors = (enabled = isColorSupported) => {
25
+ let f = enabled ? formatter : () => String;
26
+ return {
27
+ isColorSupported: enabled,
28
+ reset: f("\x1B[0m", "\x1B[0m"),
29
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
30
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
31
+ italic: f("\x1B[3m", "\x1B[23m"),
32
+ underline: f("\x1B[4m", "\x1B[24m"),
33
+ inverse: f("\x1B[7m", "\x1B[27m"),
34
+ hidden: f("\x1B[8m", "\x1B[28m"),
35
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
36
+ black: f("\x1B[30m", "\x1B[39m"),
37
+ red: f("\x1B[31m", "\x1B[39m"),
38
+ green: f("\x1B[32m", "\x1B[39m"),
39
+ yellow: f("\x1B[33m", "\x1B[39m"),
40
+ blue: f("\x1B[34m", "\x1B[39m"),
41
+ magenta: f("\x1B[35m", "\x1B[39m"),
42
+ cyan: f("\x1B[36m", "\x1B[39m"),
43
+ white: f("\x1B[37m", "\x1B[39m"),
44
+ gray: f("\x1B[90m", "\x1B[39m"),
45
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
46
+ bgRed: f("\x1B[41m", "\x1B[49m"),
47
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
48
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
49
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
50
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
51
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
52
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
53
+ blackBright: f("\x1B[90m", "\x1B[39m"),
54
+ redBright: f("\x1B[91m", "\x1B[39m"),
55
+ greenBright: f("\x1B[92m", "\x1B[39m"),
56
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
57
+ blueBright: f("\x1B[94m", "\x1B[39m"),
58
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
59
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
60
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
61
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
62
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
63
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
64
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
65
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
66
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
67
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
68
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
69
+ };
70
+ };
71
+ module.exports = createColors();
72
+ module.exports.createColors = createColors;
73
+ });
74
+
75
+ export { require_picocolors };