@alpha.consultings/eloquent-orm.js 1.0.3 → 1.0.4
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [1.0.4](https://github.com/MetalDz/Eloquent-ORM.js/compare/v1.0.3...v1.0.4) (2026-03-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add real sql rest scenario matrix and correct serialization delete runtime ([194dc23](https://github.com/MetalDz/Eloquent-ORM.js/commit/194dc235d5b9ccd7f8a930ce7f9c6683d718a336))
|
|
7
|
+
* reduce inactive tooling deps and harden security transparency ([72d591d](https://github.com/MetalDz/Eloquent-ORM.js/commit/72d591dc8fec12648f3844595c41e8c34fa2983a))
|
|
8
|
+
|
|
1
9
|
## [1.0.3](https://github.com/MetalDz/Eloquent-ORM.js/compare/v1.0.2...v1.0.3) (2026-03-24)
|
|
2
10
|
|
|
3
11
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Eloquent ORM JS
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
|
|
4
|
+
[](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
|
|
5
|
+
[](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
|
|
6
|
+
[](https://github.com/MetalDz/Eloquent-ORM.js/actions/workflows/ci.yml)
|
|
7
|
+
[](https://github.com/MetalDz/Eloquent-ORM.js)
|
|
8
|
+
[](https://github.com/MetalDz/Eloquent-ORM.js/blob/ai_master/LICENSE)
|
|
9
|
+
[](https://alphaconsultings.mintlify.app/)
|
|
10
|
+
[](https://socket.dev/npm/package/@alpha.consultings/eloquent-orm.js)
|
|
11
|
+
|
|
3
12
|
Laravel-inspired ORM + CLI for Node.js + TypeScript with SQL and MongoDB runtime support.
|
|
4
13
|
|
|
5
14
|
Package: `@alpha.consultings/eloquent-orm.js`
|
|
@@ -235,6 +244,9 @@ Some package scanners flag this package for network access and eval-like behavio
|
|
|
235
244
|
- Outbound DB/cache connections are by design. This package opens runtime connections to MySQL, PostgreSQL, MongoDB, SQLite, and Memcached when those drivers are configured.
|
|
236
245
|
- Mongo SRV mode may use custom DNS resolvers when configured. If you use a `mongodb+srv://` URI and set `MONGO_DNS_SERVERS`, the runtime may call Node's in-process DNS resolver override for Mongo SRV lookups.
|
|
237
246
|
- Eval-like behavior is not part of this package's own runtime source. Scanner warnings usually come from the `mysql2` dependency, which generates row parsers dynamically for performance.
|
|
247
|
+
- The well-known `readCodeFor` arbitrary code injection issue affected `mysql2` versions earlier than `3.9.7`. This package currently depends on `mysql2` `^3.15.2`, which is above that fixed line and is not in the vulnerable range.
|
|
248
|
+
- I also verified that the `mysql2` project continued shipping security hardening after that fix. The official `3.19.1` release notes mention bounds checks, malformed payload handling, and config-injection hardening, and npm currently lists `3.20.0` as the latest stable release as of March 25, 2026.
|
|
249
|
+
- I am intentionally not claiming every third-party summary verbatim. The specific claim I verified directly is: `mysql2 < 3.9.7` was vulnerable, while this package's supported range is above that threshold.
|
|
238
250
|
|
|
239
251
|
For the current hosted docs and security guidance:
|
|
240
252
|
|
|
@@ -60,7 +60,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
60
60
|
hidden: string[];
|
|
61
61
|
appends: string[];
|
|
62
62
|
toObject(): Record<string, unknown>;
|
|
63
|
-
toJSON(): string
|
|
63
|
+
toJSON(): Record<string, unknown>;
|
|
64
64
|
serializeValue(value: unknown): unknown;
|
|
65
65
|
all(): Promise<unknown[]>;
|
|
66
66
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -69,7 +69,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
69
69
|
hidden: string[];
|
|
70
70
|
appends: string[];
|
|
71
71
|
toObject(): Record<string, unknown>;
|
|
72
|
-
toJSON(): string
|
|
72
|
+
toJSON(): Record<string, unknown>;
|
|
73
73
|
serializeValue(value: unknown): unknown;
|
|
74
74
|
all(): Promise<unknown[]>;
|
|
75
75
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -78,7 +78,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
78
78
|
hidden: string[];
|
|
79
79
|
appends: string[];
|
|
80
80
|
toObject(): Record<string, unknown>;
|
|
81
|
-
toJSON(): string
|
|
81
|
+
toJSON(): Record<string, unknown>;
|
|
82
82
|
serializeValue(value: unknown): unknown;
|
|
83
83
|
all(): Promise<unknown[]>;
|
|
84
84
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -87,7 +87,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
87
87
|
hidden: string[];
|
|
88
88
|
appends: string[];
|
|
89
89
|
toObject(): Record<string, unknown>;
|
|
90
|
-
toJSON(): string
|
|
90
|
+
toJSON(): Record<string, unknown>;
|
|
91
91
|
serializeValue(value: unknown): unknown;
|
|
92
92
|
all(): Promise<unknown[]>;
|
|
93
93
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -96,7 +96,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
96
96
|
hidden: string[];
|
|
97
97
|
appends: string[];
|
|
98
98
|
toObject(): Record<string, unknown>;
|
|
99
|
-
toJSON(): string
|
|
99
|
+
toJSON(): Record<string, unknown>;
|
|
100
100
|
serializeValue(value: unknown): unknown;
|
|
101
101
|
all(): Promise<unknown[]>;
|
|
102
102
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -105,7 +105,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
105
105
|
hidden: string[];
|
|
106
106
|
appends: string[];
|
|
107
107
|
toObject(): Record<string, unknown>;
|
|
108
|
-
toJSON(): string
|
|
108
|
+
toJSON(): Record<string, unknown>;
|
|
109
109
|
serializeValue(value: unknown): unknown;
|
|
110
110
|
all(): Promise<unknown[]>;
|
|
111
111
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -114,7 +114,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
114
114
|
hidden: string[];
|
|
115
115
|
appends: string[];
|
|
116
116
|
toObject(): Record<string, unknown>;
|
|
117
|
-
toJSON(): string
|
|
117
|
+
toJSON(): Record<string, unknown>;
|
|
118
118
|
serializeValue(value: unknown): unknown;
|
|
119
119
|
all(): Promise<unknown[]>;
|
|
120
120
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -123,7 +123,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
123
123
|
hidden: string[];
|
|
124
124
|
appends: string[];
|
|
125
125
|
toObject(): Record<string, unknown>;
|
|
126
|
-
toJSON(): string
|
|
126
|
+
toJSON(): Record<string, unknown>;
|
|
127
127
|
serializeValue(value: unknown): unknown;
|
|
128
128
|
all(): Promise<unknown[]>;
|
|
129
129
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -132,7 +132,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
132
132
|
hidden: string[];
|
|
133
133
|
appends: string[];
|
|
134
134
|
toObject(): Record<string, unknown>;
|
|
135
|
-
toJSON(): string
|
|
135
|
+
toJSON(): Record<string, unknown>;
|
|
136
136
|
serializeValue(value: unknown): unknown;
|
|
137
137
|
all(): Promise<unknown[]>;
|
|
138
138
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -141,7 +141,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
141
141
|
hidden: string[];
|
|
142
142
|
appends: string[];
|
|
143
143
|
toObject(): Record<string, unknown>;
|
|
144
|
-
toJSON(): string
|
|
144
|
+
toJSON(): Record<string, unknown>;
|
|
145
145
|
serializeValue(value: unknown): unknown;
|
|
146
146
|
all(): Promise<unknown[]>;
|
|
147
147
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -150,7 +150,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
150
150
|
hidden: string[];
|
|
151
151
|
appends: string[];
|
|
152
152
|
toObject(): Record<string, unknown>;
|
|
153
|
-
toJSON(): string
|
|
153
|
+
toJSON(): Record<string, unknown>;
|
|
154
154
|
serializeValue(value: unknown): unknown;
|
|
155
155
|
all(): Promise<unknown[]>;
|
|
156
156
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -159,7 +159,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
159
159
|
hidden: string[];
|
|
160
160
|
appends: string[];
|
|
161
161
|
toObject(): Record<string, unknown>;
|
|
162
|
-
toJSON(): string
|
|
162
|
+
toJSON(): Record<string, unknown>;
|
|
163
163
|
serializeValue(value: unknown): unknown;
|
|
164
164
|
all(): Promise<unknown[]>;
|
|
165
165
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -168,7 +168,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
168
168
|
hidden: string[];
|
|
169
169
|
appends: string[];
|
|
170
170
|
toObject(): Record<string, unknown>;
|
|
171
|
-
toJSON(): string
|
|
171
|
+
toJSON(): Record<string, unknown>;
|
|
172
172
|
serializeValue(value: unknown): unknown;
|
|
173
173
|
all(): Promise<unknown[]>;
|
|
174
174
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -177,7 +177,7 @@ declare const SafeFinderStaticModel: ((abstract new (...args: any[]) => {
|
|
|
177
177
|
hidden: string[];
|
|
178
178
|
appends: string[];
|
|
179
179
|
toObject(): Record<string, unknown>;
|
|
180
|
-
toJSON(): string
|
|
180
|
+
toJSON(): Record<string, unknown>;
|
|
181
181
|
serializeValue(value: unknown): unknown;
|
|
182
182
|
all(): Promise<unknown[]>;
|
|
183
183
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
@@ -7,7 +7,7 @@ export interface SerializableModel {
|
|
|
7
7
|
all(): Promise<unknown[]>;
|
|
8
8
|
find(id: number | string, pk?: string): Promise<unknown | null>;
|
|
9
9
|
toObject?(): Record<string, unknown>;
|
|
10
|
-
toJSON?(): string
|
|
10
|
+
toJSON?(): Record<string, unknown>;
|
|
11
11
|
}
|
|
12
12
|
/** Generic abstract constructor used by all mixins */
|
|
13
13
|
type Constructor<T = object> = abstract new (...args: any[]) => T;
|
|
@@ -32,7 +32,7 @@ export declare function SerializeMixin<TBase extends Constructor<SerializableMod
|
|
|
32
32
|
/**
|
|
33
33
|
* 🧠 Convert model to JSON string
|
|
34
34
|
*/
|
|
35
|
-
toJSON(): string
|
|
35
|
+
toJSON(): Record<string, unknown>;
|
|
36
36
|
/**
|
|
37
37
|
* ♻️ Recursively serialize nested models, arrays, or plain objects
|
|
38
38
|
*/
|
|
@@ -11,6 +11,27 @@ const BaseMethodResolver_1 = require("./utils/BaseMethodResolver");
|
|
|
11
11
|
function SoftDeletesMixin(Base) {
|
|
12
12
|
const resolveBaseMethod = (0, BaseMethodResolver_1.createBaseMethodResolver)(Base);
|
|
13
13
|
class SoftDeletableModel extends Base {
|
|
14
|
+
supportsSoftDeletes() {
|
|
15
|
+
const ctor = this.constructor;
|
|
16
|
+
if (ctor.softDeletes === true) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const schema = ctor.schema;
|
|
20
|
+
if (!schema || typeof schema !== "object") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return Object.entries(schema).some(([fieldName, field]) => {
|
|
24
|
+
if (fieldName === this.deletedAtColumn) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (!field || typeof field !== "object") {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const candidate = field;
|
|
31
|
+
return (candidate.type === "softDeletes" ||
|
|
32
|
+
(candidate.kind === "mixin" && candidate.name === "SoftDeletes"));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
14
35
|
constructor(...args) {
|
|
15
36
|
super(...args);
|
|
16
37
|
this.deletedAtColumn = "deleted_at";
|
|
@@ -46,6 +67,19 @@ function SoftDeletesMixin(Base) {
|
|
|
46
67
|
}
|
|
47
68
|
}
|
|
48
69
|
async delete(id, pk = "id") {
|
|
70
|
+
if (!this.supportsSoftDeletes()) {
|
|
71
|
+
const baseDelete = resolveBaseMethod(this, "delete");
|
|
72
|
+
if (typeof baseDelete !== "function") {
|
|
73
|
+
throw new Error("Base 'delete' method not found for SoftDeletesMixin.");
|
|
74
|
+
}
|
|
75
|
+
const targetId = id ?? this.getTrackedPrimaryValue(pk);
|
|
76
|
+
if (targetId === undefined || targetId === null) {
|
|
77
|
+
throw new Error(`Cannot delete ${this.constructor.name} without primary key '${pk}'.`);
|
|
78
|
+
}
|
|
79
|
+
await baseDelete(targetId, pk);
|
|
80
|
+
this.syncSoftDeleteState(targetId, pk, null, { removed: true });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
49
83
|
const baseUpdate = resolveBaseMethod(this, "update");
|
|
50
84
|
if (typeof baseUpdate !== "function") {
|
|
51
85
|
throw new Error("Base 'update' method not found for SoftDeletesMixin.");
|
|
@@ -79,6 +113,9 @@ function SoftDeletesMixin(Base) {
|
|
|
79
113
|
throw new Error("Base 'all' method not found for SoftDeletesMixin.");
|
|
80
114
|
}
|
|
81
115
|
const records = await baseAll();
|
|
116
|
+
if (!this.supportsSoftDeletes()) {
|
|
117
|
+
return records;
|
|
118
|
+
}
|
|
82
119
|
return records.filter((record) => !record[this.deletedAtColumn]);
|
|
83
120
|
}
|
|
84
121
|
/**
|
|
@@ -92,6 +129,9 @@ function SoftDeletesMixin(Base) {
|
|
|
92
129
|
const record = await baseFind(id, pk);
|
|
93
130
|
if (!record)
|
|
94
131
|
return null;
|
|
132
|
+
if (!this.supportsSoftDeletes()) {
|
|
133
|
+
return record;
|
|
134
|
+
}
|
|
95
135
|
const isDeleted = typeof record[this.deletedAtColumn] === "string" &&
|
|
96
136
|
record[this.deletedAtColumn] !== null;
|
|
97
137
|
return isDeleted ? null : record;
|
|
@@ -115,6 +155,9 @@ function SoftDeletesMixin(Base) {
|
|
|
115
155
|
throw new Error("Base 'all' method not found for SoftDeletesMixin.");
|
|
116
156
|
}
|
|
117
157
|
const allRecords = (await baseAll());
|
|
158
|
+
if (!this.supportsSoftDeletes()) {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
118
161
|
return allRecords.filter((record) => typeof record[this.deletedAtColumn] === "string" &&
|
|
119
162
|
record[this.deletedAtColumn] !== null);
|
|
120
163
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alpha.consultings/eloquent-orm.js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A Laravel Eloquent-inspired ORM Multi Driver SQL & NoSQL and Cache System and Artisan CLI like for Node.js Lovers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"orm",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"test:mysql-smoke": "jest --runInBand --runTestsByPath src/lab_test/cli.integration.scenario.lifecycle.test.ts src/lab_test/cli.integration.make-migration.targeting.test.ts src/lab_test/cli.integration.migrate.targeting.test.ts src/lab_test/cli.integration.seed-and-demo.targeting.test.ts src/lab_test/cli.integration.factory-status.targeting.test.ts src/lab_test/migration.tracker.logic.test.ts src/lab_test/cache.commands.logic.test.ts",
|
|
82
82
|
"coverage:misses": "npm run test:coverage && node scripts/coverage-misses.cjs",
|
|
83
83
|
"test:critical": "jest --runInBand src/lab_test/cli.integration.scenario.lifecycle.test.ts src/lab_test/cli.integration.make-migration.targeting.test.ts src/lab_test/cli.integration.migrate.targeting.test.ts src/lab_test/cli.integration.seed-and-demo.targeting.test.ts src/lab_test/cli.integration.factory-status.targeting.test.ts src/lab_test/migration.tracker.logic.test.ts src/lab_test/cache.commands.logic.test.ts",
|
|
84
|
-
"test:pack-smoke": "node scripts/pack-smoke.js",
|
|
84
|
+
"test:pack-smoke": "npm run build && node scripts/pack-smoke.js",
|
|
85
85
|
"test:pack-smoke:docker": "docker compose -f docker-compose.coverage-debug.yml run --rm pack-smoke",
|
|
86
86
|
"dev": "ts-node src/index.ts",
|
|
87
87
|
"cli": "ts-node bin/eloquent.ts",
|
|
@@ -115,11 +115,9 @@
|
|
|
115
115
|
"@types/memcached": "^2.2.10",
|
|
116
116
|
"@types/node": "^22.18.12",
|
|
117
117
|
"@types/pg": "^8.15.5",
|
|
118
|
-
"eslint": "^9.38.0",
|
|
119
118
|
"express": "^5.1.0",
|
|
120
119
|
"jest": "^30.2.0",
|
|
121
120
|
"semantic-release": "^24.2.9",
|
|
122
|
-
"ts-jest": "^29.4.5"
|
|
123
|
-
"typescript-eslint": "^8.46.1"
|
|
121
|
+
"ts-jest": "^29.4.5"
|
|
124
122
|
}
|
|
125
123
|
}
|