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
|
@@ -3,7 +3,7 @@ async function loadPluginSettings(config) {
|
|
|
3
3
|
if (!config.db)
|
|
4
4
|
return {};
|
|
5
5
|
try {
|
|
6
|
-
const result = await config.db.find("
|
|
6
|
+
const result = await config.db.find("_plugin_settings");
|
|
7
7
|
if (!result || !result.docs)
|
|
8
8
|
return {};
|
|
9
9
|
return result.docs.reduce((acc, curr) => {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
require_picocolors
|
|
3
|
+
} from "./chunk-rwqwsanx.js";
|
|
4
|
+
import {
|
|
5
|
+
Gt,
|
|
6
|
+
R,
|
|
7
|
+
Wt,
|
|
8
|
+
be
|
|
9
|
+
} from "./chunk-ec4jhybj.js";
|
|
10
|
+
import {
|
|
11
|
+
loadConfig,
|
|
12
|
+
resolveConfigPath
|
|
13
|
+
} from "./chunk-majsbncm.js";
|
|
14
|
+
import {
|
|
15
|
+
defineCommand
|
|
16
|
+
} from "./chunk-1qm0m8r8.js";
|
|
17
|
+
import {
|
|
18
|
+
__require,
|
|
19
|
+
__toESM
|
|
20
|
+
} from "./chunk-6bywt602.js";
|
|
21
|
+
|
|
22
|
+
// src/cli/commands/seed.ts
|
|
23
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
24
|
+
|
|
25
|
+
// src/cli/core/seeding/seed-logic.ts
|
|
26
|
+
async function seedCommand(opaca, count, reset, type, targetTable) {
|
|
27
|
+
const { autoSeed } = await import("./chunk-3j9zjfmn.js");
|
|
28
|
+
try {
|
|
29
|
+
await autoSeed(opaca, count, reset, type);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error(`[OpacaCMS] Seeding failed: ${error.message}`);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/cli/commands/seed.ts
|
|
37
|
+
var seed_default = defineCommand({
|
|
38
|
+
meta: {
|
|
39
|
+
name: "seed",
|
|
40
|
+
description: "Seed the database with mock data"
|
|
41
|
+
},
|
|
42
|
+
args: {
|
|
43
|
+
config: {
|
|
44
|
+
type: "string",
|
|
45
|
+
alias: "c",
|
|
46
|
+
description: "Path to the OpacaCMS configuration file"
|
|
47
|
+
},
|
|
48
|
+
count: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Number of documents to seed",
|
|
51
|
+
default: "10"
|
|
52
|
+
},
|
|
53
|
+
reset: {
|
|
54
|
+
type: "boolean",
|
|
55
|
+
description: "Clear the database before seeding"
|
|
56
|
+
},
|
|
57
|
+
assets: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Seed only assets"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
async run({ args }) {
|
|
63
|
+
console.log();
|
|
64
|
+
Wt(import_picocolors.default.bgGreen(import_picocolors.default.white(" OpacaCMS Seeder ")));
|
|
65
|
+
const s = be();
|
|
66
|
+
s.start("Loading configuration...");
|
|
67
|
+
let opaca;
|
|
68
|
+
try {
|
|
69
|
+
const configPath = resolveConfigPath(args.config);
|
|
70
|
+
opaca = await loadConfig(configPath);
|
|
71
|
+
s.stop(`Configuration loaded. DB: ${import_picocolors.default.cyan(opaca.db.name)}`);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
s.stop(import_picocolors.default.red("Failed to load configuration."));
|
|
74
|
+
R.error(err.message);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const type = args.assets ? "assets" : "collections";
|
|
78
|
+
const count = parseInt(args.count, 10);
|
|
79
|
+
s.start(`Seeding ${count} ${type}...`);
|
|
80
|
+
try {
|
|
81
|
+
await seedCommand(opaca, count, !!args.reset, type);
|
|
82
|
+
s.stop(`Successfully seeded ${import_picocolors.default.green(count)} ${type}!`);
|
|
83
|
+
Gt("Database seeded successfully. \uD83C\uDF31");
|
|
84
|
+
} catch (error) {
|
|
85
|
+
s.stop(import_picocolors.default.red("Seeding failed."));
|
|
86
|
+
R.error(error.message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
export {
|
|
92
|
+
seed_default as default
|
|
93
|
+
};
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateDiffCode
|
|
3
|
+
} from "./chunk-7rr5p01g.js";
|
|
4
|
+
import {
|
|
5
|
+
require_picocolors
|
|
6
|
+
} from "./chunk-rwqwsanx.js";
|
|
7
|
+
import {
|
|
8
|
+
Gt,
|
|
9
|
+
R,
|
|
10
|
+
Wt,
|
|
11
|
+
be
|
|
12
|
+
} from "./chunk-ec4jhybj.js";
|
|
13
|
+
import {
|
|
14
|
+
loadConfig,
|
|
15
|
+
resolveConfigPath
|
|
16
|
+
} from "./chunk-majsbncm.js";
|
|
17
|
+
import {
|
|
18
|
+
defineCommand
|
|
19
|
+
} from "./chunk-1qm0m8r8.js";
|
|
20
|
+
import {
|
|
21
|
+
getRandomMigrationName
|
|
22
|
+
} from "./chunk-5b8r0v8c.js";
|
|
23
|
+
import"./chunk-qxt9vge8.js";
|
|
24
|
+
import {
|
|
25
|
+
logger
|
|
26
|
+
} from "./chunk-jq1drsen.js";
|
|
27
|
+
import"./chunk-6qs0g65f.js";
|
|
28
|
+
import {
|
|
29
|
+
__require,
|
|
30
|
+
__toESM
|
|
31
|
+
} from "./chunk-6bywt602.js";
|
|
32
|
+
|
|
33
|
+
// src/cli/commands/migrate.ts
|
|
34
|
+
import fs2 from "node:fs";
|
|
35
|
+
import { relative as relative2, resolve as resolve2 } from "node:path";
|
|
36
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
37
|
+
|
|
38
|
+
// src/cli/core/migrations/migrate-logic.ts
|
|
39
|
+
import { spawnSync } from "node:child_process";
|
|
40
|
+
import fs from "node:fs";
|
|
41
|
+
import { relative, resolve } from "node:path";
|
|
42
|
+
async function migrateCreateCommand(opaca, migrationName, outDir) {
|
|
43
|
+
const db = opaca.db;
|
|
44
|
+
const migrationDir = outDir || db.migrationDir || "./migrations";
|
|
45
|
+
const fullMigrationDir = resolve(process.cwd(), migrationDir);
|
|
46
|
+
if (!fs.existsSync(fullMigrationDir)) {
|
|
47
|
+
fs.mkdirSync(fullMigrationDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, "").split(".")[0];
|
|
50
|
+
const { generateDiffCode: generateDiffCode2 } = await import("./chunk-gyaf5kgf.js");
|
|
51
|
+
let dialect = "sqlite";
|
|
52
|
+
if (db.name === "postgres")
|
|
53
|
+
dialect = "postgres";
|
|
54
|
+
if (db.name === "d1")
|
|
55
|
+
dialect = "d1";
|
|
56
|
+
const isD1 = dialect === "d1";
|
|
57
|
+
const name = !migrationName || migrationName === "migration" ? getRandomMigrationName() : migrationName;
|
|
58
|
+
const snapshotName = `${timestamp}_${name}`;
|
|
59
|
+
const fileName = `${snapshotName}.${isD1 ? "sql" : "ts"}`;
|
|
60
|
+
const filePath = resolve(fullMigrationDir, fileName);
|
|
61
|
+
const result = await generateDiffCode2(opaca, dialect, migrationDir, snapshotName, {
|
|
62
|
+
saveSnapshot: true,
|
|
63
|
+
interactive: true
|
|
64
|
+
});
|
|
65
|
+
if (!result.hasChanges) {
|
|
66
|
+
logger.info("✨ No schema changes detected. Migration not created.");
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
let template = "";
|
|
70
|
+
if (isD1) {
|
|
71
|
+
template = `-- OpacaCMS Auto-generated SQL Migration
|
|
72
|
+
-- Migration: ${snapshotName}
|
|
73
|
+
|
|
74
|
+
-- UP
|
|
75
|
+
${result.upCode}
|
|
76
|
+
`;
|
|
77
|
+
} else {
|
|
78
|
+
template = `import { type OpacaMigrationDb, sql } from 'opacacms/db';
|
|
79
|
+
|
|
80
|
+
export async function up(db: OpacaMigrationDb): Promise<void> {
|
|
81
|
+
${result.upCode}}
|
|
82
|
+
|
|
83
|
+
export async function down(db: OpacaMigrationDb): Promise<void> {
|
|
84
|
+
${result.downCode}}
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
87
|
+
fs.writeFileSync(filePath, template);
|
|
88
|
+
logger.success(`\uD83D\uDE80 Migration created successfully at ${relative(process.cwd(), filePath)}`);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
async function migrateRunCommand(db) {
|
|
92
|
+
logger.info("\uD83C\uDFAC Running migrations...");
|
|
93
|
+
if (db.runMigrations) {
|
|
94
|
+
await db.connect();
|
|
95
|
+
try {
|
|
96
|
+
await db.runMigrations();
|
|
97
|
+
logger.success("✅ Migrations applied successfully!");
|
|
98
|
+
} catch (error) {
|
|
99
|
+
logger.error(`❌ Failed to run migrations: ${error.message}`);
|
|
100
|
+
throw error;
|
|
101
|
+
} finally {}
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error(`Adapter ${db.name} does not support running migrations.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function migrateStatusCommand(opaca) {
|
|
107
|
+
logger.info("\uD83D\uDCCA Checking migration status...");
|
|
108
|
+
const db = opaca.db;
|
|
109
|
+
const migrationDir = db.migrationDir || "./migrations";
|
|
110
|
+
const fullMigrationDir = resolve(process.cwd(), migrationDir);
|
|
111
|
+
if (!fs.existsSync(fullMigrationDir)) {
|
|
112
|
+
logger.info("No migrations directory found.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const migrationFiles = fs.readdirSync(fullMigrationDir).filter((f) => f.endsWith(".ts") || f.endsWith(".sql")).sort();
|
|
116
|
+
let appliedMigrations = [];
|
|
117
|
+
try {
|
|
118
|
+
await db.connect();
|
|
119
|
+
const rows = await db.unsafe("SELECT name FROM kysely_migration").catch(() => []);
|
|
120
|
+
appliedMigrations = rows.map((r) => r.name);
|
|
121
|
+
} catch (e) {} finally {}
|
|
122
|
+
console.log(`
|
|
123
|
+
Found ${migrationFiles.length} migration files in ${migrationDir}:`);
|
|
124
|
+
for (const file of migrationFiles) {
|
|
125
|
+
const name = file.replace(/\.(ts|sql)$/, "");
|
|
126
|
+
const isApplied = appliedMigrations.includes(name);
|
|
127
|
+
console.log(` ${isApplied ? "✅ [Applied] " : "❌ [Pending] "} ${file}`);
|
|
128
|
+
}
|
|
129
|
+
const pending = migrationFiles.filter((f) => !appliedMigrations.includes(f.replace(/\.(ts|sql)$/, "")));
|
|
130
|
+
if (pending.length > 0) {
|
|
131
|
+
console.log(`
|
|
132
|
+
\uD83D\uDCA1 You have ${pending.length} pending migrations. Run 'opacacms migrate' to apply them.`);
|
|
133
|
+
} else {
|
|
134
|
+
console.log(`
|
|
135
|
+
✨ All migrations are up to date.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function migrateD1Command(migrationDir, isRemote, binding = "DB") {
|
|
139
|
+
const fullMigrationDir = resolve(process.cwd(), migrationDir);
|
|
140
|
+
if (!fs.existsSync(fullMigrationDir)) {
|
|
141
|
+
throw new Error(`[OpacaCMS] Migration directory not found: ${fullMigrationDir}`);
|
|
142
|
+
}
|
|
143
|
+
const migrations = fs.readdirSync(fullMigrationDir).filter((file) => file.endsWith(".sql")).sort();
|
|
144
|
+
if (migrations.length === 0) {
|
|
145
|
+
console.log(`[OpacaCMS] No SQL migrations found in ${fullMigrationDir}`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
console.log(`[OpacaCMS] Found ${migrations.length} migrations. Applying to ${isRemote ? "\uD83C\uDF0A REMOTE (Cloudflare D1)" : "\uD83D\uDCBB LOCAL (SQLite)"}...`);
|
|
149
|
+
for (const migration of migrations) {
|
|
150
|
+
const filePath = resolve(fullMigrationDir, migration);
|
|
151
|
+
console.log(`
|
|
152
|
+
[OpacaCMS] \uD83D\uDCE6 Applying: ${migration}...`);
|
|
153
|
+
const wranglerArgs = [
|
|
154
|
+
"wrangler",
|
|
155
|
+
"d1",
|
|
156
|
+
"execute",
|
|
157
|
+
binding,
|
|
158
|
+
"--file",
|
|
159
|
+
filePath,
|
|
160
|
+
isRemote ? "--remote" : "--local",
|
|
161
|
+
"--yes"
|
|
162
|
+
];
|
|
163
|
+
const result = spawnSync("bun", ["x", ...wranglerArgs], {
|
|
164
|
+
stdio: "inherit",
|
|
165
|
+
shell: false,
|
|
166
|
+
cwd: process.cwd()
|
|
167
|
+
});
|
|
168
|
+
if (result.status !== 0) {
|
|
169
|
+
console.error(`[OpacaCMS] ❌ Failed to apply migration: ${migration}`);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(`[OpacaCMS] ✅ Success: ${migration}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
console.log(`
|
|
175
|
+
[OpacaCMS] ✨ Database migration process completed!`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/cli/commands/migrate.ts
|
|
179
|
+
var migrate_default = defineCommand({
|
|
180
|
+
meta: {
|
|
181
|
+
name: "migrate",
|
|
182
|
+
description: "Manage database migrations"
|
|
183
|
+
},
|
|
184
|
+
args: {
|
|
185
|
+
config: {
|
|
186
|
+
type: "string",
|
|
187
|
+
alias: "c",
|
|
188
|
+
description: "Path to the OpacaCMS configuration file"
|
|
189
|
+
},
|
|
190
|
+
action: {
|
|
191
|
+
type: "positional",
|
|
192
|
+
description: "Action to perform: run (default), create, diff, status, d1",
|
|
193
|
+
required: false
|
|
194
|
+
},
|
|
195
|
+
name: {
|
|
196
|
+
type: "positional",
|
|
197
|
+
description: "Name of the migration (for create)",
|
|
198
|
+
required: false
|
|
199
|
+
},
|
|
200
|
+
out: {
|
|
201
|
+
type: "string",
|
|
202
|
+
alias: "o",
|
|
203
|
+
description: "Output directory for migrations"
|
|
204
|
+
},
|
|
205
|
+
remote: {
|
|
206
|
+
type: "boolean",
|
|
207
|
+
description: "Apply migrations to remote D1"
|
|
208
|
+
},
|
|
209
|
+
binding: {
|
|
210
|
+
type: "string",
|
|
211
|
+
alias: "b",
|
|
212
|
+
description: "D1 database binding name",
|
|
213
|
+
default: "DB"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
async run({ args }) {
|
|
217
|
+
console.log();
|
|
218
|
+
Wt(import_picocolors.default.bgMagenta(import_picocolors.default.white(" OpacaCMS Migrations ")));
|
|
219
|
+
const s = be();
|
|
220
|
+
const action = args.action || "run";
|
|
221
|
+
let opaca;
|
|
222
|
+
if (action !== "d1") {
|
|
223
|
+
s.start("Loading configuration...");
|
|
224
|
+
try {
|
|
225
|
+
const configPath = resolveConfigPath(args.config);
|
|
226
|
+
opaca = await loadConfig(configPath);
|
|
227
|
+
s.stop(`Configuration loaded. DB: ${import_picocolors.default.cyan(opaca.db.name)}`);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
s.stop(import_picocolors.default.red("Failed to load configuration."));
|
|
230
|
+
R.error(err.message);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
if (action === "create") {
|
|
236
|
+
const name = !args.name || args.name === "migration" ? getRandomMigrationName() : args.name;
|
|
237
|
+
s.start(`Generating baseline migration '${name}'...`);
|
|
238
|
+
const created = await migrateCreateCommand(opaca, name, args.out);
|
|
239
|
+
if (created) {
|
|
240
|
+
s.stop(`Baseline migration created successfully!`);
|
|
241
|
+
} else {
|
|
242
|
+
s.stop(`Operation aborted. No changes detected.`);
|
|
243
|
+
}
|
|
244
|
+
} else if (action === "diff") {
|
|
245
|
+
let name = args.name || "migration";
|
|
246
|
+
if (name === "migration") {
|
|
247
|
+
name = getRandomMigrationName();
|
|
248
|
+
}
|
|
249
|
+
s.start(`Analyzing schema for differences...`);
|
|
250
|
+
let dialect = "sqlite";
|
|
251
|
+
if (opaca.db.name === "postgres")
|
|
252
|
+
dialect = "postgres";
|
|
253
|
+
if (opaca.db.name === "d1")
|
|
254
|
+
dialect = "d1";
|
|
255
|
+
const migrationDir = opaca.db.migrationDir || "./migrations";
|
|
256
|
+
const { hasChanges, upCode, downCode } = await generateDiffCode(opaca, dialect, migrationDir, "diff_check", { saveSnapshot: false, interactive: false });
|
|
257
|
+
if (!hasChanges) {
|
|
258
|
+
s.stop(`Schema is already up to date. No migration generated.`);
|
|
259
|
+
} else {
|
|
260
|
+
s.start(`Generating diff migration '${name}'...`);
|
|
261
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, "").split(".")[0];
|
|
262
|
+
const isD1 = dialect === "d1";
|
|
263
|
+
const fileName = `${timestamp}_${name}.${isD1 ? "sql" : "ts"}`;
|
|
264
|
+
const migrationDir2 = args.out || opaca.db.migrationDir || "./migrations";
|
|
265
|
+
const fullMigrationDir = resolve2(process.cwd(), migrationDir2);
|
|
266
|
+
if (!fs2.existsSync(fullMigrationDir)) {
|
|
267
|
+
fs2.mkdirSync(fullMigrationDir, { recursive: true });
|
|
268
|
+
}
|
|
269
|
+
const filePath = resolve2(fullMigrationDir, fileName);
|
|
270
|
+
let template = "";
|
|
271
|
+
if (isD1) {
|
|
272
|
+
template = `-- OpacaCMS Auto-generated SQL Diff Migration
|
|
273
|
+
|
|
274
|
+
${upCode}`;
|
|
275
|
+
} else {
|
|
276
|
+
template = `import { type OpacaMigrationDb, sql } from 'opacacms/db';
|
|
277
|
+
|
|
278
|
+
export async function up(db: OpacaMigrationDb): Promise<void> {
|
|
279
|
+
${upCode}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export async function down(db: OpacaMigrationDb): Promise<void> {
|
|
283
|
+
${downCode}
|
|
284
|
+
}
|
|
285
|
+
`;
|
|
286
|
+
}
|
|
287
|
+
fs2.writeFileSync(filePath, template);
|
|
288
|
+
s.stop(`Diff migration created successfully at ${relative2(process.cwd(), filePath)}!`);
|
|
289
|
+
}
|
|
290
|
+
} else if (action === "run") {
|
|
291
|
+
s.start(`Applying pending migrations...`);
|
|
292
|
+
await migrateRunCommand(opaca.db);
|
|
293
|
+
s.stop(`Migrations applied successfully!`);
|
|
294
|
+
} else if (action === "status") {
|
|
295
|
+
s.start(`Checking migration status...`);
|
|
296
|
+
await migrateStatusCommand(opaca);
|
|
297
|
+
s.stop(`Migration status checked.`);
|
|
298
|
+
} else if (action === "d1") {
|
|
299
|
+
s.start(`Applying D1 migrations...`);
|
|
300
|
+
await migrateD1Command(args.out || "./migrations", !!args.remote, args.binding);
|
|
301
|
+
s.stop(`D1 migrations processed!`);
|
|
302
|
+
} else {
|
|
303
|
+
R.error(`Unknown migration action: ${action}`);
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
Gt("Done! \uD83D\uDE80");
|
|
307
|
+
} catch (err) {
|
|
308
|
+
if (s)
|
|
309
|
+
s.stop(import_picocolors.default.red("Migration failed."));
|
|
310
|
+
R.error(err.message);
|
|
311
|
+
Gt(import_picocolors.default.red("Operation aborted."));
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
export {
|
|
317
|
+
migrate_default as default
|
|
318
|
+
};
|
|
@@ -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,15 +17,20 @@ import {
|
|
|
14
17
|
} from "./chunk-qxt9vge8.js";
|
|
15
18
|
import {
|
|
16
19
|
logger
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-jq1drsen.js";
|
|
18
21
|
import {
|
|
19
22
|
__require
|
|
20
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6bywt602.js";
|
|
21
24
|
|
|
22
25
|
// src/db/sqlite.ts
|
|
23
26
|
import fs from "node:fs/promises";
|
|
24
27
|
import path from "node:path";
|
|
25
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
CompiledQuery,
|
|
30
|
+
FileMigrationProvider,
|
|
31
|
+
Migrator,
|
|
32
|
+
SqliteDialect
|
|
33
|
+
} from "kysely";
|
|
26
34
|
class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
27
35
|
path;
|
|
28
36
|
name = "sqlite";
|
|
@@ -55,10 +63,16 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
55
63
|
const require2 = createRequire(import.meta.url);
|
|
56
64
|
const Database = require2("better-sqlite3");
|
|
57
65
|
this._rawDb = new Database(this.path);
|
|
58
|
-
|
|
66
|
+
const { createOpacaKysely } = await import("./chunk-sqsfk9p4.js");
|
|
67
|
+
this._db = createOpacaKysely({
|
|
59
68
|
dialect: new SqliteDialect({
|
|
60
69
|
database: this._rawDb
|
|
61
|
-
})
|
|
70
|
+
}),
|
|
71
|
+
config: {
|
|
72
|
+
collections: this._collections,
|
|
73
|
+
globals: this._globals,
|
|
74
|
+
db: { name: "sqlite" }
|
|
75
|
+
}
|
|
62
76
|
});
|
|
63
77
|
}
|
|
64
78
|
async disconnect() {
|
|
@@ -70,44 +84,6 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
70
84
|
const result = await this.db.executeQuery(compiled);
|
|
71
85
|
return result.rows;
|
|
72
86
|
}
|
|
73
|
-
async coerceData(collection, data) {
|
|
74
|
-
const colDef = this._collections.find((c) => c.slug === collection);
|
|
75
|
-
if (!colDef)
|
|
76
|
-
return data;
|
|
77
|
-
const result = { ...data };
|
|
78
|
-
const allFields = flattenFields(colDef.fields);
|
|
79
|
-
for (const field of allFields) {
|
|
80
|
-
const colName = toSnakeCase(field.name);
|
|
81
|
-
if (!(colName in result))
|
|
82
|
-
continue;
|
|
83
|
-
const value = result[colName];
|
|
84
|
-
if (value === undefined || value === null)
|
|
85
|
-
continue;
|
|
86
|
-
switch (field.type) {
|
|
87
|
-
case "boolean":
|
|
88
|
-
result[colName] = value ? 1 : 0;
|
|
89
|
-
break;
|
|
90
|
-
case "number":
|
|
91
|
-
result[colName] = Number(value);
|
|
92
|
-
break;
|
|
93
|
-
case "date":
|
|
94
|
-
if (value instanceof Date) {
|
|
95
|
-
result[colName] = value.toISOString();
|
|
96
|
-
} else if (typeof value === "string") {
|
|
97
|
-
result[colName] = new Date(value).toISOString();
|
|
98
|
-
}
|
|
99
|
-
break;
|
|
100
|
-
case "richtext":
|
|
101
|
-
case "json":
|
|
102
|
-
case "file":
|
|
103
|
-
if (typeof value === "object") {
|
|
104
|
-
result[colName] = JSON.stringify(value);
|
|
105
|
-
}
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
87
|
async count(collection, query) {
|
|
112
88
|
const tableName = toSnakeCase(collection);
|
|
113
89
|
let qb = this.db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
|
|
@@ -137,24 +113,18 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
137
113
|
delete flatData[key];
|
|
138
114
|
}
|
|
139
115
|
}
|
|
140
|
-
if (!flatData.id)
|
|
141
|
-
flatData.id = crypto.randomUUID();
|
|
142
116
|
const dbFields = flattenFields(colDef?.fields || []);
|
|
143
117
|
const validCols = new Set(dbFields.map((f) => toSnakeCase(f.name)));
|
|
144
118
|
validCols.add("id");
|
|
145
119
|
validCols.add(toSnakeCase("createdAt"));
|
|
146
120
|
validCols.add(toSnakeCase("updatedAt"));
|
|
147
|
-
const now = new Date().toISOString();
|
|
148
|
-
flatData[toSnakeCase("createdAt")] = now;
|
|
149
|
-
flatData[toSnakeCase("updatedAt")] = now;
|
|
150
121
|
const filteredData = {};
|
|
151
122
|
for (const col of Object.keys(flatData)) {
|
|
152
123
|
if (validCols.has(col)) {
|
|
153
124
|
filteredData[col] = flatData[col];
|
|
154
125
|
}
|
|
155
126
|
}
|
|
156
|
-
|
|
157
|
-
await tx.insertInto(tableName).values(coercedData).execute();
|
|
127
|
+
await tx.insertInto(tableName).values(filteredData).execute();
|
|
158
128
|
for (const [key, values] of Object.entries(hasManyData)) {
|
|
159
129
|
const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
|
|
160
130
|
if (values.length > 0) {
|
|
@@ -182,13 +152,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
182
152
|
}
|
|
183
153
|
}
|
|
184
154
|
delete blockFlatData.blockType;
|
|
185
|
-
const
|
|
155
|
+
const blockData = {
|
|
186
156
|
...blockFlatData,
|
|
187
157
|
_parent_id: flatData.id,
|
|
188
158
|
_order: i,
|
|
189
159
|
block_type: block.blockType
|
|
190
|
-
}
|
|
191
|
-
await tx.insertInto(blockTableName).values(
|
|
160
|
+
};
|
|
161
|
+
await tx.insertInto(blockTableName).values(blockData).execute();
|
|
192
162
|
}
|
|
193
163
|
}
|
|
194
164
|
return this.findOne(collection, { id: flatData.id }, tx);
|
|
@@ -260,9 +230,17 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
260
230
|
const page = options?.page || 1;
|
|
261
231
|
const limit = options?.limit || 10;
|
|
262
232
|
const offset = (page - 1) * limit;
|
|
233
|
+
const cursorColumn = options?.cursorColumn || "id";
|
|
263
234
|
const total = await this.count(collection, query);
|
|
264
235
|
const tableName = toSnakeCase(collection);
|
|
265
|
-
let qb = this.db.selectFrom(tableName).selectAll().limit(limit)
|
|
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
|
+
}
|
|
266
244
|
if (query && Object.keys(query).length > 0) {
|
|
267
245
|
qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
|
|
268
246
|
}
|
|
@@ -272,11 +250,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
272
250
|
qb = qb.orderBy(col, dir === "desc" ? "desc" : "asc");
|
|
273
251
|
}
|
|
274
252
|
} else {
|
|
275
|
-
qb = qb.orderBy(
|
|
253
|
+
qb = qb.orderBy(cursorColumn, "desc");
|
|
276
254
|
}
|
|
277
255
|
const rows = await qb.execute();
|
|
278
256
|
if (rows.length === 0) {
|
|
279
257
|
const totalPages2 = Math.ceil(total / limit);
|
|
258
|
+
const afterAnchor = options?.after;
|
|
259
|
+
const beforeAnchor = options?.before;
|
|
280
260
|
return {
|
|
281
261
|
docs: [],
|
|
282
262
|
totalDocs: total,
|
|
@@ -284,10 +264,12 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
284
264
|
totalPages: totalPages2,
|
|
285
265
|
page,
|
|
286
266
|
pagingCounter: offset + 1,
|
|
287
|
-
hasNextPage:
|
|
288
|
-
hasPrevPage: page > 1,
|
|
289
|
-
prevPage:
|
|
290
|
-
nextPage:
|
|
267
|
+
hasNextPage: false,
|
|
268
|
+
hasPrevPage: !!afterAnchor || page > 1,
|
|
269
|
+
prevPage: null,
|
|
270
|
+
nextPage: null,
|
|
271
|
+
nextCursor: null,
|
|
272
|
+
prevCursor: afterAnchor ? afterAnchor : null
|
|
291
273
|
};
|
|
292
274
|
}
|
|
293
275
|
const rowIds = rows.map((r) => r.id);
|
|
@@ -365,9 +347,11 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
365
347
|
page,
|
|
366
348
|
pagingCounter: offset + 1,
|
|
367
349
|
hasNextPage: page * limit < total,
|
|
368
|
-
hasPrevPage: page > 1,
|
|
350
|
+
hasPrevPage: page > 1 || !!options?.after || !!options?.before,
|
|
369
351
|
prevPage: page > 1 ? page - 1 : null,
|
|
370
|
-
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
|
|
371
355
|
};
|
|
372
356
|
}
|
|
373
357
|
async update(collection, query, data) {
|
|
@@ -379,6 +363,9 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
379
363
|
const current = await this.findOne(collection, normalizedQuery, tx);
|
|
380
364
|
if (!current)
|
|
381
365
|
throw new Error("Document not found");
|
|
366
|
+
const store = requestContext.getStore();
|
|
367
|
+
if (store)
|
|
368
|
+
store.previousData = current;
|
|
382
369
|
const colDef = this._collections.find((c) => c.slug === collection);
|
|
383
370
|
const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
|
|
384
371
|
const flatData = flattenPayload(data, "", jsonFields);
|
|
@@ -396,16 +383,9 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
396
383
|
delete flatData[key];
|
|
397
384
|
}
|
|
398
385
|
}
|
|
399
|
-
const ts = colDef?.timestamps !== false;
|
|
400
|
-
if (ts) {
|
|
401
|
-
const config = typeof colDef?.timestamps === "object" ? colDef.timestamps : {};
|
|
402
|
-
const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
|
|
403
|
-
flatData[updatedField] = new Date().toISOString();
|
|
404
|
-
}
|
|
405
386
|
const tableName = toSnakeCase(collection);
|
|
406
387
|
if (Object.keys(flatData).length > 0) {
|
|
407
|
-
|
|
408
|
-
await tx.updateTable(tableName).set(coercedData).where("id", "=", current.id).execute();
|
|
388
|
+
await tx.updateTable(tableName).set(flatData).where("id", "=", current.id).execute();
|
|
409
389
|
}
|
|
410
390
|
for (const [key, values] of Object.entries(hasManyData)) {
|
|
411
391
|
const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
|
|
@@ -443,13 +423,13 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
443
423
|
}
|
|
444
424
|
}
|
|
445
425
|
delete blockFlatData.blockType;
|
|
446
|
-
const
|
|
426
|
+
const blockData = {
|
|
447
427
|
...blockFlatData,
|
|
448
428
|
_parent_id: current.id,
|
|
449
429
|
_order: i,
|
|
450
430
|
block_type: block.blockType
|
|
451
|
-
}
|
|
452
|
-
await tx.insertInto(blockTableName).values(
|
|
431
|
+
};
|
|
432
|
+
await tx.insertInto(blockTableName).values(blockData).execute();
|
|
453
433
|
}
|
|
454
434
|
}
|
|
455
435
|
return this.findOne(collection, { id: current.id }, tx);
|
|
@@ -513,8 +493,7 @@ class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
513
493
|
flatData[updatedField] = new Date().toISOString();
|
|
514
494
|
}
|
|
515
495
|
if (Object.keys(flatData).length > 0) {
|
|
516
|
-
const
|
|
517
|
-
const result = await qb.set(coercedData).executeTakeFirst();
|
|
496
|
+
const result = await qb.set(flatData).executeTakeFirst();
|
|
518
497
|
return Number(result.numUpdatedRows || 0);
|
|
519
498
|
}
|
|
520
499
|
return 0;
|