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.
- package/README.md +186 -210
- package/bin/peta +1 -1
- package/dist/collection-PFmrQHyM.mjs +173 -0
- package/dist/crud-BCWvg5MI.mjs +101 -0
- package/dist/errors-sfFJolfu.mjs +69 -0
- package/dist/factory-BBvIMQuc.mjs +173 -0
- package/dist/hooks-BD0xy7uw.mjs +77 -0
- package/dist/index-BdJnSMYi.d.mts +480 -0
- package/dist/index.d.mts +215 -0
- package/dist/index.mjs +2604 -0
- package/dist/migrations/cli.d.mts +4 -0
- package/dist/migrations/cli.mjs +74 -0
- package/dist/migrations/index.d.mts +53 -0
- package/dist/migrations/index.mjs +2 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/runner-DQ7uT6LC.mjs +180 -0
- package/dist/save-D5UKXvqC.mjs +331 -0
- package/dist/state-LtlHp6XV.mjs +56 -0
- package/package.json +27 -16
- package/dist/builder/delete-builder.d.ts +0 -9
- package/dist/builder/delete-builder.d.ts.map +0 -1
- package/dist/builder/eager-loader.d.ts +0 -13
- package/dist/builder/eager-loader.d.ts.map +0 -1
- package/dist/builder/index.d.ts +0 -6
- package/dist/builder/index.d.ts.map +0 -1
- package/dist/builder/query-builder.d.ts +0 -57
- package/dist/builder/query-builder.d.ts.map +0 -1
- package/dist/builder/update-builder.d.ts +0 -9
- package/dist/builder/update-builder.d.ts.map +0 -1
- package/dist/collection/collection.d.ts +0 -48
- package/dist/collection/collection.d.ts.map +0 -1
- package/dist/collection-wwtv7qmv.js +0 -8
- package/dist/columns/arktype-config.d.ts +0 -8
- package/dist/columns/arktype-config.d.ts.map +0 -1
- package/dist/columns/column-types.d.ts +0 -27
- package/dist/columns/column-types.d.ts.map +0 -1
- package/dist/columns/column.d.ts +0 -30
- package/dist/columns/column.d.ts.map +0 -1
- package/dist/columns/schema-config.d.ts +0 -10
- package/dist/columns/schema-config.d.ts.map +0 -1
- package/dist/errors/errors.d.ts +0 -26
- package/dist/errors/errors.d.ts.map +0 -1
- package/dist/hooks/lifecycle.d.ts +0 -11
- package/dist/hooks/lifecycle.d.ts.map +0 -1
- package/dist/index-4xnrys72.js +0 -56
- package/dist/index-ddxdqxz6.js +0 -636
- package/dist/index-k18nf2r7.js +0 -18
- package/dist/index-qb301480.js +0 -2424
- package/dist/index-sm1xx8gs.js +0 -7828
- package/dist/index.d.ts +0 -24
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -9229
- package/dist/integrations/elysia.d.ts +0 -12
- package/dist/integrations/elysia.d.ts.map +0 -1
- package/dist/integrations/hono.d.ts +0 -7
- package/dist/integrations/hono.d.ts.map +0 -1
- package/dist/migrations/cli.d.ts +0 -2
- package/dist/migrations/cli.d.ts.map +0 -1
- package/dist/migrations/cli.js +0 -4079
- package/dist/migrations/config.d.ts +0 -5
- package/dist/migrations/config.d.ts.map +0 -1
- package/dist/migrations/generator.d.ts +0 -9
- package/dist/migrations/generator.d.ts.map +0 -1
- package/dist/migrations/index.d.ts +0 -5
- package/dist/migrations/index.d.ts.map +0 -1
- package/dist/migrations/index.js +0 -17
- package/dist/migrations/runner.d.ts +0 -12
- package/dist/migrations/runner.d.ts.map +0 -1
- package/dist/migrations/types.d.ts +0 -26
- package/dist/migrations/types.d.ts.map +0 -1
- package/dist/model/model-delete.d.ts +0 -7
- package/dist/model/model-delete.d.ts.map +0 -1
- package/dist/model/model-hooks.d.ts +0 -10
- package/dist/model/model-hooks.d.ts.map +0 -1
- package/dist/model/model-relation.d.ts +0 -7
- package/dist/model/model-relation.d.ts.map +0 -1
- package/dist/model/model-save.d.ts +0 -6
- package/dist/model/model-save.d.ts.map +0 -1
- package/dist/model/model-scope.d.ts +0 -6
- package/dist/model/model-scope.d.ts.map +0 -1
- package/dist/model/model-serialize.d.ts +0 -3
- package/dist/model/model-serialize.d.ts.map +0 -1
- package/dist/model/model-state.d.ts +0 -27
- package/dist/model/model-state.d.ts.map +0 -1
- package/dist/model/model.d.ts +0 -88
- package/dist/model/model.d.ts.map +0 -1
- package/dist/pagination/paginator.d.ts +0 -30
- package/dist/pagination/paginator.d.ts.map +0 -1
- package/dist/paginator-tmp4hxj5.js +0 -9
- package/dist/peta.d.ts +0 -20
- package/dist/peta.d.ts.map +0 -1
- package/dist/relations/morph.d.ts +0 -44
- package/dist/relations/morph.d.ts.map +0 -1
- package/dist/relations/relation.d.ts +0 -85
- package/dist/relations/relation.d.ts.map +0 -1
- package/dist/types.d.ts +0 -18
- package/dist/types.d.ts.map +0 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
//#region src/collection/index.ts
|
|
3
|
+
var collection_exports = /* @__PURE__ */ __exportAll({ createCollection: () => createCollection });
|
|
4
|
+
function createCollection(items) {
|
|
5
|
+
const data = [...items ?? []];
|
|
6
|
+
const collection = {
|
|
7
|
+
get length() {
|
|
8
|
+
return data.length;
|
|
9
|
+
},
|
|
10
|
+
[Symbol.iterator]() {
|
|
11
|
+
return data[Symbol.iterator]();
|
|
12
|
+
},
|
|
13
|
+
at(index) {
|
|
14
|
+
return data[index];
|
|
15
|
+
},
|
|
16
|
+
first() {
|
|
17
|
+
return data[0];
|
|
18
|
+
},
|
|
19
|
+
last() {
|
|
20
|
+
return data[data.length - 1];
|
|
21
|
+
},
|
|
22
|
+
all() {
|
|
23
|
+
return [...data];
|
|
24
|
+
},
|
|
25
|
+
findBy(id) {
|
|
26
|
+
return data.find((d) => d.get("id") === id);
|
|
27
|
+
},
|
|
28
|
+
find(callback) {
|
|
29
|
+
return data.find(callback);
|
|
30
|
+
},
|
|
31
|
+
some(callback) {
|
|
32
|
+
return data.some(callback);
|
|
33
|
+
},
|
|
34
|
+
includes(item) {
|
|
35
|
+
return data.includes(item);
|
|
36
|
+
},
|
|
37
|
+
isEmpty() {
|
|
38
|
+
return data.length === 0;
|
|
39
|
+
},
|
|
40
|
+
isNotEmpty() {
|
|
41
|
+
return data.length > 0;
|
|
42
|
+
},
|
|
43
|
+
get(key) {
|
|
44
|
+
return data.map((d) => d.get(key));
|
|
45
|
+
},
|
|
46
|
+
pluck(key) {
|
|
47
|
+
return data.map((d) => d.get(key));
|
|
48
|
+
},
|
|
49
|
+
groupBy(key) {
|
|
50
|
+
const result = {};
|
|
51
|
+
for (const item of data) {
|
|
52
|
+
const v = String(item.get(key));
|
|
53
|
+
if (!result[v]) result[v] = [];
|
|
54
|
+
result[v].push(item);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
},
|
|
58
|
+
keyBy(key) {
|
|
59
|
+
const result = {};
|
|
60
|
+
for (const item of data) result[String(item.get(key))] = item;
|
|
61
|
+
return result;
|
|
62
|
+
},
|
|
63
|
+
map(fn) {
|
|
64
|
+
return data.map(fn);
|
|
65
|
+
},
|
|
66
|
+
filter(fn) {
|
|
67
|
+
return createCollection(data.filter(fn));
|
|
68
|
+
},
|
|
69
|
+
reduce(fn, initial) {
|
|
70
|
+
return data.reduce(fn, initial);
|
|
71
|
+
},
|
|
72
|
+
forEach(fn) {
|
|
73
|
+
data.forEach(fn);
|
|
74
|
+
},
|
|
75
|
+
each(fn) {
|
|
76
|
+
data.forEach(fn);
|
|
77
|
+
return collection;
|
|
78
|
+
},
|
|
79
|
+
unique(key) {
|
|
80
|
+
if (!key) {
|
|
81
|
+
const seen = /* @__PURE__ */ new Set();
|
|
82
|
+
return createCollection(data.filter((d) => {
|
|
83
|
+
const id = d.get("id");
|
|
84
|
+
if (seen.has(id)) return false;
|
|
85
|
+
seen.add(id);
|
|
86
|
+
return true;
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
const seen = /* @__PURE__ */ new Set();
|
|
90
|
+
return createCollection(data.filter((d) => {
|
|
91
|
+
const v = d.get(key);
|
|
92
|
+
if (seen.has(v)) return false;
|
|
93
|
+
seen.add(v);
|
|
94
|
+
return true;
|
|
95
|
+
}));
|
|
96
|
+
},
|
|
97
|
+
sortBy(key, direction = "asc") {
|
|
98
|
+
return createCollection([...data].sort((a, b) => {
|
|
99
|
+
const va = a.get(key);
|
|
100
|
+
const vb = b.get(key);
|
|
101
|
+
if (va < vb) return direction === "asc" ? -1 : 1;
|
|
102
|
+
if (va > vb) return direction === "asc" ? 1 : -1;
|
|
103
|
+
return 0;
|
|
104
|
+
}));
|
|
105
|
+
},
|
|
106
|
+
shuffle() {
|
|
107
|
+
const shuffled = [...data];
|
|
108
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
109
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
110
|
+
const temp = shuffled[i];
|
|
111
|
+
shuffled[i] = shuffled[j];
|
|
112
|
+
shuffled[j] = temp;
|
|
113
|
+
}
|
|
114
|
+
return createCollection(shuffled);
|
|
115
|
+
},
|
|
116
|
+
take(n) {
|
|
117
|
+
return createCollection(data.slice(0, n));
|
|
118
|
+
},
|
|
119
|
+
skip(n) {
|
|
120
|
+
return createCollection(data.slice(n));
|
|
121
|
+
},
|
|
122
|
+
chunk(size) {
|
|
123
|
+
const chunks = [];
|
|
124
|
+
for (let i = 0; i < data.length; i += size) chunks.push(createCollection(data.slice(i, i + size)));
|
|
125
|
+
return chunks;
|
|
126
|
+
},
|
|
127
|
+
sum(key) {
|
|
128
|
+
return data.reduce((acc, d) => acc + (Number(d.get(key)) || 0), 0);
|
|
129
|
+
},
|
|
130
|
+
avg(key) {
|
|
131
|
+
return data.length === 0 ? 0 : this.sum(key) / data.length;
|
|
132
|
+
},
|
|
133
|
+
min(key) {
|
|
134
|
+
return Math.min(...data.map((d) => Number(d.get(key)) || 0));
|
|
135
|
+
},
|
|
136
|
+
max(key) {
|
|
137
|
+
return Math.max(...data.map((d) => Number(d.get(key)) || 0));
|
|
138
|
+
},
|
|
139
|
+
diff(other) {
|
|
140
|
+
const otherIds = new Set(other.pluck("id"));
|
|
141
|
+
return createCollection(data.filter((d) => !otherIds.has(d.get("id"))));
|
|
142
|
+
},
|
|
143
|
+
intersect(other) {
|
|
144
|
+
const otherIds = new Set(other.pluck("id"));
|
|
145
|
+
return createCollection(data.filter((d) => otherIds.has(d.get("id"))));
|
|
146
|
+
},
|
|
147
|
+
concat(other) {
|
|
148
|
+
return createCollection([...data, ...other.all()]);
|
|
149
|
+
},
|
|
150
|
+
push(...items) {
|
|
151
|
+
data.push(...items);
|
|
152
|
+
},
|
|
153
|
+
async load(...relations) {
|
|
154
|
+
if (data.length === 0) return collection;
|
|
155
|
+
const { EagerLoader } = await import("./index.mjs").then((n) => n.i);
|
|
156
|
+
const { getModelDefFromInstance } = await import("./factory-BBvIMQuc.mjs").then((n) => n.n);
|
|
157
|
+
const { getModelDef } = await import("./index.mjs").then((n) => n.n);
|
|
158
|
+
const first = data[0];
|
|
159
|
+
const def = getModelDefFromInstance(first) ?? getModelDef(first);
|
|
160
|
+
if (def) {
|
|
161
|
+
const loader = new EagerLoader();
|
|
162
|
+
for (const rel of relations) await loader.loadRelated(data, { name: rel }, def);
|
|
163
|
+
}
|
|
164
|
+
return collection;
|
|
165
|
+
},
|
|
166
|
+
toJSON() {
|
|
167
|
+
return data.map((d) => d.toJSON());
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
return collection;
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
export { createCollection as n, collection_exports as t };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { r as DatabaseError, s as RelationNotFoundError } from "./errors-sfFJolfu.mjs";
|
|
2
|
+
//#region src/relations/crud.ts
|
|
3
|
+
function extractRelationData(def, data) {
|
|
4
|
+
const columnData = {};
|
|
5
|
+
const relationOps = {};
|
|
6
|
+
for (const [key, value] of Object.entries(data)) if (def.relations[key] && typeof value === "object" && value !== null && !Array.isArray(value)) relationOps[key] = value;
|
|
7
|
+
else if (def.relations[key] && Array.isArray(value)) relationOps[key] = { connect: value };
|
|
8
|
+
else if (def.relations[key] && typeof value === "object" && value !== null && "create" in value) relationOps[key] = value;
|
|
9
|
+
else columnData[key] = value;
|
|
10
|
+
return {
|
|
11
|
+
columnData,
|
|
12
|
+
relationOps
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function getDb(def) {
|
|
16
|
+
if (!def._orm) throw new Error("Model not registered");
|
|
17
|
+
return def._orm.kysely;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Process relation operations after the parent model has been created.
|
|
21
|
+
* For belongsTo, the related model must be created FIRST, then its ID
|
|
22
|
+
* is set on the parent. For hasMany/hasOne/manyToMany, the parent
|
|
23
|
+
* is created first, then children are created with the parent's FK.
|
|
24
|
+
*
|
|
25
|
+
* This function handles the post-creation phase.
|
|
26
|
+
*/
|
|
27
|
+
async function processCreateRelations(def, instance, relationOps) {
|
|
28
|
+
for (const [relName, op] of Object.entries(relationOps)) {
|
|
29
|
+
const relation = def.relations[relName];
|
|
30
|
+
if (!relation) throw new RelationNotFoundError(def.name, relName);
|
|
31
|
+
relation.relatedModelClass;
|
|
32
|
+
const pkValue = instance.get(relation.localKey);
|
|
33
|
+
if (pkValue == null) throw new DatabaseError("Cannot create relations without primary key", "MISSING_ID");
|
|
34
|
+
if (relation.type === "belongsTo") await processBelongsToCreate(instance, relation, op, pkValue);
|
|
35
|
+
else if (relation.type === "hasOne") await processHasManyCreate(instance, relation, op, pkValue);
|
|
36
|
+
else if (relation.type === "hasMany") await processHasManyCreate(instance, relation, op, pkValue);
|
|
37
|
+
else if (relation.type === "manyToMany") await processManyToManyCreate(instance, relation, op, pkValue);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function processBelongsToCreate(instance, relation, op, _pkValue) {
|
|
41
|
+
const relatedDef = relation.relatedModelClass;
|
|
42
|
+
let relatedId = instance.get(relation.foreignKey);
|
|
43
|
+
if (op.create) relatedId = (await relatedDef.insert(op.create)).get(relation.localKey);
|
|
44
|
+
else if (op.connect) {
|
|
45
|
+
const related = await findRelated(relatedDef, op.connect);
|
|
46
|
+
if (related) relatedId = related.get(relation.localKey);
|
|
47
|
+
} else if (op.connectOrCreate) {
|
|
48
|
+
const existing = await findRelated(relatedDef, op.connectOrCreate.where);
|
|
49
|
+
if (existing) relatedId = existing.get(relation.localKey);
|
|
50
|
+
else relatedId = (await relatedDef.insert(op.connectOrCreate.create)).get(relation.localKey);
|
|
51
|
+
}
|
|
52
|
+
if (relatedId !== void 0) await getDb(relatedDef).updateTable(relatedDef.table).set({ [relation.foreignKey]: relatedId }).where(relation.localKey, "=", _pkValue).execute();
|
|
53
|
+
}
|
|
54
|
+
async function processHasManyCreate(_instance, relation, op, pkValue) {
|
|
55
|
+
const relatedDef = relation.relatedModelClass;
|
|
56
|
+
const fk = relation.foreignKey;
|
|
57
|
+
if (op.create) for (const data of op.create) await relatedDef.insert({
|
|
58
|
+
...data,
|
|
59
|
+
[fk]: pkValue
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function processManyToManyCreate(_instance, relation, op, pkValue) {
|
|
63
|
+
const relatedDef = relation.relatedModelClass;
|
|
64
|
+
const { throughTable, foreignPivotKey, relatedPivotKey } = getPivotInfo(relation);
|
|
65
|
+
const db = getDb(relatedDef);
|
|
66
|
+
if (op.create) for (const data of op.create) {
|
|
67
|
+
const relatedId = (await relatedDef.insert(data)).get(relation.localKey ?? "id");
|
|
68
|
+
await db.insertInto(throughTable).values({
|
|
69
|
+
[foreignPivotKey]: pkValue,
|
|
70
|
+
[relatedPivotKey]: relatedId
|
|
71
|
+
}).execute();
|
|
72
|
+
}
|
|
73
|
+
if (op.connect) for (const target of op.connect) {
|
|
74
|
+
const relatedId = await resolveTargetId(relatedDef, target);
|
|
75
|
+
if (relatedId != null) try {
|
|
76
|
+
await db.insertInto(throughTable).values({
|
|
77
|
+
[foreignPivotKey]: pkValue,
|
|
78
|
+
[relatedPivotKey]: relatedId
|
|
79
|
+
}).execute();
|
|
80
|
+
} catch {}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getPivotInfo(relation) {
|
|
84
|
+
if (relation.type !== "manyToMany" || !relation.throughTable) throw new Error("Not a many-to-many relation");
|
|
85
|
+
return {
|
|
86
|
+
throughTable: relation.throughTable,
|
|
87
|
+
foreignPivotKey: relation.foreignPivotKey ?? "",
|
|
88
|
+
relatedPivotKey: relation.relatedPivotKey ?? ""
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function findRelated(def, conditions) {
|
|
92
|
+
const key = Object.keys(conditions)[0];
|
|
93
|
+
return def.query().where(key, "=", conditions[key]).executeTakeFirst();
|
|
94
|
+
}
|
|
95
|
+
async function resolveTargetId(def, target) {
|
|
96
|
+
if (typeof target === "number" || typeof target === "string") return target;
|
|
97
|
+
const found = await findRelated(def, target);
|
|
98
|
+
if (found) return found.get("id");
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { extractRelationData, processCreateRelations };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
//#region src/errors/classes.ts
|
|
3
|
+
var ValidationError = class extends Error {
|
|
4
|
+
name = "ValidationError";
|
|
5
|
+
};
|
|
6
|
+
var ModelNotFoundError = class extends Error {
|
|
7
|
+
name = "ModelNotFoundError";
|
|
8
|
+
constructor(model, id) {
|
|
9
|
+
super(`${model} with id ${id} not found`);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var RelationNotFoundError = class extends Error {
|
|
13
|
+
name = "RelationNotFoundError";
|
|
14
|
+
constructor(model, relation) {
|
|
15
|
+
super(`Relation "${relation}" not found on ${model}`);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var RelationNotAllowedError = class extends Error {
|
|
19
|
+
name = "RelationNotAllowedError";
|
|
20
|
+
constructor(model, relation) {
|
|
21
|
+
super(`Relation "${relation}" is not in the allowGraph whitelist for ${model}`);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var ModelNotRegisteredError = class extends Error {
|
|
25
|
+
name = "ModelNotRegisteredError";
|
|
26
|
+
constructor(model) {
|
|
27
|
+
super(`Model "${model}" is not registered. Call orm.register() or pass it to createORM()`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var DatabaseError = class extends Error {
|
|
31
|
+
name = "DatabaseError";
|
|
32
|
+
code;
|
|
33
|
+
table;
|
|
34
|
+
detail;
|
|
35
|
+
constructor(message, code, table, detail) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.code = code;
|
|
38
|
+
this.table = table;
|
|
39
|
+
this.detail = detail;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/errors/normalizer.ts
|
|
44
|
+
function normalizeError(e, table) {
|
|
45
|
+
const raw = e;
|
|
46
|
+
const msg = raw.message ?? "";
|
|
47
|
+
if (raw.code === "SQLITE_CONSTRAINT_UNIQUE" || raw.code === "SQLITE_CONSTRAINT") return new DatabaseError(`Unique constraint violation on ${table}: ${msg}`, "UNIQUE_CONSTRAINT", table, msg);
|
|
48
|
+
if (raw.code === "SQLITE_CONSTRAINT_FOREIGNKEY" || raw.code === "SQLITE_CONSTRAINT_FOREIGN_KEY") return new DatabaseError(`Foreign key constraint violation on ${table}: ${msg}`, "FOREIGN_KEY_CONSTRAINT", table, msg);
|
|
49
|
+
if (raw.code === "SQLITE_CONSTRAINT_NOTNULL" || raw.code === "SQLITE_CONSTRAINT_NOT_NULL") return new DatabaseError(`Not null constraint violation on ${table}: ${msg}`, "NOT_NULL_CONSTRAINT", table, msg);
|
|
50
|
+
if (raw.code === "SQLITE_CONSTRAINT_CHECK") return new DatabaseError(`Check constraint violation on ${table}: ${msg}`, "CHECK_CONSTRAINT", table, msg);
|
|
51
|
+
if (raw.errno === 19 || raw.errno === 2067) {
|
|
52
|
+
if (msg.includes("UNIQUE")) return new DatabaseError(msg, "UNIQUE_CONSTRAINT", table, msg);
|
|
53
|
+
if (msg.includes("FOREIGN KEY")) return new DatabaseError(msg, "FOREIGN_KEY_CONSTRAINT", table, msg);
|
|
54
|
+
if (msg.includes("NOT NULL")) return new DatabaseError(msg, "NOT_NULL_CONSTRAINT", table, msg);
|
|
55
|
+
if (msg.includes("CHECK")) return new DatabaseError(msg, "CHECK_CONSTRAINT", table, msg);
|
|
56
|
+
}
|
|
57
|
+
if (raw.code === "23505") return new DatabaseError(msg, "UNIQUE_CONSTRAINT", table, msg);
|
|
58
|
+
if (raw.code === "23503") return new DatabaseError(msg, "FOREIGN_KEY_CONSTRAINT", table, msg);
|
|
59
|
+
if (raw.code === "23502") return new DatabaseError(msg, "NOT_NULL_CONSTRAINT", table, msg);
|
|
60
|
+
if (raw.code === "ER_DUP_ENTRY" || raw.errno === 1062) return new DatabaseError(`Unique constraint violation on ${table}: ${msg}`, "UNIQUE_CONSTRAINT", table, msg);
|
|
61
|
+
if (raw.code === "ER_NO_REFERENCED_ROW_2" || raw.errno === 1452) return new DatabaseError(`Foreign key constraint violation on ${table}: ${msg}`, "FOREIGN_KEY_CONSTRAINT", table, msg);
|
|
62
|
+
if (raw.code === "ER_BAD_NULL_ERROR" || raw.errno === 1048) return new DatabaseError(`Not null constraint violation on ${table}: ${msg}`, "NOT_NULL_CONSTRAINT", table, msg);
|
|
63
|
+
return new DatabaseError(msg || "Unknown database error", "UNKNOWN", table, msg);
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/errors.ts
|
|
67
|
+
var errors_exports = /* @__PURE__ */ __exportAll({ normalizeError: () => normalizeError });
|
|
68
|
+
//#endregion
|
|
69
|
+
export { ModelNotRegisteredError as a, ValidationError as c, ModelNotFoundError as i, normalizeError as n, RelationNotAllowedError as o, DatabaseError as r, RelationNotFoundError as s, errors_exports as t };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { a as getRawRelations, c as isDirty, f as syncOriginal, i as getExists, l as resetAttrs, n as getAttr, o as getState, r as getDirtyAttributes, s as initState, t as fillAttrs, u as setAttr } from "./state-LtlHp6XV.mjs";
|
|
3
|
+
//#region src/model/casts.ts
|
|
4
|
+
function castValue(value, type) {
|
|
5
|
+
if (value == null) return value;
|
|
6
|
+
switch (type) {
|
|
7
|
+
case "json":
|
|
8
|
+
case "object": return typeof value === "string" ? JSON.parse(value) : value;
|
|
9
|
+
case "boolean":
|
|
10
|
+
case "bool": return Boolean(value);
|
|
11
|
+
case "integer":
|
|
12
|
+
case "int": return Number(value);
|
|
13
|
+
case "float":
|
|
14
|
+
case "double": return Number(value);
|
|
15
|
+
case "date":
|
|
16
|
+
case "datetime": return typeof value === "string" ? value : value.toISOString();
|
|
17
|
+
default: return value;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function prepareForDb(value, type) {
|
|
21
|
+
if (value == null) return value;
|
|
22
|
+
switch (type) {
|
|
23
|
+
case "json":
|
|
24
|
+
case "object": return typeof value === "string" ? value : JSON.stringify(value);
|
|
25
|
+
case "boolean":
|
|
26
|
+
case "bool": return value ? 1 : 0;
|
|
27
|
+
default: return value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function castForSet(value, type) {
|
|
31
|
+
if (value == null) return value;
|
|
32
|
+
switch (type) {
|
|
33
|
+
case "json":
|
|
34
|
+
case "object": return typeof value === "string" ? JSON.parse(value) : value;
|
|
35
|
+
case "boolean":
|
|
36
|
+
case "bool": return Boolean(value);
|
|
37
|
+
case "integer":
|
|
38
|
+
case "int": return Number(value);
|
|
39
|
+
default: return value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function applyCastsToData(config, data, mode) {
|
|
43
|
+
if (!config.casts) return { ...data };
|
|
44
|
+
const result = { ...data };
|
|
45
|
+
for (const [key, type] of Object.entries(config.casts)) if (key in result) result[key] = mode === "get" ? castValue(result[key], type) : prepareForDb(result[key], type);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/model/runtime.ts
|
|
50
|
+
let runtime = null;
|
|
51
|
+
function initRuntime(fns) {
|
|
52
|
+
runtime = fns;
|
|
53
|
+
}
|
|
54
|
+
function getRuntime() {
|
|
55
|
+
if (!runtime) throw new Error("Model runtime not initialized. Call initRuntime() first.");
|
|
56
|
+
return runtime;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/model/types.ts
|
|
60
|
+
const FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
61
|
+
"__proto__",
|
|
62
|
+
"constructor",
|
|
63
|
+
"prototype"
|
|
64
|
+
]);
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/model/factory.ts
|
|
67
|
+
var factory_exports = /* @__PURE__ */ __exportAll({
|
|
68
|
+
createInstance: () => createInstance,
|
|
69
|
+
getModelDefFromInstance: () => getModelDefFromInstance,
|
|
70
|
+
setModelDefOnInstance: () => setModelDefOnInstance
|
|
71
|
+
});
|
|
72
|
+
const instanceDefs = /* @__PURE__ */ new WeakMap();
|
|
73
|
+
function setModelDefOnInstance(instance, def) {
|
|
74
|
+
instanceDefs.set(instance, def);
|
|
75
|
+
}
|
|
76
|
+
function getModelDefFromInstance(instance) {
|
|
77
|
+
return instanceDefs.get(instance);
|
|
78
|
+
}
|
|
79
|
+
function createInstance(def, config, data, exists) {
|
|
80
|
+
const instance = {
|
|
81
|
+
get exists() {
|
|
82
|
+
return getExists(instance);
|
|
83
|
+
},
|
|
84
|
+
get attributes() {
|
|
85
|
+
return { ...getState(instance).attributes };
|
|
86
|
+
},
|
|
87
|
+
get dirtyAttributes() {
|
|
88
|
+
return getDirtyAttributes(instance);
|
|
89
|
+
},
|
|
90
|
+
isDirty(key) {
|
|
91
|
+
return isDirty(instance, key);
|
|
92
|
+
},
|
|
93
|
+
get(key) {
|
|
94
|
+
let result = getAttr(instance, key);
|
|
95
|
+
if (config.casts?.[key]) result = castValue(result, config.casts[key]);
|
|
96
|
+
const attrDef = config.attributes?.[key];
|
|
97
|
+
if (attrDef?.get) result = attrDef.get(result, instance);
|
|
98
|
+
return result;
|
|
99
|
+
},
|
|
100
|
+
set(key, value) {
|
|
101
|
+
if (FORBIDDEN_KEYS.has(key)) return;
|
|
102
|
+
let result = value;
|
|
103
|
+
const attrDef = config.attributes?.[key];
|
|
104
|
+
if (attrDef?.set) result = attrDef.set(result, instance);
|
|
105
|
+
setAttr(instance, key, config.casts?.[key] ? castForSet(result, config.casts[key]) : result);
|
|
106
|
+
},
|
|
107
|
+
fill(data) {
|
|
108
|
+
const safe = {};
|
|
109
|
+
for (const [key, value] of Object.entries(data)) if (!FORBIDDEN_KEYS.has(key)) {
|
|
110
|
+
let v = value;
|
|
111
|
+
const attrDef = config.attributes?.[key];
|
|
112
|
+
if (attrDef?.set) v = attrDef.set(v, instance);
|
|
113
|
+
safe[key] = config.casts?.[key] ? castForSet(v, config.casts[key]) : v;
|
|
114
|
+
}
|
|
115
|
+
fillAttrs(instance, safe);
|
|
116
|
+
},
|
|
117
|
+
reset() {
|
|
118
|
+
resetAttrs(instance);
|
|
119
|
+
},
|
|
120
|
+
$getRelation(name) {
|
|
121
|
+
return getRawRelations(instance)?.[name] ?? null;
|
|
122
|
+
},
|
|
123
|
+
$setRelation(name, value) {
|
|
124
|
+
getRawRelations(instance)[name] = value;
|
|
125
|
+
},
|
|
126
|
+
$hasRelation(name) {
|
|
127
|
+
return name in (getRawRelations(instance) ?? {});
|
|
128
|
+
},
|
|
129
|
+
$relationData() {
|
|
130
|
+
return { ...getRawRelations(instance) };
|
|
131
|
+
},
|
|
132
|
+
$load: (...relations) => {
|
|
133
|
+
return getRuntime().loadModelRelations(instance, def, ...relations);
|
|
134
|
+
},
|
|
135
|
+
$related: (name) => {
|
|
136
|
+
return getRuntime().createRelationQuery(instance, def, name);
|
|
137
|
+
},
|
|
138
|
+
$save: () => {
|
|
139
|
+
return getRuntime().saveModel(def, instance);
|
|
140
|
+
},
|
|
141
|
+
$delete: () => {
|
|
142
|
+
return getRuntime().deleteModel(def, instance);
|
|
143
|
+
},
|
|
144
|
+
$forceDelete: () => {
|
|
145
|
+
return getRuntime().forceDeleteModel(def, instance);
|
|
146
|
+
},
|
|
147
|
+
$restore: () => {
|
|
148
|
+
return getRuntime().restoreModel(def, instance);
|
|
149
|
+
},
|
|
150
|
+
$trashed() {
|
|
151
|
+
return getRuntime().trashedModel(def, instance);
|
|
152
|
+
},
|
|
153
|
+
$reload: () => {
|
|
154
|
+
return getRuntime().reloadModel(def, instance);
|
|
155
|
+
},
|
|
156
|
+
$toJSON() {
|
|
157
|
+
return getRuntime().modelToJSON(def, instance);
|
|
158
|
+
},
|
|
159
|
+
toJSON() {
|
|
160
|
+
return getRuntime().modelToJSON(def, instance);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
if (exists) initState(instance, applyCastsToData(config, data || {}, "get"), true);
|
|
164
|
+
else {
|
|
165
|
+
initState(instance, {}, false);
|
|
166
|
+
if (data && Object.keys(data).length > 0) instance.fill(data);
|
|
167
|
+
syncOriginal(instance);
|
|
168
|
+
}
|
|
169
|
+
setModelDefOnInstance(instance, def);
|
|
170
|
+
return instance;
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
export { castValue as a, applyCastsToData as i, factory_exports as n, prepareForDb as o, initRuntime as r, createInstance as t };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
//#region src/hooks/index.ts
|
|
3
|
+
function createHookManager() {
|
|
4
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
5
|
+
function on(event, callback) {
|
|
6
|
+
let cbs = listeners.get(event);
|
|
7
|
+
if (!cbs) {
|
|
8
|
+
cbs = [];
|
|
9
|
+
listeners.set(event, cbs);
|
|
10
|
+
}
|
|
11
|
+
cbs.push(callback);
|
|
12
|
+
return () => off(event, callback);
|
|
13
|
+
}
|
|
14
|
+
function off(event, callback) {
|
|
15
|
+
const cbs = listeners.get(event);
|
|
16
|
+
if (cbs) {
|
|
17
|
+
const idx = cbs.indexOf(callback);
|
|
18
|
+
if (idx !== -1) cbs.splice(idx, 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function trigger(event, model) {
|
|
22
|
+
const cbs = listeners.get(event);
|
|
23
|
+
if (cbs) for (const cb of cbs) await cb(model);
|
|
24
|
+
}
|
|
25
|
+
function clone() {
|
|
26
|
+
const cloned = createHookManager();
|
|
27
|
+
for (const [event, cbs] of listeners) for (const cb of cbs) cloned.on(event, cb);
|
|
28
|
+
return cloned;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
on,
|
|
32
|
+
off,
|
|
33
|
+
trigger,
|
|
34
|
+
clone
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/model/hooks.ts
|
|
39
|
+
var hooks_exports = /* @__PURE__ */ __exportAll({
|
|
40
|
+
getHooksFor: () => getHooksFor,
|
|
41
|
+
getSoftDeleteConfig: () => getSoftDeleteConfig,
|
|
42
|
+
hasSoftDelete: () => hasSoftDelete,
|
|
43
|
+
registerSoftDeletesFor: () => registerSoftDeletesFor,
|
|
44
|
+
registerTimestampsFor: () => registerTimestampsFor
|
|
45
|
+
});
|
|
46
|
+
const hookManagers = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
function getHooksFor(def) {
|
|
48
|
+
let hm = hookManagers.get(def);
|
|
49
|
+
if (!hm) {
|
|
50
|
+
hm = createHookManager();
|
|
51
|
+
hookManagers.set(def, hm);
|
|
52
|
+
}
|
|
53
|
+
return hm;
|
|
54
|
+
}
|
|
55
|
+
const SOFT_DELETE = /* @__PURE__ */ new WeakMap();
|
|
56
|
+
function hasSoftDelete(def) {
|
|
57
|
+
return SOFT_DELETE.has(def);
|
|
58
|
+
}
|
|
59
|
+
function getSoftDeleteConfig(def) {
|
|
60
|
+
return SOFT_DELETE.get(def);
|
|
61
|
+
}
|
|
62
|
+
function registerSoftDeletesFor(def, deletedAtColumn = "deletedAt") {
|
|
63
|
+
SOFT_DELETE.set(def, { column: deletedAtColumn });
|
|
64
|
+
}
|
|
65
|
+
function registerTimestampsFor(def, createdAtCol = "createdAt", updatedAtCol = "updatedAt") {
|
|
66
|
+
const hm = getHooksFor(def);
|
|
67
|
+
hm.on("beforeCreate", (model) => {
|
|
68
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
69
|
+
if (!model.get(createdAtCol)) model.set(createdAtCol, now);
|
|
70
|
+
model.set(updatedAtCol, now);
|
|
71
|
+
});
|
|
72
|
+
hm.on("beforeUpdate", (model) => {
|
|
73
|
+
model.set(updatedAtCol, (/* @__PURE__ */ new Date()).toISOString());
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { registerSoftDeletesFor as a, hooks_exports as i, getSoftDeleteConfig as n, registerTimestampsFor as o, hasSoftDelete as r, createHookManager as s, getHooksFor as t };
|