@shadow-dev/orm 2.0.0 → 2.0.2
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 +118 -118
- package/dist/core/Database.js +6 -6
- package/dist/core/Model.d.ts +1 -1
- package/dist/core/Repository.js +28 -28
- package/dist/utils/getNextId.js +9 -9
- package/dist/utils/syncSchema.js +50 -19
- package/package.json +55 -54
package/README.md
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
# ShadowORM
|
|
2
|
-
|
|
3
|
-
> 🧩 Lightweight, type-safe MySQL ORM for ShadowCore projects.
|
|
4
|
-
> ShadowORM is built for **modularity**, **security**, and **runtime schema sync** ΓÇö perfect for bots, services, or web apps using ShadowCore.
|
|
5
|
-
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## 🔍 Overview
|
|
12
|
-
|
|
13
|
-
ShadowORM is a minimalist ORM that offers:
|
|
14
|
-
|
|
15
|
-
- ✅ **Type-safe models** using generics
|
|
16
|
-
- ✅ **Automatic schema synchronization** (no migration needed)
|
|
17
|
-
- ✅ **JSON + Date normalization**
|
|
18
|
-
- ✅ **Relational support** with foreign keys
|
|
19
|
-
- ✅ **No decorators, no reflection, no magic**
|
|
20
|
-
|
|
21
|
-
ItΓÇÖs designed to work cleanly alongside ShadowCore but can also be used standalone in any Node.js TypeScript project.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 📦 Installation
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npm install @shadow-dev/orm mysql2
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## 🛠 Usage Example
|
|
34
|
-
|
|
35
|
-
```ts
|
|
36
|
-
import { Model, Repository, initDatabase, registerModel } from "@shadow-dev/orm";
|
|
37
|
-
|
|
38
|
-
const Ticket = new Model<{
|
|
39
|
-
id: string;
|
|
40
|
-
type: "support" | "report";
|
|
41
|
-
data: { message: string };
|
|
42
|
-
createdAt: Date;
|
|
43
|
-
}>("tickets", {
|
|
44
|
-
id: "string",
|
|
45
|
-
type: "string",
|
|
46
|
-
data: "json",
|
|
47
|
-
createdAt: "datetime"
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
initDatabase({
|
|
51
|
-
host: "localhost",
|
|
52
|
-
user: "root",
|
|
53
|
-
password: "password",
|
|
54
|
-
database: "mydb"
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
registerModel(Ticket);
|
|
58
|
-
|
|
59
|
-
// Auto-create table on startup
|
|
60
|
-
await syncSchema();
|
|
61
|
-
|
|
62
|
-
const tickets = new Repository(Ticket);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Use it
|
|
66
|
-
await tickets.create({
|
|
67
|
-
id: "ticket-001",
|
|
68
|
-
type: "support",
|
|
69
|
-
data: { message: "Help me!" },
|
|
70
|
-
createdAt: new Date()
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## 🧠 Schema Types
|
|
77
|
-
|
|
78
|
-
ShadowORM supports:
|
|
79
|
-
|
|
80
|
-
| Type | SQL Equivalent |
|
|
81
|
-
|---------------------------|-------------------|
|
|
82
|
-
| `string` | `VARCHAR(255)` |
|
|
83
|
-
| `number` | `INT` |
|
|
84
|
-
| `boolean` | `BOOLEAN` |
|
|
85
|
-
| `json` | `LONGTEXT` |
|
|
86
|
-
| `datetime` | `DATETIME` |
|
|
87
|
-
| `FOREIGN_KEY:<tbl.col>` | Foreign key ref |
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## 🧱 Roadmap
|
|
92
|
-
|
|
93
|
-
- [x] CRUD repository
|
|
94
|
-
- [x] Relational schema support
|
|
95
|
-
- [x] Automatic schema sync
|
|
96
|
-
- [ ] CLI (optional)
|
|
97
|
-
- [ ] Migrations (optional)
|
|
98
|
-
- [ ] Postgres support (maybe)
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 📖 Documentation
|
|
103
|
-
|
|
104
|
-
📚 Docs are coming soon and will be available on the ShadowCore documentation site:
|
|
105
|
-
➡️ [docs.shadowdevelopment.net](https://docs.shadowdevelopment.net)
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## 🏢 Project Ownership
|
|
110
|
-
|
|
111
|
-
ShadowORM is officially developed and maintained under [Shadow Development LLC](https://shadowdevelopment.net).
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## 📜 License
|
|
116
|
-
|
|
117
|
-
Licensed under the **GNU General Public License v3.0**
|
|
118
|
-
See the [LICENSE](LICENSE) file for details.
|
|
1
|
+
# ShadowORM
|
|
2
|
+
|
|
3
|
+
> 🧩 Lightweight, type-safe MySQL ORM for ShadowCore projects.
|
|
4
|
+
> ShadowORM is built for **modularity**, **security**, and **runtime schema sync** ΓÇö perfect for bots, services, or web apps using ShadowCore.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🔍 Overview
|
|
12
|
+
|
|
13
|
+
ShadowORM is a minimalist ORM that offers:
|
|
14
|
+
|
|
15
|
+
- ✅ **Type-safe models** using generics
|
|
16
|
+
- ✅ **Automatic schema synchronization** (no migration needed)
|
|
17
|
+
- ✅ **JSON + Date normalization**
|
|
18
|
+
- ✅ **Relational support** with foreign keys
|
|
19
|
+
- ✅ **No decorators, no reflection, no magic**
|
|
20
|
+
|
|
21
|
+
ItΓÇÖs designed to work cleanly alongside ShadowCore but can also be used standalone in any Node.js TypeScript project.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 📦 Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @shadow-dev/orm mysql2
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🛠 Usage Example
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { Model, Repository, initDatabase, registerModel } from "@shadow-dev/orm";
|
|
37
|
+
|
|
38
|
+
const Ticket = new Model<{
|
|
39
|
+
id: string;
|
|
40
|
+
type: "support" | "report";
|
|
41
|
+
data: { message: string };
|
|
42
|
+
createdAt: Date;
|
|
43
|
+
}>("tickets", {
|
|
44
|
+
id: "string",
|
|
45
|
+
type: "string",
|
|
46
|
+
data: "json",
|
|
47
|
+
createdAt: "datetime"
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
initDatabase({
|
|
51
|
+
host: "localhost",
|
|
52
|
+
user: "root",
|
|
53
|
+
password: "password",
|
|
54
|
+
database: "mydb"
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
registerModel(Ticket);
|
|
58
|
+
|
|
59
|
+
// Auto-create table on startup
|
|
60
|
+
await syncSchema();
|
|
61
|
+
|
|
62
|
+
const tickets = new Repository(Ticket);
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// Use it
|
|
66
|
+
await tickets.create({
|
|
67
|
+
id: "ticket-001",
|
|
68
|
+
type: "support",
|
|
69
|
+
data: { message: "Help me!" },
|
|
70
|
+
createdAt: new Date()
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🧠 Schema Types
|
|
77
|
+
|
|
78
|
+
ShadowORM supports:
|
|
79
|
+
|
|
80
|
+
| Type | SQL Equivalent |
|
|
81
|
+
|---------------------------|-------------------|
|
|
82
|
+
| `string` | `VARCHAR(255)` |
|
|
83
|
+
| `number` | `INT` |
|
|
84
|
+
| `boolean` | `BOOLEAN` |
|
|
85
|
+
| `json` | `LONGTEXT` |
|
|
86
|
+
| `datetime` | `DATETIME` |
|
|
87
|
+
| `FOREIGN_KEY:<tbl.col>` | Foreign key ref |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 🧱 Roadmap
|
|
92
|
+
|
|
93
|
+
- [x] CRUD repository
|
|
94
|
+
- [x] Relational schema support
|
|
95
|
+
- [x] Automatic schema sync
|
|
96
|
+
- [ ] CLI (optional)
|
|
97
|
+
- [ ] Migrations (optional)
|
|
98
|
+
- [ ] Postgres support (maybe)
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📖 Documentation
|
|
103
|
+
|
|
104
|
+
📚 Docs are coming soon and will be available on the ShadowCore documentation site:
|
|
105
|
+
➡️ [docs.shadowdevelopment.net](https://docs.shadowdevelopment.net)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🏢 Project Ownership
|
|
110
|
+
|
|
111
|
+
ShadowORM is officially developed and maintained under [Shadow Development LLC](https://shadowdevelopment.net).
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 📜 License
|
|
116
|
+
|
|
117
|
+
Licensed under the **GNU General Public License v3.0**
|
|
118
|
+
See the [LICENSE](LICENSE) file for details.
|
package/dist/core/Database.js
CHANGED
|
@@ -66,12 +66,12 @@ export async function transaction(fn) {
|
|
|
66
66
|
/* Migrations */
|
|
67
67
|
/* ---------------------------------- */
|
|
68
68
|
async function ensureMigrationTable() {
|
|
69
|
-
await exec(`
|
|
70
|
-
CREATE TABLE IF NOT EXISTS shadoworm_migrations (
|
|
71
|
-
id VARCHAR(255) PRIMARY KEY,
|
|
72
|
-
name VARCHAR(255) NOT NULL,
|
|
73
|
-
executed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
74
|
-
);
|
|
69
|
+
await exec(`
|
|
70
|
+
CREATE TABLE IF NOT EXISTS shadoworm_migrations (
|
|
71
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
72
|
+
name VARCHAR(255) NOT NULL,
|
|
73
|
+
executed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
74
|
+
);
|
|
75
75
|
`);
|
|
76
76
|
}
|
|
77
77
|
async function loadMigrations(dir) {
|
package/dist/core/Model.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface BaseSchema {
|
|
|
3
3
|
data?: any;
|
|
4
4
|
createdAt?: Date;
|
|
5
5
|
}
|
|
6
|
-
export type SimpleFieldType = "string" | "int" | "float" | "boolean" | "
|
|
6
|
+
export type SimpleFieldType = "string" | "text" | "mediumtext" | "longtext" | "int" | "bigint" | "float" | "double" | "decimal" | "boolean" | "date" | "time" | "datetime" | "timestamp" | "json" | "binary" | "varbinary" | "uuid";
|
|
7
7
|
export interface FieldOptions {
|
|
8
8
|
type: SimpleFieldType;
|
|
9
9
|
pk?: boolean;
|
package/dist/core/Repository.js
CHANGED
|
@@ -16,10 +16,10 @@ export class Repository {
|
|
|
16
16
|
const keys = this.getInsertableKeys(data);
|
|
17
17
|
if (keys.length === 0)
|
|
18
18
|
throw new Error("create(): empty data");
|
|
19
|
-
const sql = `
|
|
20
|
-
INSERT INTO \`${this.model.name}\`
|
|
21
|
-
(${keys.map(k => `\`${k}\``).join(",")})
|
|
22
|
-
VALUES (${keys.map(() => "?").join(",")})
|
|
19
|
+
const sql = `
|
|
20
|
+
INSERT INTO \`${this.model.name}\`
|
|
21
|
+
(${keys.map(k => `\`${k}\``).join(",")})
|
|
22
|
+
VALUES (${keys.map(() => "?").join(",")})
|
|
23
23
|
`;
|
|
24
24
|
const values = keys.map(k => this.normalizeWriteValue(k, data[k]));
|
|
25
25
|
const [res] = await getPool().execute(sql, values);
|
|
@@ -39,10 +39,10 @@ export class Repository {
|
|
|
39
39
|
.map(() => `(${keys.map(() => "?").join(",")})`)
|
|
40
40
|
.join(",");
|
|
41
41
|
const values = rows.flatMap(row => keys.map(k => this.normalizeWriteValue(k, row[k])));
|
|
42
|
-
const sql = `
|
|
43
|
-
INSERT INTO \`${this.model.name}\`
|
|
44
|
-
(${keys.map(k => `\`${k}\``).join(",")})
|
|
45
|
-
VALUES ${placeholders}
|
|
42
|
+
const sql = `
|
|
43
|
+
INSERT INTO \`${this.model.name}\`
|
|
44
|
+
(${keys.map(k => `\`${k}\``).join(",")})
|
|
45
|
+
VALUES ${placeholders}
|
|
46
46
|
`;
|
|
47
47
|
const [res] = await getPool().execute(sql, values);
|
|
48
48
|
const pk = this.getPrimaryKeyField();
|
|
@@ -59,10 +59,10 @@ export class Repository {
|
|
|
59
59
|
.map(() => `(${keys.map(() => "?").join(",")})`)
|
|
60
60
|
.join(",");
|
|
61
61
|
const values = rows.flatMap(row => keys.map(k => this.normalizeWriteValue(k, row[k])));
|
|
62
|
-
const sql = `
|
|
63
|
-
INSERT INTO \`${this.model.name}\`
|
|
64
|
-
(${keys.map(k => `\`${k}\``).join(",")})
|
|
65
|
-
VALUES ${placeholders}
|
|
62
|
+
const sql = `
|
|
63
|
+
INSERT INTO \`${this.model.name}\`
|
|
64
|
+
(${keys.map(k => `\`${k}\``).join(",")})
|
|
65
|
+
VALUES ${placeholders}
|
|
66
66
|
`;
|
|
67
67
|
const [res] = await getPool().execute(sql, values);
|
|
68
68
|
return res.affectedRows;
|
|
@@ -100,9 +100,9 @@ export class Repository {
|
|
|
100
100
|
return [];
|
|
101
101
|
const pk = this.getPrimaryKeyField();
|
|
102
102
|
const placeholders = ids.map(() => "?").join(",");
|
|
103
|
-
const query = `
|
|
104
|
-
SELECT * FROM \`${this.model.name}\`
|
|
105
|
-
WHERE \`${String(pk)}\` IN (${placeholders})
|
|
103
|
+
const query = `
|
|
104
|
+
SELECT * FROM \`${this.model.name}\`
|
|
105
|
+
WHERE \`${String(pk)}\` IN (${placeholders})
|
|
106
106
|
`;
|
|
107
107
|
const [rows] = await getPool().execute(query, ids);
|
|
108
108
|
return rows;
|
|
@@ -120,10 +120,10 @@ export class Repository {
|
|
|
120
120
|
const setClause = setKeys.map(k => `\`${k}\` = ?`).join(", ");
|
|
121
121
|
const setValues = setKeys.map(k => this.normalizeWriteValue(k, data[k]));
|
|
122
122
|
const { sql: whereClause, params: whereValues } = this.buildWhereClause(where);
|
|
123
|
-
const query = `
|
|
124
|
-
UPDATE \`${this.model.name}\`
|
|
125
|
-
SET ${setClause}
|
|
126
|
-
${whereClause}
|
|
123
|
+
const query = `
|
|
124
|
+
UPDATE \`${this.model.name}\`
|
|
125
|
+
SET ${setClause}
|
|
126
|
+
${whereClause}
|
|
127
127
|
`;
|
|
128
128
|
await getPool().execute(query, [...setValues, ...whereValues]);
|
|
129
129
|
return this.findOne(where);
|
|
@@ -138,10 +138,10 @@ export class Repository {
|
|
|
138
138
|
const setClause = setKeys.map(k => `\`${k}\` = ?`).join(", ");
|
|
139
139
|
const setValues = setKeys.map(k => this.normalizeWriteValue(k, data[k]));
|
|
140
140
|
const { sql, params } = this.buildWhereClause(where);
|
|
141
|
-
const query = `
|
|
142
|
-
UPDATE \`${this.model.name}\`
|
|
143
|
-
SET ${setClause}
|
|
144
|
-
${sql}
|
|
141
|
+
const query = `
|
|
142
|
+
UPDATE \`${this.model.name}\`
|
|
143
|
+
SET ${setClause}
|
|
144
|
+
${sql}
|
|
145
145
|
`;
|
|
146
146
|
const [res] = await getPool().execute(query, [
|
|
147
147
|
...setValues,
|
|
@@ -180,11 +180,11 @@ export class Repository {
|
|
|
180
180
|
.map(k => `\`${k}\` = VALUES(\`${k}\`)`)
|
|
181
181
|
.join(",");
|
|
182
182
|
const values = keys.map(k => this.normalizeWriteValue(k, data[k]));
|
|
183
|
-
const sql = `
|
|
184
|
-
INSERT INTO \`${this.model.name}\`
|
|
185
|
-
(${insertCols})
|
|
186
|
-
VALUES (${insertVals})
|
|
187
|
-
ON DUPLICATE KEY UPDATE ${updateCols}
|
|
183
|
+
const sql = `
|
|
184
|
+
INSERT INTO \`${this.model.name}\`
|
|
185
|
+
(${insertCols})
|
|
186
|
+
VALUES (${insertVals})
|
|
187
|
+
ON DUPLICATE KEY UPDATE ${updateCols}
|
|
188
188
|
`;
|
|
189
189
|
await getPool().execute(sql, values);
|
|
190
190
|
return (await this.findOne({ [pk]: data[pk] }));
|
package/dist/utils/getNextId.js
CHANGED
|
@@ -2,18 +2,18 @@ import { getPool } from "../core/Database.js";
|
|
|
2
2
|
export async function getNextId(prefix) {
|
|
3
3
|
const pool = getPool();
|
|
4
4
|
// Ensure table exists (safe to call multiple times)
|
|
5
|
-
await pool.execute(`
|
|
6
|
-
CREATE TABLE IF NOT EXISTS _id_counters (
|
|
7
|
-
prefix VARCHAR(255) PRIMARY KEY,
|
|
8
|
-
count INT NOT NULL
|
|
9
|
-
)
|
|
5
|
+
await pool.execute(`
|
|
6
|
+
CREATE TABLE IF NOT EXISTS _id_counters (
|
|
7
|
+
prefix VARCHAR(255) PRIMARY KEY,
|
|
8
|
+
count INT NOT NULL
|
|
9
|
+
)
|
|
10
10
|
`);
|
|
11
11
|
// Atomic upsert + increment
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
|
-
const [result] = await pool.execute(`
|
|
14
|
-
INSERT INTO _id_counters (prefix, count)
|
|
15
|
-
VALUES (?, 1)
|
|
16
|
-
ON DUPLICATE KEY UPDATE count = count + 1
|
|
13
|
+
const [result] = await pool.execute(`
|
|
14
|
+
INSERT INTO _id_counters (prefix, count)
|
|
15
|
+
VALUES (?, 1)
|
|
16
|
+
ON DUPLICATE KEY UPDATE count = count + 1
|
|
17
17
|
`, [prefix]);
|
|
18
18
|
// Fetch the new value
|
|
19
19
|
const [rows] = await pool.query(`SELECT count FROM _id_counters WHERE prefix = ?`, [prefix]);
|
package/dist/utils/syncSchema.js
CHANGED
|
@@ -6,14 +6,35 @@ import { getAllModels, getPool } from "../core/Database.js";
|
|
|
6
6
|
/* Helpers */
|
|
7
7
|
/* ---------------------------------- */
|
|
8
8
|
function mapType(type) {
|
|
9
|
-
switch (type) {
|
|
9
|
+
switch (type.toLowerCase()) {
|
|
10
|
+
// strings
|
|
10
11
|
case "string": return "VARCHAR(255)";
|
|
11
|
-
case "
|
|
12
|
-
case "
|
|
12
|
+
case "text": return "TEXT";
|
|
13
|
+
case "mediumtext": return "MEDIUMTEXT";
|
|
14
|
+
case "longtext": return "LONGTEXT";
|
|
15
|
+
// numbers
|
|
13
16
|
case "int": return "INT";
|
|
17
|
+
case "bigint": return "BIGINT";
|
|
14
18
|
case "float": return "FLOAT";
|
|
19
|
+
case "double": return "DOUBLE";
|
|
20
|
+
case "decimal": return "DECIMAL(10,2)";
|
|
21
|
+
// boolean
|
|
15
22
|
case "boolean": return "BOOLEAN";
|
|
16
|
-
|
|
23
|
+
// dates
|
|
24
|
+
case "date": return "DATE";
|
|
25
|
+
case "time": return "TIME";
|
|
26
|
+
case "datetime": return "DATETIME";
|
|
27
|
+
case "timestamp": return "TIMESTAMP";
|
|
28
|
+
// json
|
|
29
|
+
case "json": return "JSON";
|
|
30
|
+
// binary
|
|
31
|
+
case "binary": return "BINARY(16)";
|
|
32
|
+
case "varbinary": return "VARBINARY(255)";
|
|
33
|
+
// uuid (convention)
|
|
34
|
+
case "uuid": return "CHAR(36)";
|
|
35
|
+
// passthrough (escape hatch)
|
|
36
|
+
default:
|
|
37
|
+
return type; // allows raw MySQL like "ENUM(...)", "VARCHAR(64)", etc.
|
|
17
38
|
}
|
|
18
39
|
}
|
|
19
40
|
function formatDefault(value) {
|
|
@@ -85,10 +106,20 @@ function generateCreateTableSQL(model) {
|
|
|
85
106
|
col += ` DEFAULT ${formatDefault(field.default)}`;
|
|
86
107
|
columns.push(col);
|
|
87
108
|
}
|
|
88
|
-
const fks = model.foreignKeys.map(fk =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
109
|
+
const fks = model.foreignKeys.map(fk => {
|
|
110
|
+
let sql = `FOREIGN KEY (\`${fk.column}\`) ` +
|
|
111
|
+
`REFERENCES \`${fk.references.table}\`(\`${fk.references.column}\`)`;
|
|
112
|
+
if (fk.onDelete) {
|
|
113
|
+
sql += ` ON DELETE ${fk.onDelete}`;
|
|
114
|
+
}
|
|
115
|
+
if (fk.onUpdate) {
|
|
116
|
+
sql += ` ON UPDATE ${fk.onUpdate}`;
|
|
117
|
+
}
|
|
118
|
+
return sql;
|
|
119
|
+
});
|
|
120
|
+
return `
|
|
121
|
+
CREATE TABLE \`${model.name}\` (
|
|
122
|
+
${[...columns, ...fks].join(",\n ")}
|
|
92
123
|
);`.trim();
|
|
93
124
|
}
|
|
94
125
|
function generateIndexSQL(model) {
|
|
@@ -114,19 +145,19 @@ function emitMigration(sql, dir) {
|
|
|
114
145
|
.slice(0, 14);
|
|
115
146
|
const filename = `${id}_auto_sync.ts`;
|
|
116
147
|
const filePath = path.join(dir, filename);
|
|
117
|
-
const content = `
|
|
118
|
-
import type { Migration } from "@shadow-dev/orm";
|
|
119
|
-
|
|
120
|
-
export const migration: Migration = {
|
|
121
|
-
id: "${id}",
|
|
122
|
-
name: "auto_sync",
|
|
123
|
-
|
|
124
|
-
async up(db) {
|
|
148
|
+
const content = `
|
|
149
|
+
import type { Migration } from "@shadow-dev/orm";
|
|
150
|
+
|
|
151
|
+
export const migration: Migration = {
|
|
152
|
+
id: "${id}",
|
|
153
|
+
name: "auto_sync",
|
|
154
|
+
|
|
155
|
+
async up(db) {
|
|
125
156
|
${sql
|
|
126
157
|
.map(s => ` await db.exec(\`${s.replace(/`/g, "\\`")}\`);`)
|
|
127
|
-
.join("\n")}
|
|
128
|
-
}
|
|
129
|
-
};
|
|
158
|
+
.join("\n")}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
130
161
|
`.trim();
|
|
131
162
|
fs.writeFileSync(filePath, content, { encoding: "utf8" });
|
|
132
163
|
console.log(`📝 Migration generated: ${filePath}`);
|
package/package.json
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@shadow-dev/orm",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Lightweight dynamic MySQL ORM designed for ShadowCore and modular apps.",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"types": "./dist/index.d.ts",
|
|
7
|
-
"files": ["dist"],
|
|
8
|
-
"type": "module",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"import": "./dist/index.js",
|
|
12
|
-
"types": "./dist/index.d.ts"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"prepublishOnly": "npm run build",
|
|
17
|
-
"dev": "ts-node src/index.ts",
|
|
18
|
-
"build": "tsc",
|
|
19
|
-
"lint": "eslint . --ext .ts",
|
|
20
|
-
"type-check": "tsc --noEmit",
|
|
21
|
-
"setup": "node scripts/setup.js",
|
|
22
|
-
"test": "jest"
|
|
23
|
-
},
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "https://github.com/Shadows-Development/ShadowORM.git"
|
|
27
|
-
},
|
|
28
|
-
"author": "Shadow Development LLC",
|
|
29
|
-
"license": "LGPL-3.0-or-later",
|
|
30
|
-
"keywords": [
|
|
31
|
-
"orm",
|
|
32
|
-
"mysql",
|
|
33
|
-
"typescript",
|
|
34
|
-
"lightweight",
|
|
35
|
-
"shadowcore",
|
|
36
|
-
"shadow-dev"
|
|
37
|
-
],
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@eslint/json": "^0.13.1",
|
|
40
|
-
"@types/jest": "^30.0.0",
|
|
41
|
-
"@types/node": "^24.1.0",
|
|
42
|
-
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
43
|
-
"@typescript-eslint/parser": "^8.38.0",
|
|
44
|
-
"eslint": "^9.32.0",
|
|
45
|
-
"jest": "^30.0.5",
|
|
46
|
-
"ts-jest": "^29.4.0",
|
|
47
|
-
"ts-node": "^10.9.2",
|
|
48
|
-
"typescript": "^5.8.3",
|
|
49
|
-
"typescript-eslint": "^8.38.0"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"mysql2": "^3.14.3"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@shadow-dev/orm",
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"description": "Lightweight dynamic MySQL ORM designed for ShadowCore and modular apps.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": ["dist"],
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
17
|
+
"dev": "ts-node src/index.ts",
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"lint": "eslint . --ext .ts",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"setup": "node scripts/setup.js",
|
|
22
|
+
"test": "jest"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Shadows-Development/ShadowORM.git"
|
|
27
|
+
},
|
|
28
|
+
"author": "Shadow Development LLC",
|
|
29
|
+
"license": "LGPL-3.0-or-later",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"orm",
|
|
32
|
+
"mysql",
|
|
33
|
+
"typescript",
|
|
34
|
+
"lightweight",
|
|
35
|
+
"shadowcore",
|
|
36
|
+
"shadow-dev"
|
|
37
|
+
],
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@eslint/json": "^0.13.1",
|
|
40
|
+
"@types/jest": "^30.0.0",
|
|
41
|
+
"@types/node": "^24.1.0",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
43
|
+
"@typescript-eslint/parser": "^8.38.0",
|
|
44
|
+
"eslint": "^9.32.0",
|
|
45
|
+
"jest": "^30.0.5",
|
|
46
|
+
"ts-jest": "^29.4.0",
|
|
47
|
+
"ts-node": "^10.9.2",
|
|
48
|
+
"typescript": "^5.8.3",
|
|
49
|
+
"typescript-eslint": "^8.38.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"mysql2": "^3.14.3"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|