opacacms 0.3.16 → 0.3.18
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/dist/admin/{stores → features/collections}/admin-queries.d.ts +1 -1
- package/dist/admin/{ui/views → features/collections}/collection-list-view.d.ts +1 -1
- package/dist/admin/{ui/views → features/collections}/document-edit-view.d.ts +2 -1
- package/dist/admin/{ui/views → features/collections}/global-edit-view.d.ts +1 -1
- package/dist/admin/{ui/components → features/collections}/versions-sheet.d.ts +3 -3
- package/dist/admin/{ui/views → features/dashboard}/dashboard-view.d.ts +1 -1
- package/dist/admin/{ui/components/media/AssetManagerModal.d.ts → features/media/components/asset-manager-modal.d.ts} +1 -2
- package/dist/admin/features/media/media-registry-view.d.ts +7 -0
- package/dist/admin/{ui/components/PluginSettingsForm.d.ts → features/settings/plugin-settings-form.d.ts} +3 -3
- package/dist/admin/{ui/views → features/settings}/settings-view.d.ts +2 -2
- package/dist/admin/{stores → features/ui-shell}/config.d.ts +1 -1
- package/dist/admin/{stores → features/ui-shell}/ui.d.ts +1 -1
- package/dist/admin/index.d.ts +8 -8
- package/dist/admin/index.js +4 -4
- package/dist/admin/ui/{components/ui → core}/blocks.d.ts +1 -1
- package/dist/admin/ui/core/breadcrumbs.d.ts +21 -0
- package/dist/admin/ui/{components/ui → core}/button.d.ts +4 -4
- package/dist/admin/ui/{components/ui → core}/collapsible.d.ts +2 -2
- package/dist/admin/ui/core/context-menu.d.ts +29 -0
- package/dist/admin/ui/core/dialog.d.ts +20 -0
- package/dist/admin/ui/{components/ui → core}/group.d.ts +2 -2
- package/dist/admin/ui/core/index.d.ts +17 -0
- package/dist/admin/ui/{components/ui → core}/input.d.ts +2 -2
- package/dist/admin/ui/{components/ui → core}/join.d.ts +1 -1
- package/dist/admin/ui/core/label.d.ts +4 -0
- package/dist/admin/ui/core/popover.d.ts +10 -0
- package/dist/admin/ui/{components/ui → core}/radio-group.d.ts +2 -2
- package/dist/admin/ui/{components/ui → core}/relationship.d.ts +1 -1
- package/dist/admin/ui/{components/ui → core}/scroll-area.d.ts +1 -1
- package/dist/admin/ui/core/select.d.ts +15 -0
- package/dist/admin/ui/{components/ui → core}/sheet.d.ts +6 -6
- package/dist/admin/ui/core/sidebar.d.ts +69 -0
- package/dist/admin/ui/core/skeleton.d.ts +2 -0
- package/dist/admin/ui/core/switch.d.ts +6 -0
- package/dist/admin/ui/core/table.d.ts +10 -0
- package/dist/admin/ui/core/tabs.d.ts +11 -0
- package/dist/admin/ui/hooks/use-mobile.d.ts +1 -0
- package/dist/admin/ui/{admin-client.d.ts → layout/admin-client.d.ts} +1 -1
- package/dist/admin/ui/{admin-layout.d.ts → layout/admin-layout.d.ts} +2 -2
- package/dist/admin/ui/{components → shared}/column-visibility-toggle.d.ts +1 -1
- package/dist/admin/ui/{components → shared}/detail-sheet.d.ts +2 -2
- package/dist/admin/ui/{components/fields/ArrayField.d.ts → shared/fields/array-field.d.ts} +1 -1
- package/dist/admin/ui/shared/fields/blocks-field.d.ts +25 -0
- package/dist/admin/ui/{components/fields/BooleanField.d.ts → shared/fields/boolean-field.d.ts} +1 -1
- package/dist/admin/ui/{components/fields/CollapsibleField.d.ts → shared/fields/collapsible-field.d.ts} +1 -1
- package/dist/admin/ui/{components/fields/FileField.d.ts → shared/fields/file-field.d.ts} +13 -3
- package/dist/admin/ui/{components/fields/GroupField.d.ts → shared/fields/group-field.d.ts} +1 -1
- package/dist/admin/ui/shared/fields/index.d.ts +28 -0
- package/dist/admin/ui/{components/fields/JoinField.d.ts → shared/fields/join-field.d.ts} +1 -1
- package/dist/admin/ui/{components/fields/RelationshipField.d.ts → shared/fields/relationship-field.d.ts} +1 -1
- package/dist/admin/ui/{components → shared}/fields/richtext-editor/index.d.ts +2 -2
- package/dist/admin/ui/{components/fields/richtext-editor/nodes/ImageNode.d.ts → shared/fields/richtext-editor/nodes/image-node.d.ts} +3 -3
- package/dist/admin/ui/{components/fields/TabsField.d.ts → shared/fields/tabs-field.d.ts} +1 -1
- package/dist/admin/ui/{components/fields/VirtualField.d.ts → shared/fields/virtual-field.d.ts} +1 -1
- package/dist/admin/ui/{components → shared}/toast.d.ts +1 -1
- package/dist/admin/webcomponent.js +34 -34
- package/dist/admin.css +1 -1
- package/dist/{chunk-5y0mkt7x.js → chunk-2abqb0h6.js} +2 -2
- package/dist/{chunk-m83ybzf8.js → chunk-hrxq1x98.js} +1 -1
- package/dist/{chunk-nch158fe.js → chunk-y3ehzvp4.js} +1 -1
- package/dist/{chunk-vmz9ncf1.js → chunk-yw9w63kr.js} +3 -3
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/core/seeding/auto-seed.d.ts +1 -1
- package/dist/cli/index.js +28 -3
- package/dist/config.d.ts +2 -6
- package/dist/db/adapter.d.ts +1 -1
- package/dist/db/better-sqlite.d.ts +1 -1
- package/dist/db/better-sqlite.js +587 -9
- package/dist/db/bun-sqlite.js +590 -9
- package/dist/db/d1.d.ts +1 -1
- package/dist/db/d1.js +605 -9
- package/dist/db/index.d.ts +0 -5
- package/dist/db/index.js +0 -35
- package/dist/db/kysely/plugins/draft-swapper.d.ts +2 -2
- package/dist/db/kysely/plugins/i18n-fallback.d.ts +2 -2
- package/dist/db/kysely/plugins/json-flattener.d.ts +2 -2
- package/dist/db/kysely/plugins/virtual-field-resolver.d.ts +2 -2
- package/dist/db/kysely/schema-builder.d.ts +1 -1
- package/dist/db/kysely/snapshot/snapshot-manager.d.ts +1 -1
- package/dist/db/postgres.js +613 -9
- package/dist/db/sqlite.d.ts +1 -1
- package/dist/db/sqlite.js +602 -9
- package/dist/runtimes/bun.js +1 -1
- package/dist/runtimes/cloudflare-workers.js +1 -1
- package/dist/runtimes/next.js +1 -1
- package/dist/runtimes/node.js +1 -1
- package/dist/server.js +4 -4
- package/dist/types.d.ts +3 -3
- package/package.json +25 -7
- package/dist/admin/ui/components/Table.d.ts +0 -10
- package/dist/admin/ui/components/fields/BlocksField.d.ts +0 -17
- package/dist/admin/ui/components/fields/index.d.ts +0 -28
- package/dist/admin/ui/components/ui/breadcrumbs.d.ts +0 -7
- package/dist/admin/ui/components/ui/dialog.d.ts +0 -27
- package/dist/admin/ui/components/ui/index.d.ts +0 -17
- package/dist/admin/ui/components/ui/label.d.ts +0 -3
- package/dist/admin/ui/components/ui/select.d.ts +0 -37
- package/dist/admin/ui/components/ui/tabs.d.ts +0 -17
- package/dist/admin/ui/views/media-registry-view.d.ts +0 -7
- package/dist/chunk-5b9eqr34.js +0 -608
- package/dist/chunk-dz5bh1bd.js +0 -586
- package/dist/chunk-nz6xhtja.js +0 -601
- package/dist/chunk-qsefknd3.js +0 -593
- package/dist/chunk-tsmhn78f.js +0 -616
- /package/dist/admin/{stores → features/auth}/auth.d.ts +0 -0
- /package/dist/admin/{ui/views → features/auth}/login-view.d.ts +0 -0
- /package/dist/admin/{ui/components → features/collections}/data-detail-view.d.ts +0 -0
- /package/dist/admin/{ui/views → features/init}/init-view.d.ts +0 -0
- /package/dist/admin/{stores → features/media}/media.d.ts +0 -0
- /package/dist/admin/{stores → features/ui-shell}/column-visibility.d.ts +0 -0
- /package/dist/admin/{stores → features/ui-shell}/query.d.ts +0 -0
- /package/dist/admin/ui/{components/ui → core}/accordion.d.ts +0 -0
- /package/dist/admin/ui/{components/ui → core}/alert-dialog.d.ts +0 -0
- /package/dist/admin/ui/{components/ui → core}/separator.d.ts +0 -0
- /package/dist/admin/ui/{components/ui → core}/tooltip.d.ts +0 -0
- /package/dist/admin/ui/{components/ui → core}/utils.d.ts +0 -0
- /package/dist/admin/ui/{components → shared}/custom-alert.d.ts +0 -0
- /package/dist/admin/ui/{components/fields/DateField.d.ts → shared/fields/date-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/FieldLabel.d.ts → shared/fields/field-label.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/NumberField.d.ts → shared/fields/number-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/RadioField.d.ts → shared/fields/radio-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/nodes/ImageComponent.d.ts → shared/fields/richtext-editor/nodes/image-component.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/plugins/ComponentPickerPlugin.d.ts → shared/fields/richtext-editor/plugins/component-picker-plugin.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/plugins/EditableSyncPlugin.d.ts → shared/fields/richtext-editor/plugins/editable-sync-plugin.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/plugins/NotionToolbarPlugin.d.ts → shared/fields/richtext-editor/plugins/notion-toolbar-plugin.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/plugins/SimpleToolbarPlugin.d.ts → shared/fields/richtext-editor/plugins/simple-toolbar-plugin.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/richtext-editor/plugins/ValueSyncPlugin.d.ts → shared/fields/richtext-editor/plugins/value-sync-plugin.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/RowField.d.ts → shared/fields/row-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/SelectField.d.ts → shared/fields/select-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/TextAreaField.d.ts → shared/fields/text-area-field.d.ts} +0 -0
- /package/dist/admin/ui/{components/fields/TextField.d.ts → shared/fields/text-field.d.ts} +0 -0
- /package/dist/admin/ui/{components → shared}/fields/utils.d.ts +0 -0
- /package/dist/admin/ui/{components → shared}/link.d.ts +0 -0
- /package/dist/admin/ui/{components → shared}/plugin-iframe.d.ts +0 -0
|
@@ -5,9 +5,9 @@ import type { Collection, Global } from "../../../types";
|
|
|
5
5
|
*/
|
|
6
6
|
export interface JsonFlattenerPluginConfig {
|
|
7
7
|
/** The list of CMS collections. */
|
|
8
|
-
collections: Collection[];
|
|
8
|
+
collections: Collection[] | readonly Collection[];
|
|
9
9
|
/** The list of CMS globals. */
|
|
10
|
-
globals?: Global[];
|
|
10
|
+
globals?: Global[] | readonly Global[];
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Kysely plugin that automatically handles JSON serialization and deserialization
|
|
@@ -5,9 +5,9 @@ import type { ApiKey, Collection, Global, Session, User } from "../../../types";
|
|
|
5
5
|
*/
|
|
6
6
|
export interface VirtualFieldResolverPluginConfig {
|
|
7
7
|
/** The list of CMS collections. */
|
|
8
|
-
collections: Collection[];
|
|
8
|
+
collections: Collection[] | readonly Collection[];
|
|
9
9
|
/** The list of CMS globals. */
|
|
10
|
-
globals?: Global[];
|
|
10
|
+
globals?: Global[] | readonly Global[];
|
|
11
11
|
/** The current request context (Hono context or similar). */
|
|
12
12
|
req?: any;
|
|
13
13
|
/** The current authenticated user. */
|
|
@@ -10,6 +10,6 @@ export type DialectType = "postgres" | "sqlite" | "d1";
|
|
|
10
10
|
* @param globals The user globals
|
|
11
11
|
* @param options Push options
|
|
12
12
|
*/
|
|
13
|
-
export declare function pushSchema(db: Kysely<any>, dialect: DialectType, collections: Collection[], globals?: Global[], options?: {
|
|
13
|
+
export declare function pushSchema(db: Kysely<any>, dialect: DialectType, collections: Collection[] | readonly Collection[], globals?: Global[] | readonly Global[], options?: {
|
|
14
14
|
pushDestructive?: boolean;
|
|
15
15
|
}): Promise<void>;
|
|
@@ -13,6 +13,6 @@ export interface TableSnapshot {
|
|
|
13
13
|
export interface SchemaSnapshot {
|
|
14
14
|
tables: Record<string, TableSnapshot>;
|
|
15
15
|
}
|
|
16
|
-
export declare function createSchemaSnapshot(collections: Collection[], globals: Global[], dialect: "postgres" | "sqlite" | "d1"): SchemaSnapshot;
|
|
16
|
+
export declare function createSchemaSnapshot(collections: Collection[] | readonly Collection[], globals: Global[] | readonly Global[], dialect: "postgres" | "sqlite" | "d1"): SchemaSnapshot;
|
|
17
17
|
export declare function saveSnapshot(migrationDir: string, snapshotName: string, snapshot: SchemaSnapshot): void;
|
|
18
18
|
export declare function loadLastSnapshot(migrationDir: string): SchemaSnapshot | null;
|
package/dist/db/postgres.js
CHANGED
|
@@ -1,14 +1,618 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
buildKyselyWhere,
|
|
3
|
+
flattenPayload,
|
|
4
|
+
pushSchema,
|
|
5
|
+
unflattenRow
|
|
6
|
+
} from "../chunk-re459gm9.js";
|
|
7
|
+
import {
|
|
8
|
+
requestContext
|
|
9
|
+
} from "../chunk-q5sb5dcr.js";
|
|
10
|
+
import {
|
|
11
|
+
getRelationalFields,
|
|
12
|
+
toSnakeCase
|
|
13
|
+
} from "../chunk-5xpf5jxd.js";
|
|
14
|
+
import {
|
|
15
|
+
logger
|
|
16
|
+
} from "../chunk-jq1drsen.js";
|
|
10
17
|
import"../chunk-h8v093av.js";
|
|
11
|
-
import
|
|
18
|
+
import {
|
|
19
|
+
BaseDatabaseAdapter
|
|
20
|
+
} from "../chunk-s8mqwnm1.js";
|
|
21
|
+
import {
|
|
22
|
+
__require
|
|
23
|
+
} from "../chunk-8sqjbsgt.js";
|
|
24
|
+
|
|
25
|
+
// src/db/postgres.ts
|
|
26
|
+
import fs from "node:fs/promises";
|
|
27
|
+
import path from "node:path";
|
|
28
|
+
import { pathToFileURL } from "node:url";
|
|
29
|
+
import {
|
|
30
|
+
CompiledQuery,
|
|
31
|
+
FileMigrationProvider,
|
|
32
|
+
Migrator,
|
|
33
|
+
PostgresDialect
|
|
34
|
+
} from "kysely";
|
|
35
|
+
class PostgresAdapter extends BaseDatabaseAdapter {
|
|
36
|
+
name = "postgres";
|
|
37
|
+
_rawDb = null;
|
|
38
|
+
_db = null;
|
|
39
|
+
_collections = [];
|
|
40
|
+
_globals = [];
|
|
41
|
+
config;
|
|
42
|
+
push;
|
|
43
|
+
migrationDir;
|
|
44
|
+
pushDestructive;
|
|
45
|
+
get raw() {
|
|
46
|
+
return this._rawDb;
|
|
47
|
+
}
|
|
48
|
+
get db() {
|
|
49
|
+
if (!this._db)
|
|
50
|
+
throw new Error("Database not connected. Call connect() first.");
|
|
51
|
+
return this._db;
|
|
52
|
+
}
|
|
53
|
+
constructor(config, options) {
|
|
54
|
+
super();
|
|
55
|
+
this.config = config;
|
|
56
|
+
this.push = options?.push ?? true;
|
|
57
|
+
this.pushDestructive = options?.pushDestructive ?? false;
|
|
58
|
+
this.migrationDir = options?.migrationDir ?? "./migrations";
|
|
59
|
+
}
|
|
60
|
+
async connect() {
|
|
61
|
+
if (this._rawDb)
|
|
62
|
+
return;
|
|
63
|
+
const { default: postgres } = await import("postgres");
|
|
64
|
+
if (typeof this.config === "string") {
|
|
65
|
+
this._rawDb = postgres(this.config);
|
|
66
|
+
} else {
|
|
67
|
+
this._rawDb = postgres({
|
|
68
|
+
host: this.config.host,
|
|
69
|
+
port: this.config.port,
|
|
70
|
+
database: this.config.database,
|
|
71
|
+
username: this.config.username,
|
|
72
|
+
password: this.config.password,
|
|
73
|
+
ssl: this.config.ssl
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const { createOpacaKysely } = await import("../chunk-gzbz5jwy.js");
|
|
77
|
+
this._db = createOpacaKysely({
|
|
78
|
+
dialect: new PostgresDialect({
|
|
79
|
+
pool: {
|
|
80
|
+
connect: async () => {
|
|
81
|
+
const conn = await this._rawDb.reserve();
|
|
82
|
+
const query = async (sqlStr, parameters) => {
|
|
83
|
+
try {
|
|
84
|
+
const res = await conn.unsafe(sqlStr, parameters || []);
|
|
85
|
+
return { rows: res };
|
|
86
|
+
} catch (e) {
|
|
87
|
+
const wrapped = new Error(e.message);
|
|
88
|
+
wrapped.code = e.code;
|
|
89
|
+
wrapped.detail = e.detail;
|
|
90
|
+
wrapped.hint = e.hint;
|
|
91
|
+
wrapped.position = e.position;
|
|
92
|
+
wrapped.stack = e.stack;
|
|
93
|
+
throw wrapped;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return { query, release: () => conn.release() };
|
|
97
|
+
},
|
|
98
|
+
end: async () => {},
|
|
99
|
+
on: () => {}
|
|
100
|
+
}
|
|
101
|
+
}),
|
|
102
|
+
config: {
|
|
103
|
+
collections: this._collections,
|
|
104
|
+
globals: this._globals,
|
|
105
|
+
db: { name: "postgres" }
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async disconnect() {
|
|
110
|
+
if (this._db)
|
|
111
|
+
await this.db.destroy();
|
|
112
|
+
if (this._rawDb)
|
|
113
|
+
await this._rawDb.end();
|
|
114
|
+
this._db = null;
|
|
115
|
+
this._rawDb = null;
|
|
116
|
+
}
|
|
117
|
+
async unsafe(query, params) {
|
|
118
|
+
if (!this.db)
|
|
119
|
+
throw new Error("DB not connected");
|
|
120
|
+
const compiled = CompiledQuery.raw(query, params || []);
|
|
121
|
+
const result = await this.db.executeQuery(compiled);
|
|
122
|
+
return result.rows;
|
|
123
|
+
}
|
|
124
|
+
async count(collection, query) {
|
|
125
|
+
const tableName = toSnakeCase(collection);
|
|
126
|
+
let qb = this.db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
|
|
127
|
+
if (query && Object.keys(query).length > 0) {
|
|
128
|
+
qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
129
|
+
}
|
|
130
|
+
const result = await qb.executeTakeFirst();
|
|
131
|
+
return Number(result?.count || 0);
|
|
132
|
+
}
|
|
133
|
+
async create(collection, data) {
|
|
134
|
+
if (!this.db)
|
|
135
|
+
throw new Error("DB not connected");
|
|
136
|
+
const tableName = toSnakeCase(collection);
|
|
137
|
+
return this.db.transaction().execute(async (tx) => {
|
|
138
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
139
|
+
const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
|
|
140
|
+
const flatData = flattenPayload(data, "", jsonFields);
|
|
141
|
+
const hasManyData = {};
|
|
142
|
+
const blocksData = {};
|
|
143
|
+
for (const key in flatData) {
|
|
144
|
+
if (Array.isArray(flatData[key])) {
|
|
145
|
+
const isHasMany = colDef?.fields.some((f) => f.type === "relationship" && ("hasMany" in f) && f.hasMany && f.name === key);
|
|
146
|
+
if (isHasMany) {
|
|
147
|
+
hasManyData[key] = flatData[key];
|
|
148
|
+
} else {
|
|
149
|
+
blocksData[key] = flatData[key];
|
|
150
|
+
}
|
|
151
|
+
delete flatData[key];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!flatData.id) {
|
|
155
|
+
flatData.id = crypto.randomUUID();
|
|
156
|
+
}
|
|
157
|
+
await tx.insertInto(tableName).values(flatData).execute();
|
|
158
|
+
for (const [key, values] of Object.entries(hasManyData)) {
|
|
159
|
+
const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
|
|
160
|
+
if (values.length > 0) {
|
|
161
|
+
const joinData = values.map((val, idx) => {
|
|
162
|
+
const tId = typeof val === "object" ? val.id : val;
|
|
163
|
+
return { id: crypto.randomUUID(), source_id: flatData.id, target_id: tId, order: idx };
|
|
164
|
+
});
|
|
165
|
+
await tx.insertInto(joinTableName).values(joinData).execute();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const [key, blocks] of Object.entries(blocksData)) {
|
|
169
|
+
for (let i = 0;i < blocks.length; i++) {
|
|
170
|
+
const block = blocks[i];
|
|
171
|
+
if (!block.blockType)
|
|
172
|
+
continue;
|
|
173
|
+
const blockTableName = `${tableName}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
|
|
174
|
+
const bId = block.id || crypto.randomUUID();
|
|
175
|
+
const blockFlatData = flattenPayload({ ...block, id: bId });
|
|
176
|
+
delete blockFlatData.blockType;
|
|
177
|
+
await tx.insertInto(blockTableName).values({
|
|
178
|
+
...blockFlatData,
|
|
179
|
+
_parent_id: flatData.id,
|
|
180
|
+
_order: i,
|
|
181
|
+
block_type: block.blockType
|
|
182
|
+
}).execute();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return this.findOne(collection, { id: flatData.id }, tx);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
async findOne(collection, query, tx) {
|
|
189
|
+
const tableName = toSnakeCase(collection);
|
|
190
|
+
const executor = tx || this.db;
|
|
191
|
+
if (!executor)
|
|
192
|
+
throw new Error("DB not connected");
|
|
193
|
+
let qb = executor.selectFrom(tableName).selectAll();
|
|
194
|
+
if (query && Object.keys(query).length > 0) {
|
|
195
|
+
qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
196
|
+
}
|
|
197
|
+
const row = await qb.executeTakeFirst();
|
|
198
|
+
if (!row)
|
|
199
|
+
return null;
|
|
200
|
+
const unflattened = unflattenRow(row);
|
|
201
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
202
|
+
if (colDef) {
|
|
203
|
+
const relationalFields = getRelationalFields(colDef.fields);
|
|
204
|
+
for (const field of relationalFields) {
|
|
205
|
+
if (!field.name)
|
|
206
|
+
continue;
|
|
207
|
+
const snakeName = toSnakeCase(field.name);
|
|
208
|
+
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
209
|
+
const joinTableName = `${collection}_${snakeName}_relations`.toLowerCase();
|
|
210
|
+
try {
|
|
211
|
+
const relations = await executor.selectFrom(joinTableName).selectAll().where("source_id", "=", row.id).orderBy("order", "asc").execute();
|
|
212
|
+
const parts = field.name.split("__");
|
|
213
|
+
let current = unflattened;
|
|
214
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
215
|
+
if (!current[parts[i]])
|
|
216
|
+
current[parts[i]] = {};
|
|
217
|
+
current = current[parts[i]];
|
|
218
|
+
}
|
|
219
|
+
current[parts[parts.length - 1]] = relations.map((r) => r.target_id);
|
|
220
|
+
} catch (e) {}
|
|
221
|
+
} else if (field.type === "blocks" && "blocks" in field && field.blocks) {
|
|
222
|
+
const blockData = [];
|
|
223
|
+
for (const b of field.blocks) {
|
|
224
|
+
const blockTableName = `${collection}_${snakeName}_${b.slug}`.toLowerCase();
|
|
225
|
+
try {
|
|
226
|
+
const blocks = await executor.selectFrom(blockTableName).selectAll().where("_parent_id", "=", row.id).execute();
|
|
227
|
+
for (const blk of blocks) {
|
|
228
|
+
const uf = unflattenRow(blk);
|
|
229
|
+
uf.blockType = blk.block_type;
|
|
230
|
+
blockData.push(uf);
|
|
231
|
+
}
|
|
232
|
+
} catch (e) {}
|
|
233
|
+
}
|
|
234
|
+
blockData.sort((a, b) => a._order - b._order);
|
|
235
|
+
blockData.forEach((b) => {
|
|
236
|
+
delete b._order;
|
|
237
|
+
delete b._parent_id;
|
|
238
|
+
});
|
|
239
|
+
const parts = field.name.split("__");
|
|
240
|
+
let current = unflattened;
|
|
241
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
242
|
+
if (!current[parts[i]])
|
|
243
|
+
current[parts[i]] = {};
|
|
244
|
+
current = current[parts[i]];
|
|
245
|
+
}
|
|
246
|
+
current[parts[parts.length - 1]] = blockData;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return unflattened;
|
|
251
|
+
}
|
|
252
|
+
async find(collection, query, options) {
|
|
253
|
+
if (!this.db)
|
|
254
|
+
throw new Error("DB not connected");
|
|
255
|
+
const page = options?.page || 1;
|
|
256
|
+
const limit = options?.limit || 10;
|
|
257
|
+
const offset = (page - 1) * limit;
|
|
258
|
+
const cursorColumn = options?.cursorColumn || "id";
|
|
259
|
+
const total = await this.count(collection, query);
|
|
260
|
+
const tableName = toSnakeCase(collection);
|
|
261
|
+
let qb = this.db.selectFrom(tableName).selectAll().limit(limit);
|
|
262
|
+
if (options?.after) {
|
|
263
|
+
qb = qb.where(cursorColumn, ">", options.after);
|
|
264
|
+
} else if (options?.before) {
|
|
265
|
+
qb = qb.where(cursorColumn, "<", options.before);
|
|
266
|
+
} else {
|
|
267
|
+
qb = qb.offset(offset);
|
|
268
|
+
}
|
|
269
|
+
if (query && Object.keys(query).length > 0) {
|
|
270
|
+
qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
271
|
+
}
|
|
272
|
+
if (options?.sort) {
|
|
273
|
+
const [col, dir] = (options.sort ?? "").split(":");
|
|
274
|
+
if (col) {
|
|
275
|
+
qb = qb.orderBy(col, dir === "desc" ? "desc" : "asc");
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
qb = qb.orderBy(cursorColumn, "desc");
|
|
279
|
+
}
|
|
280
|
+
const rows = await qb.execute();
|
|
281
|
+
if (rows.length === 0) {
|
|
282
|
+
const totalPages2 = Math.ceil(total / limit);
|
|
283
|
+
const afterAnchor = options?.after;
|
|
284
|
+
const beforeAnchor = options?.before;
|
|
285
|
+
return {
|
|
286
|
+
docs: [],
|
|
287
|
+
totalDocs: total,
|
|
288
|
+
limit,
|
|
289
|
+
totalPages: totalPages2,
|
|
290
|
+
page,
|
|
291
|
+
pagingCounter: offset + 1,
|
|
292
|
+
hasNextPage: false,
|
|
293
|
+
hasPrevPage: !!afterAnchor || page > 1,
|
|
294
|
+
prevPage: null,
|
|
295
|
+
nextPage: null,
|
|
296
|
+
nextCursor: null,
|
|
297
|
+
prevCursor: afterAnchor ? afterAnchor : null
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
const rowIds = rows.map((r) => r.id);
|
|
301
|
+
const docs = rows.map((r) => unflattenRow(r));
|
|
302
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
303
|
+
if (colDef) {
|
|
304
|
+
const relationalFields = getRelationalFields(colDef.fields);
|
|
305
|
+
for (const field of relationalFields) {
|
|
306
|
+
if (!field.name)
|
|
307
|
+
continue;
|
|
308
|
+
const snakeName = toSnakeCase(field.name);
|
|
309
|
+
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
310
|
+
const joinTableName = `${toSnakeCase(collection)}_${snakeName}_relations`.toLowerCase();
|
|
311
|
+
try {
|
|
312
|
+
const allRelations = await this.db.selectFrom(joinTableName).selectAll().where("source_id", "in", rowIds).orderBy("order", "asc").execute();
|
|
313
|
+
const relationsBySource = allRelations.reduce((acc, r) => {
|
|
314
|
+
if (!acc[r.source_id])
|
|
315
|
+
acc[r.source_id] = [];
|
|
316
|
+
acc[r.source_id].push(r.target_id);
|
|
317
|
+
return acc;
|
|
318
|
+
}, {});
|
|
319
|
+
const parts = field.name.split("__");
|
|
320
|
+
for (let docIdx = 0;docIdx < docs.length; docIdx++) {
|
|
321
|
+
const rowId = rowIds[docIdx];
|
|
322
|
+
let current = docs[docIdx];
|
|
323
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
324
|
+
if (!current[parts[i]])
|
|
325
|
+
current[parts[i]] = {};
|
|
326
|
+
current = current[parts[i]];
|
|
327
|
+
}
|
|
328
|
+
current[parts[parts.length - 1]] = relationsBySource[rowId] || [];
|
|
329
|
+
}
|
|
330
|
+
} catch (e) {}
|
|
331
|
+
} else if (field.type === "blocks" && field.blocks) {
|
|
332
|
+
const blocksBySource = {};
|
|
333
|
+
for (const b of field.blocks) {
|
|
334
|
+
const blockTableName = `${collection}_${snakeName}_${toSnakeCase(b.slug)}`.toLowerCase();
|
|
335
|
+
try {
|
|
336
|
+
const allBlocks = await this.db.selectFrom(blockTableName).selectAll().where("_parent_id", "in", rowIds).execute();
|
|
337
|
+
for (const blk of allBlocks) {
|
|
338
|
+
const uf = unflattenRow(blk);
|
|
339
|
+
uf.blockType = blk.block_type;
|
|
340
|
+
if (!blocksBySource[blk._parent_id])
|
|
341
|
+
blocksBySource[blk._parent_id] = [];
|
|
342
|
+
blocksBySource[blk._parent_id].push(uf);
|
|
343
|
+
}
|
|
344
|
+
} catch (e) {}
|
|
345
|
+
}
|
|
346
|
+
const parts = field.name.split("__");
|
|
347
|
+
for (let docIdx = 0;docIdx < docs.length; docIdx++) {
|
|
348
|
+
const rowId = rowIds[docIdx];
|
|
349
|
+
const blockData = blocksBySource[rowId] || [];
|
|
350
|
+
blockData.sort((a, b) => a._order - b._order);
|
|
351
|
+
blockData.forEach((b) => {
|
|
352
|
+
delete b._order;
|
|
353
|
+
delete b._parentId;
|
|
354
|
+
});
|
|
355
|
+
let current = docs[docIdx];
|
|
356
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
357
|
+
if (!current[parts[i]])
|
|
358
|
+
current[parts[i]] = {};
|
|
359
|
+
current = current[parts[i]];
|
|
360
|
+
}
|
|
361
|
+
current[parts[parts.length - 1]] = blockData;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const totalPages = Math.ceil(total / limit);
|
|
367
|
+
const hasNextPage = page * limit < total;
|
|
368
|
+
return {
|
|
369
|
+
docs: docs.filter(Boolean),
|
|
370
|
+
totalDocs: total,
|
|
371
|
+
limit,
|
|
372
|
+
totalPages,
|
|
373
|
+
page,
|
|
374
|
+
pagingCounter: offset + 1,
|
|
375
|
+
hasNextPage,
|
|
376
|
+
hasPrevPage: page > 1 || !!options?.after || !!options?.before,
|
|
377
|
+
prevPage: page > 1 ? page - 1 : null,
|
|
378
|
+
nextPage: page < totalPages ? page + 1 : null,
|
|
379
|
+
nextCursor: docs.length > 0 && hasNextPage ? docs[docs.length - 1][cursorColumn] : null,
|
|
380
|
+
prevCursor: docs.length > 0 && (page > 1 || !!options?.after || !!options?.before) ? docs[0][cursorColumn] : null
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async update(collection, query, data) {
|
|
384
|
+
if (!this.db)
|
|
385
|
+
throw new Error("DB not connected");
|
|
386
|
+
return this.db.transaction().execute(async (tx) => {
|
|
387
|
+
let normalizedQuery = query;
|
|
388
|
+
if (typeof query !== "object" || query === null) {
|
|
389
|
+
normalizedQuery = { id: query };
|
|
390
|
+
}
|
|
391
|
+
const current = await this.findOne(collection, normalizedQuery, tx);
|
|
392
|
+
if (!current)
|
|
393
|
+
throw new Error("Document not found");
|
|
394
|
+
const store = requestContext.getStore();
|
|
395
|
+
if (store)
|
|
396
|
+
store.previousData = current;
|
|
397
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
398
|
+
const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
|
|
399
|
+
const flatData = flattenPayload(data, "", jsonFields);
|
|
400
|
+
const hasManyData = {};
|
|
401
|
+
const blocksData = {};
|
|
402
|
+
for (const key in flatData) {
|
|
403
|
+
if (Array.isArray(flatData[key])) {
|
|
404
|
+
const isHasMany = colDef?.fields.some((f) => f.type === "relationship" && ("hasMany" in f) && f.hasMany && f.name === key);
|
|
405
|
+
if (isHasMany) {
|
|
406
|
+
hasManyData[key] = flatData[key];
|
|
407
|
+
} else {
|
|
408
|
+
blocksData[key] = flatData[key];
|
|
409
|
+
}
|
|
410
|
+
delete flatData[key];
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
flatData.updatedAt = new Date().toISOString();
|
|
414
|
+
const tableName = toSnakeCase(collection);
|
|
415
|
+
if (Object.keys(flatData).length > 0) {
|
|
416
|
+
await tx.updateTable(tableName).set(flatData).where("id", "=", current.id).execute();
|
|
417
|
+
}
|
|
418
|
+
for (const [key, values] of Object.entries(hasManyData)) {
|
|
419
|
+
const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
|
|
420
|
+
await tx.deleteFrom(joinTableName).where("source_id", "=", current.id).execute();
|
|
421
|
+
if (values.length > 0) {
|
|
422
|
+
const joinData = values.map((val, idx) => {
|
|
423
|
+
const tId = typeof val === "object" ? val.id : val;
|
|
424
|
+
return { id: crypto.randomUUID(), source_id: current.id, target_id: tId, order: idx };
|
|
425
|
+
});
|
|
426
|
+
await tx.insertInto(joinTableName).values(joinData).execute();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
for (const [key, blocks] of Object.entries(blocksData)) {
|
|
430
|
+
const fieldDef = colDef?.fields.find((f) => f.name === key);
|
|
431
|
+
if (fieldDef && "blocks" in fieldDef && fieldDef.blocks) {
|
|
432
|
+
await Promise.all(fieldDef.blocks.map(async (b) => {
|
|
433
|
+
const blockTableName = `${tableName}_${toSnakeCase(key)}_${b.slug}`.toLowerCase();
|
|
434
|
+
try {
|
|
435
|
+
await tx.deleteFrom(blockTableName).where("_parent_id", "=", current.id).execute();
|
|
436
|
+
} catch (e) {}
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
for (let i = 0;i < blocks.length; i++) {
|
|
440
|
+
const block = blocks[i];
|
|
441
|
+
if (!block.blockType)
|
|
442
|
+
continue;
|
|
443
|
+
const blockTableName = `${tableName}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
|
|
444
|
+
const bId = block.id || crypto.randomUUID();
|
|
445
|
+
const blockFlatData = flattenPayload({ ...block, id: bId });
|
|
446
|
+
delete blockFlatData.blockType;
|
|
447
|
+
await tx.insertInto(blockTableName).values({
|
|
448
|
+
...blockFlatData,
|
|
449
|
+
_parent_id: current.id,
|
|
450
|
+
_order: i,
|
|
451
|
+
block_type: block.blockType
|
|
452
|
+
}).execute();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return this.findOne(collection, { id: current.id }, tx);
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
async updateMany(collection, query, data) {
|
|
459
|
+
if (!this.db)
|
|
460
|
+
throw new Error("DB not connected");
|
|
461
|
+
const tableName = toSnakeCase(collection);
|
|
462
|
+
return this.db.transaction().execute(async (tx) => {
|
|
463
|
+
let qb = tx.updateTable(tableName);
|
|
464
|
+
if (query && Object.keys(query).length > 0) {
|
|
465
|
+
qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
466
|
+
}
|
|
467
|
+
const flatData = flattenPayload(data);
|
|
468
|
+
for (const key in flatData) {
|
|
469
|
+
if (Array.isArray(flatData[key])) {
|
|
470
|
+
delete flatData[key];
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
flatData.updatedAt = new Date().toISOString();
|
|
474
|
+
if (Object.keys(flatData).length > 0) {
|
|
475
|
+
const result = await qb.set(flatData).executeTakeFirst();
|
|
476
|
+
return Number(result.numUpdatedRows || 0);
|
|
477
|
+
}
|
|
478
|
+
return 0;
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
async delete(collection, query) {
|
|
482
|
+
if (!this.db)
|
|
483
|
+
throw new Error("DB not connected");
|
|
484
|
+
let normalizedQuery = query;
|
|
485
|
+
if (typeof query !== "object" || query === null) {
|
|
486
|
+
normalizedQuery = { id: query };
|
|
487
|
+
}
|
|
488
|
+
const current = await this.findOne(collection, normalizedQuery);
|
|
489
|
+
if (!current)
|
|
490
|
+
return false;
|
|
491
|
+
const tableName = toSnakeCase(collection);
|
|
492
|
+
await this.db.transaction().execute(async (tx) => {
|
|
493
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
494
|
+
if (colDef) {
|
|
495
|
+
for (const field of colDef.fields) {
|
|
496
|
+
const snakeName = toSnakeCase(field.name);
|
|
497
|
+
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
498
|
+
const joinTableName = `${tableName}_${snakeName}_relations`.toLowerCase();
|
|
499
|
+
try {
|
|
500
|
+
await tx.deleteFrom(joinTableName).where("source_id", "=", current.id).execute();
|
|
501
|
+
} catch (e) {}
|
|
502
|
+
} else if (field.type === "blocks" && "blocks" in field && field.blocks) {
|
|
503
|
+
await Promise.all(field.blocks.map(async (b) => {
|
|
504
|
+
const blockTableName = `${tableName}_${snakeName}_${b.slug}`.toLowerCase();
|
|
505
|
+
try {
|
|
506
|
+
await tx.deleteFrom(blockTableName).where("_parent_id", "=", current.id).execute();
|
|
507
|
+
} catch (e) {}
|
|
508
|
+
}));
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
await tx.deleteFrom(tableName).where("id", "=", current.id).execute();
|
|
513
|
+
});
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
async deleteMany(collection, query) {
|
|
517
|
+
if (!this.db)
|
|
518
|
+
throw new Error("DB not connected");
|
|
519
|
+
const tableName = toSnakeCase(collection);
|
|
520
|
+
return this.db.transaction().execute(async (tx) => {
|
|
521
|
+
let selectQb = tx.selectFrom(tableName).select("id");
|
|
522
|
+
if (query && Object.keys(query).length > 0) {
|
|
523
|
+
selectQb = selectQb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
524
|
+
}
|
|
525
|
+
const docs = await selectQb.execute();
|
|
526
|
+
if (docs.length === 0)
|
|
527
|
+
return 0;
|
|
528
|
+
const ids = docs.map((d) => d.id);
|
|
529
|
+
const colDef = this._collections.find((c) => c.slug === collection);
|
|
530
|
+
if (colDef) {
|
|
531
|
+
for (const field of colDef.fields) {
|
|
532
|
+
const snakeName = toSnakeCase(field.name);
|
|
533
|
+
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
534
|
+
const joinTableName = `${tableName}_${snakeName}_relations`.toLowerCase();
|
|
535
|
+
try {
|
|
536
|
+
await tx.deleteFrom(joinTableName).where("source_id", "in", ids).execute();
|
|
537
|
+
} catch (e) {}
|
|
538
|
+
} else if (field.type === "blocks" && "blocks" in field && field.blocks) {
|
|
539
|
+
await Promise.all(field.blocks.map(async (b) => {
|
|
540
|
+
const blockTableName = `${tableName}_${snakeName}_${b.slug}`.toLowerCase();
|
|
541
|
+
try {
|
|
542
|
+
await tx.deleteFrom(blockTableName).where("_parent_id", "in", ids).execute();
|
|
543
|
+
} catch (e) {}
|
|
544
|
+
}));
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
const result = await tx.deleteFrom(tableName).where("id", "in", ids).executeTakeFirst();
|
|
549
|
+
return Number(result.numDeletedRows || 0);
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
async findGlobal(slug) {
|
|
553
|
+
if (!this.db)
|
|
554
|
+
throw new Error("DB not connected");
|
|
555
|
+
const tableName = toSnakeCase(slug);
|
|
556
|
+
const row = await this.db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
|
|
557
|
+
return row ? unflattenRow(row) : null;
|
|
558
|
+
}
|
|
559
|
+
async updateGlobal(slug, data) {
|
|
560
|
+
if (!this.db)
|
|
561
|
+
throw new Error("DB not connected");
|
|
562
|
+
const tableName = toSnakeCase(slug);
|
|
563
|
+
const existing = await this.findGlobal(slug);
|
|
564
|
+
const globalDef = this._globals.find((g) => g.slug === slug);
|
|
565
|
+
const jsonFields = globalDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
|
|
566
|
+
const flatData = flattenPayload(data, "", jsonFields);
|
|
567
|
+
const now = new Date().toISOString();
|
|
568
|
+
flatData[toSnakeCase("updatedAt")] = now;
|
|
569
|
+
if (!existing) {
|
|
570
|
+
if (!flatData.id)
|
|
571
|
+
flatData.id = "global";
|
|
572
|
+
flatData[toSnakeCase("createdAt")] = now;
|
|
573
|
+
await this.db.insertInto(tableName).values(flatData).execute();
|
|
574
|
+
} else {
|
|
575
|
+
await this.db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
|
|
576
|
+
}
|
|
577
|
+
return this.findGlobal(slug);
|
|
578
|
+
}
|
|
579
|
+
async runMigrations() {
|
|
580
|
+
if (!this.db)
|
|
581
|
+
throw new Error("DB not connected");
|
|
582
|
+
const migrator = new Migrator({
|
|
583
|
+
db: this.db,
|
|
584
|
+
provider: new FileMigrationProvider({
|
|
585
|
+
fs,
|
|
586
|
+
path,
|
|
587
|
+
migrationFolder: pathToFileURL(path.resolve(process.cwd(), this.migrationDir)).href
|
|
588
|
+
})
|
|
589
|
+
});
|
|
590
|
+
const { error, results } = await migrator.migrateToLatest();
|
|
591
|
+
results?.forEach((it) => {
|
|
592
|
+
if (it.status === "Success") {
|
|
593
|
+
logger.success(`\uD83D\uDE80 Migration "${it.migrationName}" was executed successfully`);
|
|
594
|
+
} else if (it.status === "Error") {
|
|
595
|
+
logger.error(`❌ Migration "${it.migrationName}" failed`);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
if (error) {
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async migrate(collections, globals = []) {
|
|
603
|
+
const { getSystemCollections } = await import("../chunk-40tky6qh.js");
|
|
604
|
+
this._collections = [...getSystemCollections(), ...collections];
|
|
605
|
+
this._globals = globals;
|
|
606
|
+
if (this.push && this._db) {
|
|
607
|
+
await pushSchema(this.db, "postgres", collections, globals, {
|
|
608
|
+
pushDestructive: this.pushDestructive
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function createPostgresAdapter(config, options) {
|
|
614
|
+
return new PostgresAdapter(config, options);
|
|
615
|
+
}
|
|
12
616
|
export {
|
|
13
617
|
createPostgresAdapter,
|
|
14
618
|
PostgresAdapter
|
package/dist/db/sqlite.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
32
32
|
findGlobal<T extends object>(slug: string): Promise<T | null>;
|
|
33
33
|
updateGlobal<T extends object>(slug: string, data: Partial<T>): Promise<T>;
|
|
34
34
|
runMigrations(): Promise<void>;
|
|
35
|
-
migrate(collections: Collection[], globals?: Global[]): Promise<void>;
|
|
35
|
+
migrate(collections: Collection[] | readonly Collection[], globals?: Global[] | readonly Global[]): Promise<void>;
|
|
36
36
|
}
|
|
37
37
|
export declare function createSQLiteAdapter(path: string, options?: {
|
|
38
38
|
push?: boolean;
|