@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
+ [![npm version](https://img.shields.io/npm/v/%40alpha.consultings%2F@alpha.consultings/eloquent-orm.js?logo=npm&label=npm)](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
4
+ [![downloads](https://img.shields.io/npm/dm/%40alpha.consultings%2F@alpha.consultings/eloquent-orm.js?label=downloads)](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
5
+ [![node](https://img.shields.io/node/v/%40alpha.consultings%2F@alpha.consultings/eloquent-orm.js?label=node)](https://www.npmjs.com/package/@alpha.consultings/eloquent-orm.js)
6
+ [![ci](https://img.shields.io/github/actions/workflow/status/MetalDz/Eloquent-ORM.js/ci.yml?branch=ai_master&label=ci)](https://github.com/MetalDz/Eloquent-ORM.js/actions/workflows/ci.yml)
7
+ [![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://github.com/MetalDz/Eloquent-ORM.js)
8
+ [![license](https://img.shields.io/npm/l/%40alpha.consultings%2F@alpha.consultings/eloquent-orm.js?label=license)](https://github.com/MetalDz/Eloquent-ORM.js/blob/ai_master/LICENSE)
9
+ [![docs](https://img.shields.io/badge/docs-official-blue)](https://alphaconsultings.mintlify.app/)
10
+ [![Socket Badge](https://badge.socket.dev/npm/package/@alpha.consultings/eloquent-orm.js)](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
  */
@@ -51,7 +51,7 @@ function SerializeMixin(Base) {
51
51
  * 🧠 Convert model to JSON string
52
52
  */
53
53
  toJSON() {
54
- return JSON.stringify(this.toObject());
54
+ return this.toObject();
55
55
  }
56
56
  /**
57
57
  * ♻️ Recursively serialize nested models, arrays, or plain objects
@@ -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",
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
  }