peta-orm 0.2.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +186 -210
  2. package/bin/peta +1 -1
  3. package/dist/collection-PFmrQHyM.mjs +173 -0
  4. package/dist/crud-BCWvg5MI.mjs +101 -0
  5. package/dist/errors-sfFJolfu.mjs +69 -0
  6. package/dist/factory-BBvIMQuc.mjs +173 -0
  7. package/dist/hooks-BD0xy7uw.mjs +77 -0
  8. package/dist/index-BdJnSMYi.d.mts +480 -0
  9. package/dist/index.d.mts +215 -0
  10. package/dist/index.mjs +2604 -0
  11. package/dist/migrations/cli.d.mts +4 -0
  12. package/dist/migrations/cli.mjs +74 -0
  13. package/dist/migrations/index.d.mts +53 -0
  14. package/dist/migrations/index.mjs +2 -0
  15. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  16. package/dist/runner-DQ7uT6LC.mjs +180 -0
  17. package/dist/save-D5UKXvqC.mjs +331 -0
  18. package/dist/state-LtlHp6XV.mjs +56 -0
  19. package/package.json +27 -16
  20. package/dist/builder/delete-builder.d.ts +0 -9
  21. package/dist/builder/delete-builder.d.ts.map +0 -1
  22. package/dist/builder/eager-loader.d.ts +0 -13
  23. package/dist/builder/eager-loader.d.ts.map +0 -1
  24. package/dist/builder/index.d.ts +0 -6
  25. package/dist/builder/index.d.ts.map +0 -1
  26. package/dist/builder/query-builder.d.ts +0 -57
  27. package/dist/builder/query-builder.d.ts.map +0 -1
  28. package/dist/builder/update-builder.d.ts +0 -9
  29. package/dist/builder/update-builder.d.ts.map +0 -1
  30. package/dist/collection/collection.d.ts +0 -48
  31. package/dist/collection/collection.d.ts.map +0 -1
  32. package/dist/collection-wwtv7qmv.js +0 -8
  33. package/dist/columns/arktype-config.d.ts +0 -8
  34. package/dist/columns/arktype-config.d.ts.map +0 -1
  35. package/dist/columns/column-types.d.ts +0 -27
  36. package/dist/columns/column-types.d.ts.map +0 -1
  37. package/dist/columns/column.d.ts +0 -30
  38. package/dist/columns/column.d.ts.map +0 -1
  39. package/dist/columns/schema-config.d.ts +0 -10
  40. package/dist/columns/schema-config.d.ts.map +0 -1
  41. package/dist/errors/errors.d.ts +0 -26
  42. package/dist/errors/errors.d.ts.map +0 -1
  43. package/dist/hooks/lifecycle.d.ts +0 -11
  44. package/dist/hooks/lifecycle.d.ts.map +0 -1
  45. package/dist/index-4xnrys72.js +0 -56
  46. package/dist/index-ddxdqxz6.js +0 -636
  47. package/dist/index-k18nf2r7.js +0 -18
  48. package/dist/index-qb301480.js +0 -2424
  49. package/dist/index-sm1xx8gs.js +0 -7828
  50. package/dist/index.d.ts +0 -24
  51. package/dist/index.d.ts.map +0 -1
  52. package/dist/index.js +0 -9229
  53. package/dist/integrations/elysia.d.ts +0 -12
  54. package/dist/integrations/elysia.d.ts.map +0 -1
  55. package/dist/integrations/hono.d.ts +0 -7
  56. package/dist/integrations/hono.d.ts.map +0 -1
  57. package/dist/migrations/cli.d.ts +0 -2
  58. package/dist/migrations/cli.d.ts.map +0 -1
  59. package/dist/migrations/cli.js +0 -4079
  60. package/dist/migrations/config.d.ts +0 -5
  61. package/dist/migrations/config.d.ts.map +0 -1
  62. package/dist/migrations/generator.d.ts +0 -9
  63. package/dist/migrations/generator.d.ts.map +0 -1
  64. package/dist/migrations/index.d.ts +0 -5
  65. package/dist/migrations/index.d.ts.map +0 -1
  66. package/dist/migrations/index.js +0 -17
  67. package/dist/migrations/runner.d.ts +0 -12
  68. package/dist/migrations/runner.d.ts.map +0 -1
  69. package/dist/migrations/types.d.ts +0 -26
  70. package/dist/migrations/types.d.ts.map +0 -1
  71. package/dist/model/model-delete.d.ts +0 -7
  72. package/dist/model/model-delete.d.ts.map +0 -1
  73. package/dist/model/model-hooks.d.ts +0 -10
  74. package/dist/model/model-hooks.d.ts.map +0 -1
  75. package/dist/model/model-relation.d.ts +0 -7
  76. package/dist/model/model-relation.d.ts.map +0 -1
  77. package/dist/model/model-save.d.ts +0 -6
  78. package/dist/model/model-save.d.ts.map +0 -1
  79. package/dist/model/model-scope.d.ts +0 -6
  80. package/dist/model/model-scope.d.ts.map +0 -1
  81. package/dist/model/model-serialize.d.ts +0 -3
  82. package/dist/model/model-serialize.d.ts.map +0 -1
  83. package/dist/model/model-state.d.ts +0 -27
  84. package/dist/model/model-state.d.ts.map +0 -1
  85. package/dist/model/model.d.ts +0 -88
  86. package/dist/model/model.d.ts.map +0 -1
  87. package/dist/pagination/paginator.d.ts +0 -30
  88. package/dist/pagination/paginator.d.ts.map +0 -1
  89. package/dist/paginator-tmp4hxj5.js +0 -9
  90. package/dist/peta.d.ts +0 -20
  91. package/dist/peta.d.ts.map +0 -1
  92. package/dist/relations/morph.d.ts +0 -44
  93. package/dist/relations/morph.d.ts.map +0 -1
  94. package/dist/relations/relation.d.ts +0 -85
  95. package/dist/relations/relation.d.ts.map +0 -1
  96. package/dist/types.d.ts +0 -18
  97. package/dist/types.d.ts.map +0 -1
@@ -0,0 +1,4 @@
1
+ //#region src/migrations/cli.d.ts
2
+ declare function run(): Promise<void>;
3
+ //#endregion
4
+ export { run };
@@ -0,0 +1,74 @@
1
+ import { a as loadMigrationFiles, i as loadConfig, n as createMigrationGenerator, t as createMigrationRunner } from "../runner-DQ7uT6LC.mjs";
2
+ import { resolve } from "node:path";
3
+ import { mkdirSync, writeFileSync } from "node:fs";
4
+ import cac from "cac";
5
+ import ora from "ora";
6
+ //#region src/migrations/cli.ts
7
+ async function run() {
8
+ const cli = cac("peta");
9
+ cli.command("migrate:init", "Create migrations directory and tracking table").action(async () => {
10
+ const config = await loadConfig();
11
+ const spinner = ora("Setting up migrations...").start();
12
+ mkdirSync(config.migrationsDir, { recursive: true });
13
+ await createMigrationRunner(config.getKysely()).ensureTable();
14
+ spinner.succeed(`Migrations directory created at ${config.migrationsDir}`);
15
+ });
16
+ cli.command("migrate:generate [name]", "Generate initial migration from models").action(async (name) => {
17
+ const config = await loadConfig();
18
+ const spinner = ora("Generating migration...").start();
19
+ const code = createMigrationGenerator().generateInitialMigration(/* @__PURE__ */ new Map(), { name: name ?? "Initial" });
20
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.Z]/g, "").slice(0, 14);
21
+ const safeName = (name ?? "initial").replace(/[^a-zA-Z0-9_]/g, "_");
22
+ const filename = resolve(config.migrationsDir, `${timestamp}_${safeName}.ts`);
23
+ mkdirSync(config.migrationsDir, { recursive: true });
24
+ writeFileSync(filename, code);
25
+ spinner.succeed(`Created ${filename}`);
26
+ });
27
+ cli.command("migrate:up", "Apply pending migrations").action(async () => {
28
+ const config = await loadConfig();
29
+ const migrations = await loadMigrationFiles(config.migrationsDir);
30
+ if (migrations.length === 0) {
31
+ console.log("No migration files found.");
32
+ return;
33
+ }
34
+ const runner = createMigrationRunner(config.getKysely());
35
+ const status = await runner.status(migrations);
36
+ if (status.pending.length === 0) {
37
+ console.log("All migrations have been applied.");
38
+ return;
39
+ }
40
+ const spinner = ora(`Running ${status.pending.length} migration(s)...`).start();
41
+ await runner.up(migrations);
42
+ spinner.succeed(`Applied ${(await runner.getCompleted()).length} migration(s)`);
43
+ });
44
+ cli.command("migrate:down", "Rollback last batch").action(async () => {
45
+ const config = await loadConfig();
46
+ const migrations = await loadMigrationFiles(config.migrationsDir);
47
+ if (migrations.length === 0) {
48
+ console.log("No migration files found.");
49
+ return;
50
+ }
51
+ const runner = createMigrationRunner(config.getKysely());
52
+ if ((await runner.getCompleted()).length === 0) {
53
+ console.log("Nothing to rollback.");
54
+ return;
55
+ }
56
+ const spinner = ora("Rolling back...").start();
57
+ await runner.down(migrations);
58
+ spinner.succeed("Rolled back");
59
+ });
60
+ cli.command("migrate:status", "Show migration status").action(async () => {
61
+ const config = await loadConfig();
62
+ const migrations = await loadMigrationFiles(config.migrationsDir);
63
+ const { completed, pending } = await createMigrationRunner(config.getKysely()).status(migrations);
64
+ console.log(`\n Completed: ${completed.length}`);
65
+ for (const m of completed) console.log(` ✓ ${m.name}`);
66
+ console.log(`\n Pending: ${pending.length}`);
67
+ for (const m of pending) console.log(` · ${m.name}`);
68
+ console.log();
69
+ });
70
+ cli.help();
71
+ cli.parse();
72
+ }
73
+ //#endregion
74
+ export { run };
@@ -0,0 +1,53 @@
1
+ import { a as ModelDefinition } from "../index-BdJnSMYi.mjs";
2
+ import { Kysely } from "kysely";
3
+
4
+ //#region src/migrations/types.d.ts
5
+ interface MigrationFile {
6
+ name: string;
7
+ up: (db: Kysely<unknown>) => Promise<void>;
8
+ down: (db: Kysely<unknown>) => Promise<void>;
9
+ }
10
+ interface MigrationRecord {
11
+ name: string;
12
+ appliedAt: string;
13
+ }
14
+ interface MigrationStatus {
15
+ completed: MigrationRecord[];
16
+ pending: MigrationFile[];
17
+ }
18
+ interface PetaMigrateConfig {
19
+ migrationsDir: string;
20
+ models: string[] | string;
21
+ getKysely: () => Kysely<unknown>;
22
+ }
23
+ interface ResolvedConfig {
24
+ migrationsDir: string;
25
+ models: string[] | string;
26
+ getKysely: () => Kysely<unknown>;
27
+ }
28
+ //#endregion
29
+ //#region src/migrations/config.d.ts
30
+ declare function defineConfig(config: PetaMigrateConfig): PetaMigrateConfig;
31
+ declare function loadConfig(): Promise<ResolvedConfig>;
32
+ declare function loadMigrationFiles(dir: string): Promise<MigrationFile[]>;
33
+ //#endregion
34
+ //#region src/migrations/generator.d.ts
35
+ interface GeneratorOptions {
36
+ name?: string;
37
+ }
38
+ interface MigrationGenerator {
39
+ generateInitialMigration(models: Map<string, ModelDefinition>, options?: GeneratorOptions): string;
40
+ }
41
+ declare function createMigrationGenerator(): MigrationGenerator;
42
+ //#endregion
43
+ //#region src/migrations/runner.d.ts
44
+ interface MigrationRunner {
45
+ ensureTable(): Promise<void>;
46
+ getCompleted(): Promise<MigrationRecord[]>;
47
+ up(migrations: MigrationFile[]): Promise<void>;
48
+ down(migrations: MigrationFile[]): Promise<void>;
49
+ status(migrations: MigrationFile[]): Promise<MigrationStatus>;
50
+ }
51
+ declare function createMigrationRunner(db: Kysely<Record<string, never>>, table?: string): MigrationRunner;
52
+ //#endregion
53
+ export { type GeneratorOptions, type MigrationFile, type MigrationGenerator, type MigrationRecord, type MigrationRunner, type MigrationStatus, type PetaMigrateConfig, type ResolvedConfig, createMigrationGenerator, createMigrationRunner, defineConfig, loadConfig, loadMigrationFiles };
@@ -0,0 +1,2 @@
1
+ import { a as loadMigrationFiles, i as loadConfig, n as createMigrationGenerator, r as defineConfig, t as createMigrationRunner } from "../runner-DQ7uT6LC.mjs";
2
+ export { createMigrationGenerator, createMigrationRunner, defineConfig, loadConfig, loadMigrationFiles };
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -0,0 +1,180 @@
1
+ import { sql } from "kysely";
2
+ import { resolve } from "node:path";
3
+ //#region src/migrations/config.ts
4
+ function defineConfig(config) {
5
+ return config;
6
+ }
7
+ async function loadConfig() {
8
+ const candidates = [
9
+ "peta.config.ts",
10
+ "peta.config.js",
11
+ "peta.config.mjs"
12
+ ];
13
+ let mod = null;
14
+ for (const file of candidates) try {
15
+ mod = await import(resolve(process.cwd(), file));
16
+ break;
17
+ } catch {}
18
+ if (!mod) throw new Error("No peta.config.ts found. Create one in your project root.");
19
+ const config = mod.default ?? mod;
20
+ return {
21
+ migrationsDir: config.migrationsDir,
22
+ models: config.models,
23
+ getKysely: config.getKysely
24
+ };
25
+ }
26
+ async function loadMigrationFiles(dir) {
27
+ const { readdirSync } = await import("node:fs");
28
+ const files = readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
29
+ const migrations = [];
30
+ for (const file of files) {
31
+ const mod = await import(resolve(dir, file));
32
+ if (mod.up) migrations.push({
33
+ name: file.replace(/\.(ts|js)$/, ""),
34
+ up: mod.up,
35
+ down: mod.down ?? (async () => {})
36
+ });
37
+ }
38
+ return migrations;
39
+ }
40
+ //#endregion
41
+ //#region src/migrations/generator.ts
42
+ function createMigrationGenerator() {
43
+ function generateInitialMigration(models, options = {}) {
44
+ options.name;
45
+ const parts = [];
46
+ const indexParts = [];
47
+ const warnings = [];
48
+ const registeredTables = new Set([...models.values()].map((m) => m.table).filter(Boolean));
49
+ for (const [, modelDef] of models) {
50
+ const table = modelDef.table;
51
+ if (!table) continue;
52
+ parts.push(generateCreateTable(table, modelDef.columns));
53
+ for (const [colName, col] of Object.entries(modelDef.columns)) if (col.hasConstraint("index") && !col.isPrimaryKey && !col.isUnique) indexParts.push(generateCreateIndex(table, colName));
54
+ for (const [, rel] of Object.entries(modelDef.relations ?? {})) if (rel.type === "manyToMany") {
55
+ const through = rel.throughTable;
56
+ if (through && !registeredTables.has(through)) warnings.push(`// ⚠ Detected ManyToMany "${modelDef.name}" references table "${through}" but no model is registered for it.\n// Add a model to include the pivot table.`);
57
+ }
58
+ }
59
+ const upBody = [...parts, ...indexParts].join("\n\n");
60
+ const downTables = [...models.values()].filter((m) => m.table).map((m) => ` await db.schema.dropTable("${m.table}").ifExists().execute()`).join("\n");
61
+ return `import type { Kysely } from "kysely"\nimport { sql } from "kysely"\n\nexport async function up(db: Kysely<any>): Promise<void> {\n${warnings.length > 0 ? ` // Warnings:\n${warnings.join("\n")}\n\n` : ""}${upBody}\n}\n\nexport async function down(db: Kysely<any>): Promise<void> {\n${downTables}\n}\n`;
62
+ }
63
+ return { generateInitialMigration };
64
+ }
65
+ function generateCreateTable(table, columns) {
66
+ const lines = [` await db.schema.createTable("${table}").ifNotExists()`];
67
+ for (const [name, col] of Object.entries(columns)) lines.push(` .addColumn("${name}", "${mapType(col)}"${columnCallback(col)})`);
68
+ lines.push(" .execute()");
69
+ return lines.join("\n");
70
+ }
71
+ function generateCreateIndex(table, column) {
72
+ return [
73
+ ` await db.schema.createIndex("${table}_${column}_index")`,
74
+ ` .on("${table}")`,
75
+ ` .column("${column}")`,
76
+ " .execute()"
77
+ ].join("\n");
78
+ }
79
+ function columnCallback(col) {
80
+ const calls = [];
81
+ if (col.isPrimaryKey) {
82
+ if (col.dataType === "integer") calls.push("autoIncrement()");
83
+ calls.push("primaryKey()");
84
+ }
85
+ if (!col.isNullable && !col.isPrimaryKey) calls.push("notNull()");
86
+ const dv = col.defaultValue;
87
+ if (dv !== void 0 && typeof dv !== "function") calls.push(`defaultTo(${JSON.stringify(dv)})`);
88
+ if (col.isUnique && !col.isPrimaryKey) calls.push("unique()");
89
+ const refConstraint = col.constraints.find((c) => c.type === "references");
90
+ if (refConstraint?.args[0]) {
91
+ const targetTable = (typeof refConstraint.args[0] === "function" ? refConstraint.args[0]() : refConstraint.args[0])?.table;
92
+ const targetColumns = refConstraint.args[1];
93
+ if (typeof targetTable === "string" && targetTable && targetColumns?.length) calls.push(`references("${targetTable}.${targetColumns[0]}")`);
94
+ }
95
+ return calls.length === 0 ? "" : `, (c) => c.${calls.join(".")}`;
96
+ }
97
+ function mapType(col) {
98
+ switch (col.dataType) {
99
+ case "integer":
100
+ case "smallint":
101
+ case "bigint":
102
+ case "text":
103
+ case "boolean":
104
+ case "timestamp":
105
+ case "date":
106
+ case "float":
107
+ case "double":
108
+ case "uuid": return col.dataType;
109
+ case "string": {
110
+ const max = col.args[0];
111
+ return max != null ? `varchar(${max})` : "varchar";
112
+ }
113
+ case "json":
114
+ case "jsonb": return "json";
115
+ case "decimal": {
116
+ const p = col.args[0];
117
+ const s = col.args[1];
118
+ return p != null ? `decimal(${p}, ${s ?? 0})` : "decimal";
119
+ }
120
+ case "enum": return "text";
121
+ default: return col.dataType;
122
+ }
123
+ }
124
+ //#endregion
125
+ //#region src/migrations/runner.ts
126
+ function createMigrationRunner(db, table = "_peta_migrations") {
127
+ async function ensureTable() {
128
+ await db.schema.createTable(table).ifNotExists().addColumn("name", "varchar", (c) => c.notNull().primaryKey()).addColumn("applied_at", "timestamp", (c) => c.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
129
+ }
130
+ async function getCompleted() {
131
+ try {
132
+ return (await db.selectFrom(table).select(["name", "applied_at"]).orderBy("name", "asc").execute()).map((r) => ({
133
+ name: String(r.name),
134
+ appliedAt: String(r.applied_at)
135
+ }));
136
+ } catch {
137
+ return [];
138
+ }
139
+ }
140
+ async function up(migrations) {
141
+ await ensureTable();
142
+ const completed = await getCompleted();
143
+ const completedNames = new Set(completed.map((r) => r.name));
144
+ for (const m of migrations.filter((m) => !completedNames.has(m.name)).sort(byName)) {
145
+ await m.up(db);
146
+ await db.insertInto(table).values({
147
+ name: m.name,
148
+ applied_at: (/* @__PURE__ */ new Date()).toISOString()
149
+ }).execute();
150
+ }
151
+ }
152
+ async function down(migrations) {
153
+ const completed = await getCompleted();
154
+ if (completed.length === 0 || migrations.length === 0) return;
155
+ for (const m of migrations.filter((m) => completed.some((r) => r.name === m.name)).sort(byName).reverse()) {
156
+ await m.down(db);
157
+ await db.deleteFrom(table).where("name", "=", m.name).execute();
158
+ }
159
+ }
160
+ async function status(migrations) {
161
+ const completed = await getCompleted();
162
+ const completedNames = new Set(completed.map((r) => r.name));
163
+ return {
164
+ completed,
165
+ pending: migrations.filter((m) => !completedNames.has(m.name)).sort(byName)
166
+ };
167
+ }
168
+ return {
169
+ ensureTable,
170
+ getCompleted,
171
+ up,
172
+ down,
173
+ status
174
+ };
175
+ }
176
+ function byName(a, b) {
177
+ return a.name.localeCompare(b.name);
178
+ }
179
+ //#endregion
180
+ export { loadMigrationFiles as a, loadConfig as i, createMigrationGenerator as n, defineConfig as r, createMigrationRunner as t };
@@ -0,0 +1,331 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { n as normalizeError, r as DatabaseError } from "./errors-sfFJolfu.mjs";
3
+ import { t as getHooksFor } from "./hooks-BD0xy7uw.mjs";
4
+ import { i as applyCastsToData, o as prepareForDb, t as createInstance } from "./factory-BBvIMQuc.mjs";
5
+ import { d as setExists, f as syncOriginal, i as getExists, o as getState } from "./state-LtlHp6XV.mjs";
6
+ //#region src/model/save.ts
7
+ var save_exports = /* @__PURE__ */ __exportAll({
8
+ getConfig: () => getConfig,
9
+ insertManyModel: () => insertManyModel,
10
+ insertModel: () => insertModel,
11
+ reloadModel: () => reloadModel,
12
+ saveModel: () => saveModel,
13
+ setConfig: () => setConfig,
14
+ updateModel: () => updateModel
15
+ });
16
+ function getPrimaryKeyColumn(def) {
17
+ const cols = def.columns;
18
+ for (const [name, col] of Object.entries(cols)) if (col.isPrimaryKey) return name;
19
+ return "id";
20
+ }
21
+ function getTable(def) {
22
+ return def.table;
23
+ }
24
+ function getDb(def) {
25
+ if (!def._orm) throw new Error("Model not registered");
26
+ return def._orm.kysely;
27
+ }
28
+ async function saveModel(def, model) {
29
+ const hm = getHooksFor(def);
30
+ const exists = getExists(model);
31
+ const pk = getPrimaryKeyColumn(def);
32
+ const db = getDb(def);
33
+ const config = getConfig(def);
34
+ if (exists) {
35
+ const dirty = getState(model).attributes;
36
+ const original = getState(model).original;
37
+ const changed = {};
38
+ for (const key of Object.keys(dirty)) if (dirty[key] !== original[key]) changed[key] = config?.casts?.[key] ? prepareForDb(dirty[key], config.casts[key]) : dirty[key];
39
+ if (Object.keys(changed).length === 0) return model;
40
+ await hm.trigger("beforeUpdate", model);
41
+ await hm.trigger("beforeSave", model);
42
+ const pkValue = model.get(pk);
43
+ try {
44
+ await db.updateTable(getTable(def)).set(changed).where(pk, "=", pkValue).execute();
45
+ } catch (e) {
46
+ throw normalizeError(e, getTable(def));
47
+ }
48
+ syncOriginal(model);
49
+ await hm.trigger("afterUpdate", model);
50
+ await hm.trigger("afterSave", model);
51
+ } else {
52
+ await hm.trigger("beforeCreate", model);
53
+ await hm.trigger("beforeSave", model);
54
+ const data = {};
55
+ const attrs = getState(model).attributes;
56
+ for (const [key, value] of Object.entries(attrs)) if (key !== pk || value !== void 0) data[key] = config?.casts?.[key] ? prepareForDb(value, config.casts[key]) : value;
57
+ try {
58
+ const result = await db.insertInto(getTable(def)).values(data).returningAll().executeTakeFirst();
59
+ if (result) {
60
+ const applied = config?.casts ? applyCastsToData(config, result, "get") : result;
61
+ for (const [key, value] of Object.entries(applied)) getState(model).attributes[key] = value;
62
+ }
63
+ } catch (e) {
64
+ throw normalizeError(e, getTable(def));
65
+ }
66
+ setExists(model, true);
67
+ syncOriginal(model);
68
+ await hm.trigger("afterCreate", model);
69
+ await hm.trigger("afterSave", model);
70
+ }
71
+ return model;
72
+ }
73
+ async function insertModel(def, data) {
74
+ const config = getConfig(def) ?? { columns: def.columns };
75
+ if (!Object.keys(data).some((key) => key in def.relations)) {
76
+ const model = createInstance(def, config, data, false);
77
+ await saveModel(def, model);
78
+ return model;
79
+ }
80
+ const { extractRelationData, processCreateRelations } = await import("./crud-BCWvg5MI.mjs");
81
+ const { columnData, relationOps } = extractRelationData(def, data);
82
+ for (const [relName, op] of Object.entries(relationOps)) {
83
+ const relation = def.relations[relName];
84
+ if (relation?.type === "belongsTo") {
85
+ const bop = op;
86
+ const relatedDef = relation.relatedModelClass;
87
+ if (bop.create) {
88
+ const related = await relatedDef.insert(bop.create);
89
+ columnData[relation.foreignKey] = related.get(relation.localKey);
90
+ } else if (bop.connect) {
91
+ const cond = bop.connect;
92
+ const condKey = Object.keys(cond)[0];
93
+ const found = await relatedDef.query().where(condKey, "=", cond[condKey]).executeTakeFirst();
94
+ if (found) columnData[relation.foreignKey] = found.get(relation.localKey);
95
+ } else if (bop.connectOrCreate) {
96
+ const { where, create } = bop.connectOrCreate;
97
+ const whereKey = Object.keys(where)[0];
98
+ const found = await relatedDef.query().where(whereKey, "=", where[whereKey]).executeTakeFirst();
99
+ if (found) columnData[relation.foreignKey] = found.get(relation.localKey);
100
+ else {
101
+ const created = await relatedDef.insert(create);
102
+ columnData[relation.foreignKey] = created.get(relation.localKey);
103
+ }
104
+ }
105
+ }
106
+ }
107
+ const model = createInstance(def, config, columnData, false);
108
+ await saveModel(def, model);
109
+ const postOps = {};
110
+ for (const [relName, op] of Object.entries(relationOps)) {
111
+ const relation = def.relations[relName];
112
+ if (relation && relation.type !== "belongsTo") postOps[relName] = op;
113
+ }
114
+ if (Object.keys(postOps).length > 0) await processCreateRelations(def, model, postOps);
115
+ return model;
116
+ }
117
+ async function insertManyModel(def, dataArray) {
118
+ const db = getDb(def);
119
+ const pk = getPrimaryKeyColumn(def);
120
+ const config = getConfig(def);
121
+ const hm = getHooksFor(def);
122
+ const instances = [];
123
+ for (const data of dataArray) {
124
+ const instance = createInstance(def, config ?? { columns: def.columns }, {}, false);
125
+ const fillData = {};
126
+ for (const [key, value] of Object.entries(data)) if (key !== pk) fillData[key] = value;
127
+ instance.fill(fillData);
128
+ await hm.trigger("beforeCreate", instance);
129
+ instances.push(instance);
130
+ }
131
+ const prepared = instances.map((inst) => {
132
+ const attrs = inst.attributes ?? {};
133
+ const row = {};
134
+ for (const [key, value] of Object.entries(attrs)) row[key] = config?.casts?.[key] ? prepareForDb(value, config.casts[key]) : value;
135
+ return row;
136
+ });
137
+ let results;
138
+ try {
139
+ results = await db.insertInto(getTable(def)).values(prepared).returningAll().execute();
140
+ } catch (e) {
141
+ throw normalizeError(e, getTable(def));
142
+ }
143
+ const models = results.map((row) => {
144
+ const applied = config?.casts ? applyCastsToData(config, row, "get") : row;
145
+ return createInstance(def, config ?? { columns: def.columns }, applied, true);
146
+ });
147
+ for (const model of models) await hm.trigger("afterCreate", model);
148
+ return models;
149
+ }
150
+ async function updateModel(def, id, data) {
151
+ const model = await def.findOrFail(id);
152
+ if (!Object.keys(data).some((key) => key in def.relations)) {
153
+ model.fill(data);
154
+ await saveModel(def, model);
155
+ return model;
156
+ }
157
+ const { extractRelationData } = await import("./crud-BCWvg5MI.mjs");
158
+ const { columnData, relationOps } = extractRelationData(def, data);
159
+ model.fill(columnData);
160
+ await saveModel(def, model);
161
+ const pkValue = model.get("id");
162
+ if (pkValue == null) return model;
163
+ for (const [relName, op] of Object.entries(relationOps)) {
164
+ const relation = def.relations[relName];
165
+ if (!relation) continue;
166
+ const relatedDef = relation.relatedModelClass;
167
+ const db = relatedDef._orm?.kysely;
168
+ if (!db) continue;
169
+ if (relation.type === "belongsTo") {
170
+ const bop = op;
171
+ if (bop.update) {
172
+ const fkValue = model.get(relation.foreignKey);
173
+ if (fkValue != null) {
174
+ const related = await relatedDef.find(fkValue);
175
+ if (related) {
176
+ related.fill(bop.update);
177
+ const { saveModel: saveRel } = await Promise.resolve().then(() => save_exports);
178
+ await saveRel(relatedDef, related);
179
+ }
180
+ }
181
+ } else if (bop.upsert) {
182
+ const { update, create } = bop.upsert;
183
+ const fkValue = model.get(relation.foreignKey);
184
+ if (fkValue != null) {
185
+ const related = await relatedDef.find(fkValue);
186
+ if (related) {
187
+ related.fill(update);
188
+ const { saveModel: saveRel } = await Promise.resolve().then(() => save_exports);
189
+ await saveRel(relatedDef, related);
190
+ }
191
+ } else {
192
+ const created = await relatedDef.insert(create);
193
+ await db.updateTable(def.table).set({ [relation.foreignKey]: created.get(relation.localKey) }).where("id", "=", pkValue).execute();
194
+ model.set(relation.foreignKey, created.get(relation.localKey));
195
+ }
196
+ } else if (bop.disconnect) {
197
+ await db.updateTable(def.table).set({ [relation.foreignKey]: null }).where("id", "=", pkValue).execute();
198
+ model.set(relation.foreignKey, null);
199
+ } else if (bop.delete) {
200
+ const fkValue = model.get(relation.foreignKey);
201
+ if (fkValue != null) {
202
+ const related = await relatedDef.find(fkValue);
203
+ if (related) {
204
+ const { deleteModel: delRel } = await import("./index.mjs").then((n) => n.r);
205
+ await delRel(relatedDef, related);
206
+ }
207
+ }
208
+ }
209
+ } else if (relation.type === "hasMany" || relation.type === "hasOne") {
210
+ const hop = op;
211
+ if (hop.create) for (const childData of hop.create) await relatedDef.insert({
212
+ ...childData,
213
+ [relation.foreignKey]: pkValue
214
+ });
215
+ if (hop.update) {
216
+ const queries = Array.isArray(hop.update?.where) ? hop.update.where : [hop.update?.where];
217
+ for (const where of queries) {
218
+ const whereKey = Object.keys(where)[0];
219
+ await relatedDef.query().where(whereKey, "=", where[whereKey]).all().updateMany(hop.update.data);
220
+ }
221
+ }
222
+ if (hop.delete) {
223
+ const queries = Array.isArray(hop.delete) ? hop.delete : [hop.delete];
224
+ for (const where of queries) {
225
+ const whereKey = Object.keys(where)[0];
226
+ await relatedDef.query().where(whereKey, "=", where[whereKey]).all().deleteMany();
227
+ }
228
+ }
229
+ } else if (relation.type === "manyToMany") {
230
+ const mop = op;
231
+ if (mop.create) {
232
+ const throughTable = relation.throughTable;
233
+ const fpk = relation.foreignPivotKey;
234
+ const rpk = relation.relatedPivotKey;
235
+ for (const childData of mop.create) {
236
+ const child = await relatedDef.insert(childData);
237
+ try {
238
+ await db.insertInto(throughTable).values({
239
+ [fpk]: pkValue,
240
+ [rpk]: child.get(relation.localKey ?? "id")
241
+ }).execute();
242
+ } catch {}
243
+ }
244
+ }
245
+ if (mop.connect) {
246
+ const throughTable = relation.throughTable;
247
+ const fpk = relation.foreignPivotKey;
248
+ const rpk = relation.relatedPivotKey;
249
+ for (const target of mop.connect) {
250
+ let targetId = target;
251
+ if (typeof target !== "number" && typeof target !== "string") {
252
+ const t = target;
253
+ const key = Object.keys(t)[0];
254
+ targetId = (await relatedDef.query().where(key, "=", t[key]).executeTakeFirst())?.get("id");
255
+ }
256
+ if (targetId != null) try {
257
+ await db.insertInto(throughTable).values({
258
+ [fpk]: pkValue,
259
+ [rpk]: targetId
260
+ }).execute();
261
+ } catch {}
262
+ }
263
+ }
264
+ if (mop.disconnect) {
265
+ const throughTable = relation.throughTable;
266
+ const fpk = relation.foreignPivotKey;
267
+ const rpk = relation.relatedPivotKey;
268
+ const queries = Array.isArray(mop.disconnect) ? mop.disconnect : [mop.disconnect];
269
+ for (const where of queries) if (typeof where === "object" && Object.keys(where).length > 0) {
270
+ const key = Object.keys(where)[0];
271
+ const val = Object.values(where)[0];
272
+ if (key === "id") await db.deleteFrom(throughTable).where(fpk, "=", pkValue).where(rpk, "=", val).execute();
273
+ }
274
+ }
275
+ if (mop.set) {
276
+ const throughTable = relation.throughTable;
277
+ const fpk = relation.foreignPivotKey;
278
+ const rpk = relation.relatedPivotKey;
279
+ const current = await db.selectFrom(throughTable).select(rpk).where(fpk, "=", pkValue).execute();
280
+ const currentIds = new Set(current.map((r) => r[rpk]));
281
+ const desiredIds = /* @__PURE__ */ new Set();
282
+ for (const target of mop.set) {
283
+ let targetId = target;
284
+ if (typeof target !== "number" && typeof target !== "string") {
285
+ const t = target;
286
+ const key = Object.keys(t)[0];
287
+ targetId = (await relatedDef.query().where(key, "=", t[key]).executeTakeFirst())?.get("id");
288
+ }
289
+ if (targetId != null) {
290
+ desiredIds.add(targetId);
291
+ if (!currentIds.has(targetId)) try {
292
+ await db.insertInto(throughTable).values({
293
+ [fpk]: pkValue,
294
+ [rpk]: targetId
295
+ }).execute();
296
+ } catch {}
297
+ }
298
+ }
299
+ for (const id of currentIds) if (!desiredIds.has(id)) await db.deleteFrom(throughTable).where(fpk, "=", pkValue).where(rpk, "=", id).execute();
300
+ }
301
+ }
302
+ }
303
+ return model;
304
+ }
305
+ async function reloadModel(def, model) {
306
+ const pk = getPrimaryKeyColumn(def);
307
+ const pkValue = model.get(pk);
308
+ if (pkValue == null) throw new DatabaseError("Cannot reload model without primary key", "MISSING_ID");
309
+ const db = getDb(def);
310
+ try {
311
+ const row = await db.selectFrom(getTable(def)).selectAll().where(pk, "=", pkValue).executeTakeFirst();
312
+ if (row) {
313
+ const config = getConfig(def);
314
+ const applied = config?.casts ? applyCastsToData(config, row, "get") : row;
315
+ const state = getState(model);
316
+ state.attributes = { ...applied };
317
+ state.original = { ...applied };
318
+ }
319
+ } catch (e) {
320
+ throw normalizeError(e, getTable(def));
321
+ }
322
+ }
323
+ const configMap = /* @__PURE__ */ new WeakMap();
324
+ function setConfig(def, config) {
325
+ configMap.set(def, config);
326
+ }
327
+ function getConfig(def) {
328
+ return configMap.get(def);
329
+ }
330
+ //#endregion
331
+ export { setConfig as a, save_exports as i, reloadModel as n, saveModel as r, getConfig as t };