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