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,20 +17,25 @@ 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/sqlite.ts
|
|
20
26
|
import fs from "node:fs/promises";
|
|
21
27
|
import path from "node:path";
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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(
|
|
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.
|
|
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.
|
|
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(
|
|
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:
|
|
278
|
-
hasPrevPage: page > 1,
|
|
279
|
-
prevPage:
|
|
280
|
-
nextPage:
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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(
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
554
|
+
await this.db.insertInto(tableName).values(flatData).execute();
|
|
566
555
|
} else {
|
|
567
|
-
await this.
|
|
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.
|
|
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.
|
|
585
|
+
await pushSchema(this.db, "sqlite", collections, globals, {
|
|
597
586
|
pushDestructive: this.pushDestructive
|
|
598
587
|
});
|
|
599
588
|
}
|