opacacms 0.2.1 → 0.3.1
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 +66 -16
- 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-jdfw4v3r.js → chunk-3j9zjfmn.js} +95 -30
- package/dist/{chunk-byq8g0rd.js → chunk-48ywpd0a.js} +16 -22
- package/dist/{chunk-tfnaf41w.js → chunk-5422w4eq.js} +41 -25
- 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-2es275xs.js → chunk-941zxavt.js} +867 -322
- 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-6d1vdfwa.js → chunk-e0g6gn7n.js} +54 -75
- 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-bygjkgrx.js → chunk-naqcqj8n.js} +57 -80
- package/dist/chunk-q5sb5dcr.js +15 -0
- package/dist/{chunk-06ks4ggh.js → chunk-qhdsjek6.js} +49 -89
- package/dist/{chunk-n133qpsm.js → chunk-qsh2nqz3.js} +50 -81
- 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/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/better-sqlite.d.ts +2 -3
- package/dist/db/better-sqlite.js +6 -5
- package/dist/db/bun-sqlite.d.ts +2 -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 +2 -2
- package/dist/db/postgres.js +6 -5
- package/dist/db/sqlite.d.ts +2 -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 +5 -5
- package/dist/types.d.ts +253 -42
- 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 +50 -11
- 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-g1jb60xd.js +0 -17
- package/dist/chunk-j53pz21t.js +0 -20
- package/dist/chunk-mkn49zmy.js +0 -102
- package/dist/chunk-r39em4yj.js +0 -29
- package/dist/chunk-rsf0tpy1.js +0 -8
- package/dist/chunk-srsac177.js +0 -85
- 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
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
mapFieldToSQLiteType,
|
|
6
6
|
toSnakeCase
|
|
7
7
|
} from "./chunk-qxt9vge8.js";
|
|
8
|
+
import {
|
|
9
|
+
logger
|
|
10
|
+
} from "./chunk-jq1drsen.js";
|
|
8
11
|
import {
|
|
9
12
|
getSystemCollections,
|
|
10
13
|
init_system_schema
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import {
|
|
13
|
-
logger
|
|
14
|
-
} from "./chunk-t0zg026p.js";
|
|
14
|
+
} from "./chunk-6qs0g65f.js";
|
|
15
15
|
|
|
16
16
|
// src/db/kysely/data-mapper.ts
|
|
17
17
|
function toCamelCase(str) {
|
|
@@ -192,7 +192,6 @@ function buildKyselyWhere(eb, query) {
|
|
|
192
192
|
|
|
193
193
|
// src/db/kysely/schema-builder.ts
|
|
194
194
|
import { sql } from "kysely";
|
|
195
|
-
init_system_schema();
|
|
196
195
|
|
|
197
196
|
// src/db/kysely/sql-utils.ts
|
|
198
197
|
function assertSafeIdentifier(identifier) {
|
|
@@ -206,6 +205,7 @@ function assertSafeIdentifier(identifier) {
|
|
|
206
205
|
}
|
|
207
206
|
|
|
208
207
|
// src/db/kysely/schema-builder.ts
|
|
208
|
+
init_system_schema();
|
|
209
209
|
async function pushSchema(db, dialect, collections, globals = [], options = {}) {
|
|
210
210
|
const rawSchemas = [...getSystemCollections(), ...collections, ...globals];
|
|
211
211
|
const allSchemas = [];
|
|
@@ -219,20 +219,15 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
219
219
|
const { pushDestructive } = options;
|
|
220
220
|
logger.debug(`Starting schema push via Kysely (${dialect})...`);
|
|
221
221
|
const mapType = dialect === "postgres" ? mapFieldToPostgresType : mapFieldToSQLiteType;
|
|
222
|
-
let
|
|
222
|
+
let tablesMetadata = [];
|
|
223
223
|
try {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
} else {
|
|
228
|
-
const res = await sql`SELECT name FROM sqlite_master WHERE type='table'`.execute(db);
|
|
229
|
-
existingTables = res.rows.map((r) => r.name);
|
|
230
|
-
}
|
|
231
|
-
} catch (_) {
|
|
232
|
-
logger.warn("Failed to fetch existing tables:");
|
|
224
|
+
tablesMetadata = await db.introspection.getTables();
|
|
225
|
+
} catch (e) {
|
|
226
|
+
logger.warn("Failed to fetch database introspection. Falling back to empty state.", e);
|
|
233
227
|
}
|
|
234
|
-
|
|
235
|
-
const
|
|
228
|
+
const existingTableMap = new Map(tablesMetadata.map((t) => [t.name, t]));
|
|
229
|
+
const existingTables = Array.from(existingTableMap.keys());
|
|
230
|
+
logger.debug(`Existing tables found: ${existingTables.join(", ")}`);
|
|
236
231
|
const expectedTableNames = new Set;
|
|
237
232
|
for (const collection of allSchemas) {
|
|
238
233
|
const slug = collection.slug;
|
|
@@ -242,8 +237,9 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
242
237
|
const flattenedFields = flattenFields(collection.fields);
|
|
243
238
|
const hasTimestamps = true;
|
|
244
239
|
const versions = collection.versions;
|
|
245
|
-
|
|
246
|
-
|
|
240
|
+
const existingTable = existingTableMap.get(tableName);
|
|
241
|
+
if (!existingTable) {
|
|
242
|
+
logger.info(` ${logger.format("green", "✔")} Creating table: ${logger.bold(`"${tableName}"`)}`);
|
|
247
243
|
let builder = db.schema.createTable(tableName).ifNotExists();
|
|
248
244
|
builder = builder.addColumn("id", "text", (col) => col.primaryKey());
|
|
249
245
|
for (const field of flattenedFields) {
|
|
@@ -278,29 +274,8 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
278
274
|
builder = builder.addColumn(updatedField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
|
|
279
275
|
}
|
|
280
276
|
await builder.execute();
|
|
281
|
-
if (versions) {
|
|
282
|
-
const versionsTable = `${tableName}_versions`.toLowerCase();
|
|
283
|
-
assertSafeIdentifier(versionsTable);
|
|
284
|
-
expectedTableNames.add(versionsTable);
|
|
285
|
-
if (!existingTableSet.has(versionsTable)) {
|
|
286
|
-
logger.info(` -> Creating versions table: ${logger.format("green", `"${versionsTable}"`)}`);
|
|
287
|
-
await db.schema.createTable(versionsTable).addColumn("id", "text", (col) => col.primaryKey()).addColumn("_parent_id", "text", (col) => col.notNull()).addColumn("_version_data", dialect === "postgres" ? "jsonb" : "text", (col) => col.notNull()).addColumn("_status", "text").addColumn("created_at", dialect === "postgres" ? "timestamp with time zone" : "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
277
|
} else {
|
|
291
|
-
|
|
292
|
-
try {
|
|
293
|
-
if (dialect === "postgres") {
|
|
294
|
-
const res = await sql`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = ${tableName}`.execute(db);
|
|
295
|
-
existingColumns = res.rows.map((r) => r.column_name);
|
|
296
|
-
} else {
|
|
297
|
-
const res = await sql`PRAGMA table_info(${sql.id(tableName)})`.execute(db);
|
|
298
|
-
existingColumns = res.rows.map((r) => r.name);
|
|
299
|
-
}
|
|
300
|
-
} catch (e) {
|
|
301
|
-
logger.warn(`Failed to fetch columns for ${slug}:`, e);
|
|
302
|
-
}
|
|
303
|
-
const existingColSet = new Set(existingColumns);
|
|
278
|
+
const existingColSet = new Set(existingTable.columns.map((c) => c.name));
|
|
304
279
|
for (const field of flattenedFields) {
|
|
305
280
|
if (field.type === "relationship" && "hasMany" in field && field.hasMany)
|
|
306
281
|
continue;
|
|
@@ -309,13 +284,13 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
309
284
|
continue;
|
|
310
285
|
assertSafeIdentifier(colName);
|
|
311
286
|
if (!existingColSet.has(colName)) {
|
|
312
|
-
logger.info(`
|
|
287
|
+
logger.info(` ${logger.format("green", "✔")} Adding column: ${logger.bold(`${tableName}.${colName}`)}`);
|
|
313
288
|
const colType = mapType(field);
|
|
314
289
|
await db.schema.alterTable(tableName).addColumn(colName, colType).execute();
|
|
315
290
|
}
|
|
316
291
|
}
|
|
317
292
|
if (versions?.drafts && !existingColSet.has("_status")) {
|
|
318
|
-
logger.info(`
|
|
293
|
+
logger.info(` ${logger.format("green", "✔")} Adding status column to: ${tableName}`);
|
|
319
294
|
await db.schema.alterTable(tableName).addColumn("_status", "text", (col) => col.defaultTo("draft")).execute();
|
|
320
295
|
}
|
|
321
296
|
if (hasTimestamps) {
|
|
@@ -333,14 +308,6 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
333
308
|
await db.schema.alterTable(tableName).addColumn(updatedField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
334
309
|
}
|
|
335
310
|
}
|
|
336
|
-
if (versions) {
|
|
337
|
-
const versionsTable = `${tableName}_versions`.toLowerCase();
|
|
338
|
-
expectedTableNames.add(versionsTable);
|
|
339
|
-
if (!existingTableSet.has(versionsTable)) {
|
|
340
|
-
logger.info(` -> Creating missing versions table for: ${tableName}`);
|
|
341
|
-
await db.schema.createTable(versionsTable).addColumn("id", "text", (col) => col.primaryKey()).addColumn("_parent_id", "text", (col) => col.notNull()).addColumn("_version_data", dialect === "postgres" ? "jsonb" : "text", (col) => col.notNull()).addColumn("_status", "text").addColumn("created_at", dialect === "postgres" ? "timestamp with time zone" : "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
311
|
if (pushDestructive) {
|
|
345
312
|
const expectedCols = new Set(flattenedFields.filter((f) => !(f.type === "relationship" && f.hasMany)).map((f) => toSnakeCase(f.name)));
|
|
346
313
|
if (hasTimestamps) {
|
|
@@ -352,13 +319,14 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
352
319
|
if (versions?.drafts)
|
|
353
320
|
expectedCols.add("_status");
|
|
354
321
|
expectedCols.add("id");
|
|
355
|
-
for (const existingCol of
|
|
356
|
-
|
|
357
|
-
|
|
322
|
+
for (const existingCol of existingColSet) {
|
|
323
|
+
const colName = existingCol;
|
|
324
|
+
if (!expectedCols.has(colName)) {
|
|
325
|
+
logger.info(` -> Dropping stale column: ${logger.format("red", `${tableName}.${colName}`)}`);
|
|
358
326
|
try {
|
|
359
|
-
await db.schema.alterTable(tableName).dropColumn(
|
|
327
|
+
await db.schema.alterTable(tableName).dropColumn(colName).execute();
|
|
360
328
|
} catch (_) {
|
|
361
|
-
logger.warn(`Failed to drop column ${
|
|
329
|
+
logger.warn(`Failed to drop column ${colName}.`);
|
|
362
330
|
}
|
|
363
331
|
}
|
|
364
332
|
}
|
|
@@ -367,20 +335,18 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
367
335
|
const relationalFields = getRelationalFields(collection.fields);
|
|
368
336
|
for (const field of relationalFields) {
|
|
369
337
|
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
370
|
-
const sourceIdType = "text";
|
|
371
338
|
const colName = toSnakeCase(field.name);
|
|
372
339
|
const joinTableName = `${tableName}_${colName}_relations`.toLowerCase();
|
|
373
340
|
assertSafeIdentifier(joinTableName);
|
|
374
341
|
expectedTableNames.add(joinTableName);
|
|
375
|
-
if (!
|
|
342
|
+
if (!existingTableMap.has(joinTableName)) {
|
|
376
343
|
logger.info(` -> Creating relation table: ${logger.format("green", `"${joinTableName}"`)}`);
|
|
377
|
-
await db.schema.createTable(joinTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("source_id",
|
|
344
|
+
await db.schema.createTable(joinTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("source_id", "text", (col) => col.notNull()).addColumn("target_id", "text", (col) => col.notNull()).addColumn("order", "integer", (col) => col.defaultTo(0)).execute();
|
|
378
345
|
}
|
|
379
346
|
}
|
|
380
347
|
}
|
|
381
348
|
for (const field of relationalFields) {
|
|
382
349
|
if (field.type === "blocks" && field.blocks && Array.isArray(field.blocks)) {
|
|
383
|
-
const parentIdType = "text";
|
|
384
350
|
for (const block of field.blocks) {
|
|
385
351
|
const blockName = toSnakeCase(field.name);
|
|
386
352
|
const blockSlug = toSnakeCase(block.slug);
|
|
@@ -389,9 +355,10 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
389
355
|
const blockTableName = `${tableName}_${blockName}_${blockSlug}`.toLowerCase();
|
|
390
356
|
assertSafeIdentifier(blockTableName);
|
|
391
357
|
expectedTableNames.add(blockTableName);
|
|
392
|
-
|
|
358
|
+
const existingBlockTable = existingTableMap.get(blockTableName);
|
|
359
|
+
if (!existingBlockTable) {
|
|
393
360
|
logger.info(` -> Creating block table: ${logger.format("green", `"${blockTableName}"`)}`);
|
|
394
|
-
let bBuilder = db.schema.createTable(blockTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("_parent_id",
|
|
361
|
+
let bBuilder = db.schema.createTable(blockTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("_parent_id", "text", (col) => col.notNull()).addColumn("_order", "integer", (col) => col.defaultTo(0)).addColumn("block_type", "text", (col) => col.notNull().defaultTo(block.slug));
|
|
395
362
|
const blockFlattened = flattenFields(block.fields);
|
|
396
363
|
for (const bField of blockFlattened) {
|
|
397
364
|
const bColName = toSnakeCase(bField.name);
|
|
@@ -415,17 +382,7 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
415
382
|
bBuilder = bBuilder.addColumn("updated_at", tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
|
|
416
383
|
await bBuilder.execute();
|
|
417
384
|
} else {
|
|
418
|
-
|
|
419
|
-
try {
|
|
420
|
-
if (dialect === "postgres") {
|
|
421
|
-
const res = await sql`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = ${blockTableName}`.execute(db);
|
|
422
|
-
existingBCols = res.rows.map((r) => r.column_name);
|
|
423
|
-
} else {
|
|
424
|
-
const res = await sql`PRAGMA table_info(${sql.id(blockTableName)})`.execute(db);
|
|
425
|
-
existingBCols = res.rows.map((r) => r.name);
|
|
426
|
-
}
|
|
427
|
-
} catch (_) {}
|
|
428
|
-
const existingBColSet = new Set(existingBCols);
|
|
385
|
+
const existingBColSet = new Set(existingBlockTable.columns.map((c) => c.name));
|
|
429
386
|
const blockFlattened = flattenFields(block.fields);
|
|
430
387
|
for (const bField of blockFlattened) {
|
|
431
388
|
const bColName = toSnakeCase(bField.name);
|
|
@@ -466,7 +423,7 @@ async function pushSchema(db, dialect, collections, globals = [], options = {})
|
|
|
466
423
|
}
|
|
467
424
|
}
|
|
468
425
|
}
|
|
469
|
-
logger.
|
|
426
|
+
logger.info(`${logger.format("green", "✔")} Schema synchronization complete.`);
|
|
470
427
|
}
|
|
471
428
|
|
|
472
429
|
export { flattenPayload, unflattenRow, buildKyselyWhere, pushSchema };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// src/utils/logger.ts
|
|
2
2
|
var RESET = "\x1B[0m";
|
|
3
|
+
var BOLD = "\x1B[1m";
|
|
3
4
|
var BLUE = "\x1B[34m";
|
|
4
5
|
var GREEN = "\x1B[32m";
|
|
5
6
|
var YELLOW = "\x1B[33m";
|
|
6
7
|
var RED = "\x1B[31m";
|
|
7
8
|
var GRAY = "\x1B[90m";
|
|
8
|
-
var PREFIX = `${BLUE}[OpacaCMS]${RESET}`;
|
|
9
|
+
var PREFIX = `${BLUE}${BOLD}[OpacaCMS]${RESET}`;
|
|
9
10
|
var LOG_LEVELS = {
|
|
10
11
|
debug: 0,
|
|
11
12
|
info: 1,
|
|
@@ -49,6 +50,16 @@ class OpacaLogger {
|
|
|
49
50
|
return;
|
|
50
51
|
console.error(`${PREFIX} ${RED}Error: ${message}${RESET}`, ...args);
|
|
51
52
|
}
|
|
53
|
+
log(message, ...args) {
|
|
54
|
+
if (this.config.disabled)
|
|
55
|
+
return;
|
|
56
|
+
console.log(message, ...args);
|
|
57
|
+
}
|
|
58
|
+
bold(msg) {
|
|
59
|
+
if (this.config.disableColors)
|
|
60
|
+
return msg;
|
|
61
|
+
return `${BOLD}${msg}${RESET}`;
|
|
62
|
+
}
|
|
52
63
|
format(color, msg) {
|
|
53
64
|
if (this.config.disableColors)
|
|
54
65
|
return msg;
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
exports_compiler,
|
|
3
|
+
init_compiler
|
|
4
|
+
} from "./chunk-m5ems3hh.js";
|
|
5
|
+
import {
|
|
6
|
+
OpacaLogger
|
|
7
|
+
} from "./chunk-jq1drsen.js";
|
|
1
8
|
import {
|
|
2
9
|
getSystemCollections,
|
|
3
10
|
init_system_schema
|
|
4
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-6qs0g65f.js";
|
|
5
12
|
import {
|
|
6
|
-
|
|
7
|
-
} from "./chunk-
|
|
13
|
+
__toCommonJS
|
|
14
|
+
} from "./chunk-6bywt602.js";
|
|
8
15
|
|
|
9
16
|
// src/auth/index.ts
|
|
10
17
|
import { apiKey } from "@better-auth/api-key";
|
|
11
18
|
import { betterAuth } from "better-auth";
|
|
12
19
|
import { admin, openAPI } from "better-auth/plugins";
|
|
13
|
-
import { CamelCasePlugin } from "kysely";
|
|
14
20
|
|
|
15
21
|
// src/auth/premissions.ts
|
|
16
22
|
import { createAccessControl } from "better-auth/plugins/access";
|
|
@@ -48,10 +54,6 @@ function createPermissions(config) {
|
|
|
48
54
|
|
|
49
55
|
// src/auth/index.ts
|
|
50
56
|
async function createAuth(config) {
|
|
51
|
-
const userAuth = config.auth || {};
|
|
52
|
-
const trustedOrigins = config.trustedOrigins;
|
|
53
|
-
const { ac, roles } = createPermissions(config);
|
|
54
|
-
const rawDb = config.db.raw;
|
|
55
57
|
const env = typeof process !== "undefined" ? process.env : {};
|
|
56
58
|
const baseURL = String(config.serverURL || env.BETTER_AUTH_URL || "").replace(/\/$/, "");
|
|
57
59
|
if (!baseURL) {
|
|
@@ -65,20 +67,14 @@ async function createAuth(config) {
|
|
|
65
67
|
if (typeof process !== "undefined" && !env.BETTER_AUTH_URL) {
|
|
66
68
|
process.env.BETTER_AUTH_URL = authURL;
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
db: kysely.withPlugin(new CamelCasePlugin),
|
|
73
|
-
type: config.db.name === "postgres" ? "pg" : "sqlite"
|
|
74
|
-
};
|
|
75
|
-
} else {
|
|
76
|
-
databaseConfig = {
|
|
77
|
-
db: rawDb,
|
|
78
|
-
type: config.db.name === "postgres" ? "pg" : "sqlite"
|
|
79
|
-
};
|
|
80
|
-
}
|
|
70
|
+
const databaseConfig = {
|
|
71
|
+
db: config.db.db,
|
|
72
|
+
type: config.db.name === "postgres" ? "pg" : "sqlite"
|
|
73
|
+
};
|
|
81
74
|
const isSecure = baseURL.startsWith("https");
|
|
75
|
+
const userAuth = config.auth || {};
|
|
76
|
+
const { ac, roles } = createPermissions(config);
|
|
77
|
+
const trustedOrigins = config.trustedOrigins;
|
|
82
78
|
const plugins = [
|
|
83
79
|
admin({
|
|
84
80
|
ac,
|
|
@@ -177,6 +173,9 @@ async function createAuth(config) {
|
|
|
177
173
|
return msg.replace(/\[better-auth\]\s*/g, "").replace(/BETTER_AUTH_SECRET/g, "OPACA_SECRET").replace(/`npx auth secret`/g, "`openssl rand -base64 32`").replace(/npx auth secret/g, "openssl rand -base64 32").replace(/^Warning:\s*/i, "");
|
|
178
174
|
};
|
|
179
175
|
const branded = rebrand(message);
|
|
176
|
+
if (level === "error" && (branded.toLowerCase().includes("invalid api key") || branded.toLowerCase().includes("failed to validate api key"))) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
180
179
|
const brandedArgs = args.map((a) => typeof a === "string" ? rebrand(a) : a);
|
|
181
180
|
const authLogger = new OpacaLogger(config.logger);
|
|
182
181
|
switch (level) {
|
|
@@ -207,8 +206,8 @@ function sanitizeConfig(config, settings = {}) {
|
|
|
207
206
|
const supportsAuth = ["sqlite", "postgres", "d1", "bun-sqlite", "better-sqlite3"].includes(config.db.name);
|
|
208
207
|
const systemCollections = getSystemCollections();
|
|
209
208
|
for (const systemCol of systemCollections) {
|
|
210
|
-
const isAsset = systemCol.slug === "
|
|
211
|
-
const isAuth = ["_users", "_sessions", "_accounts", "_verifications", "_api_keys"
|
|
209
|
+
const isAsset = systemCol.slug === "_assets";
|
|
210
|
+
const isAuth = ["_users", "_sessions", "_accounts", "_verifications", "_api_keys"].includes(systemCol.slug);
|
|
212
211
|
if (isAsset && config.storages || isAuth && supportsAuth) {
|
|
213
212
|
if (!collections.find((col) => col.slug === systemCol.slug)) {
|
|
214
213
|
collections.push({
|
|
@@ -218,6 +217,11 @@ function sanitizeConfig(config, settings = {}) {
|
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
219
|
}
|
|
220
|
+
const serializeFn = (fn) => {
|
|
221
|
+
if (typeof fn !== "function")
|
|
222
|
+
return fn;
|
|
223
|
+
return `__opaca_fn__:${fn.toString()}`;
|
|
224
|
+
};
|
|
221
225
|
const sanitizeField = (f) => ({
|
|
222
226
|
name: f.name,
|
|
223
227
|
type: f.type,
|
|
@@ -226,11 +230,15 @@ function sanitizeConfig(config, settings = {}) {
|
|
|
226
230
|
unique: f.unique,
|
|
227
231
|
defaultValue: f.defaultValue,
|
|
228
232
|
localized: f.localized,
|
|
233
|
+
condition: serializeFn(f.condition),
|
|
234
|
+
requiredCondition: serializeFn(f.requiredCondition),
|
|
229
235
|
admin: f.admin ? {
|
|
230
236
|
description: f.admin.description,
|
|
231
237
|
hidden: f.admin.hidden,
|
|
232
238
|
readOnly: f.admin.readOnly,
|
|
233
|
-
components: f.admin.components
|
|
239
|
+
components: f.admin.components,
|
|
240
|
+
condition: serializeFn(f.admin.condition),
|
|
241
|
+
requiredCondition: serializeFn(f.admin.requiredCondition)
|
|
234
242
|
} : undefined,
|
|
235
243
|
options: f.options,
|
|
236
244
|
fields: f.fields ? f.fields.map(sanitizeField) : undefined,
|
|
@@ -285,8 +293,12 @@ function sanitizeConfig(config, settings = {}) {
|
|
|
285
293
|
adminAssets: p.adminAssets ? p.adminAssets() : undefined,
|
|
286
294
|
adminUI: p.adminUI,
|
|
287
295
|
settings: settings[p.name] || {},
|
|
288
|
-
configSchema: p.configSchema ? p.configSchema.map(sanitizeField) : undefined
|
|
289
|
-
}))
|
|
296
|
+
configSchema: p.configSchema ? (Array.isArray(p.configSchema) ? p.configSchema : (init_compiler(), __toCommonJS(exports_compiler)).zodToOpacaFields(p.configSchema)).map(sanitizeField) : undefined
|
|
297
|
+
})),
|
|
298
|
+
api: config.api ? {
|
|
299
|
+
rest: config.api.rest,
|
|
300
|
+
graphql: config.api.graphql
|
|
301
|
+
} : undefined
|
|
290
302
|
};
|
|
291
303
|
}
|
|
292
304
|
|