@stonyx/orm 0.2.1-alpha.14 → 0.2.1-alpha.15
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/package.json +6 -2
- package/src/belongs-to.js +4 -1
- package/src/has-many.js +4 -1
- package/src/main.js +1 -1
- package/src/model.js +4 -4
- package/src/mysql/schema-introspector.js +22 -16
- package/src/store.js +1 -1
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"stonyx-async",
|
|
5
5
|
"stonyx-module"
|
|
6
6
|
],
|
|
7
|
-
"version": "0.2.1-alpha.
|
|
7
|
+
"version": "0.2.1-alpha.15",
|
|
8
8
|
"description": "",
|
|
9
9
|
"main": "src/main.js",
|
|
10
10
|
"type": "module",
|
|
@@ -38,11 +38,15 @@
|
|
|
38
38
|
"@stonyx/cron": "0.2.1-beta.12"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"mysql2": "^3.0.0"
|
|
41
|
+
"mysql2": "^3.0.0",
|
|
42
|
+
"@stonyx/rest-server": ">=0.2.1-beta.14"
|
|
42
43
|
},
|
|
43
44
|
"peerDependenciesMeta": {
|
|
44
45
|
"mysql2": {
|
|
45
46
|
"optional": true
|
|
47
|
+
},
|
|
48
|
+
"@stonyx/rest-server": {
|
|
49
|
+
"optional": true
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
package/src/belongs-to.js
CHANGED
|
@@ -11,7 +11,7 @@ export default function belongsTo(modelName) {
|
|
|
11
11
|
const pendingHasManyQueue = relationships.get('pending');
|
|
12
12
|
const pendingBelongsToQueue = relationships.get('pendingBelongsTo');
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const fn = (sourceRecord, rawData, options) => {
|
|
15
15
|
if (!rawData) return null;
|
|
16
16
|
|
|
17
17
|
const { __name: sourceModelName } = sourceRecord.__model;
|
|
@@ -60,4 +60,7 @@ export default function belongsTo(modelName) {
|
|
|
60
60
|
|
|
61
61
|
return output;
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
fn.__relatedModelName = modelName;
|
|
65
|
+
return fn;
|
|
63
66
|
}
|
package/src/has-many.js
CHANGED
|
@@ -16,7 +16,7 @@ export default function hasMany(modelName) {
|
|
|
16
16
|
const globalRelationships = relationships.get('global');
|
|
17
17
|
const pendingRelationships = relationships.get('pending');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const fn = (sourceRecord, rawData, options) => {
|
|
20
20
|
const { __name: sourceModelName } = sourceRecord.__model;
|
|
21
21
|
const relationshipId = sourceRecord.id;
|
|
22
22
|
const relationship = getRelationships('hasMany', sourceModelName, modelName, relationshipId);
|
|
@@ -58,4 +58,7 @@ export default function hasMany(modelName) {
|
|
|
58
58
|
|
|
59
59
|
return output;
|
|
60
60
|
}
|
|
61
|
+
|
|
62
|
+
fn.__relatedModelName = modelName;
|
|
63
|
+
return fn;
|
|
61
64
|
}
|
package/src/main.js
CHANGED
|
@@ -113,7 +113,7 @@ export default class Orm {
|
|
|
113
113
|
// Wire up memory resolver so store.find() can check model memory flags
|
|
114
114
|
Orm.store._memoryResolver = (modelName) => {
|
|
115
115
|
const { modelClass } = this.getRecordClasses(modelName);
|
|
116
|
-
return modelClass?.memory
|
|
116
|
+
return modelClass?.memory !== false;
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
// Wire up MySQL reference for on-demand queries from store.find()/findAll()
|
package/src/model.js
CHANGED
|
@@ -4,12 +4,12 @@ export default class Model {
|
|
|
4
4
|
/**
|
|
5
5
|
* Controls whether records of this model are loaded into memory on startup.
|
|
6
6
|
*
|
|
7
|
-
* - true → loaded on boot, kept in store
|
|
8
|
-
* - false → never cached; find() always queries MySQL
|
|
7
|
+
* - true → loaded on boot, kept in store (default for backward compatibility)
|
|
8
|
+
* - false → never cached; find() always queries MySQL
|
|
9
9
|
*
|
|
10
|
-
* Override in subclass: static memory =
|
|
10
|
+
* Override in subclass: static memory = false;
|
|
11
11
|
*/
|
|
12
|
-
static memory =
|
|
12
|
+
static memory = true;
|
|
13
13
|
static pluralName = undefined;
|
|
14
14
|
|
|
15
15
|
id = attr('number');
|
|
@@ -7,13 +7,18 @@ import { dbKey } from '../db.js';
|
|
|
7
7
|
function getRelationshipInfo(property) {
|
|
8
8
|
if (typeof property !== 'function') return null;
|
|
9
9
|
const fnStr = property.toString();
|
|
10
|
+
const modelName = property.__relatedModelName || null;
|
|
10
11
|
|
|
11
|
-
if (fnStr.includes(`getRelationships('belongsTo',`)) return 'belongsTo';
|
|
12
|
-
if (fnStr.includes(`getRelationships('hasMany',`)) return 'hasMany';
|
|
12
|
+
if (fnStr.includes(`getRelationships('belongsTo',`)) return { type: 'belongsTo', modelName };
|
|
13
|
+
if (fnStr.includes(`getRelationships('hasMany',`)) return { type: 'hasMany', modelName };
|
|
13
14
|
|
|
14
15
|
return null;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
function sanitizeTableName(name) {
|
|
19
|
+
return name.replace(/\//g, '_');
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
export function introspectModels() {
|
|
18
23
|
const { models } = Orm.instance;
|
|
19
24
|
const schemas = {};
|
|
@@ -34,12 +39,12 @@ export function introspectModels() {
|
|
|
34
39
|
for (const [key, property] of Object.entries(model)) {
|
|
35
40
|
if (key.startsWith('__')) continue;
|
|
36
41
|
|
|
37
|
-
const
|
|
42
|
+
const relInfo = getRelationshipInfo(property);
|
|
38
43
|
|
|
39
|
-
if (
|
|
40
|
-
relationships.belongsTo[key] =
|
|
41
|
-
} else if (
|
|
42
|
-
relationships.hasMany[key] =
|
|
44
|
+
if (relInfo?.type === 'belongsTo') {
|
|
45
|
+
relationships.belongsTo[key] = relInfo.modelName;
|
|
46
|
+
} else if (relInfo?.type === 'hasMany') {
|
|
47
|
+
relationships.hasMany[key] = relInfo.modelName;
|
|
43
48
|
} else if (property?.constructor?.name === 'ModelProperty') {
|
|
44
49
|
if (key === 'id') {
|
|
45
50
|
idType = property.type;
|
|
@@ -50,22 +55,21 @@ export function introspectModels() {
|
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
// Build foreign keys from belongsTo relationships
|
|
53
|
-
for (const relName of Object.
|
|
54
|
-
const modelName = camelCaseToKebabCase(relName);
|
|
58
|
+
for (const [relName, targetModelName] of Object.entries(relationships.belongsTo)) {
|
|
55
59
|
const fkColumn = `${relName}_id`;
|
|
56
60
|
foreignKeys[fkColumn] = {
|
|
57
|
-
references: getPluralName(
|
|
61
|
+
references: sanitizeTableName(getPluralName(targetModelName)),
|
|
58
62
|
column: 'id',
|
|
59
63
|
};
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
schemas[name] = {
|
|
63
|
-
table: getPluralName(name),
|
|
67
|
+
table: sanitizeTableName(getPluralName(name)),
|
|
64
68
|
idType,
|
|
65
69
|
columns,
|
|
66
70
|
foreignKeys,
|
|
67
71
|
relationships,
|
|
68
|
-
memory: modelClass.memory
|
|
72
|
+
memory: modelClass.memory !== false, // default true for backward compat
|
|
69
73
|
};
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -73,7 +77,8 @@ export function introspectModels() {
|
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
export function buildTableDDL(name, schema, allSchemas = {}) {
|
|
76
|
-
const {
|
|
80
|
+
const { idType, columns, foreignKeys } = schema;
|
|
81
|
+
const table = sanitizeTableName(schema.table);
|
|
77
82
|
const lines = [];
|
|
78
83
|
|
|
79
84
|
// Primary key
|
|
@@ -100,7 +105,8 @@ export function buildTableDDL(name, schema, allSchemas = {}) {
|
|
|
100
105
|
|
|
101
106
|
// Foreign key constraints
|
|
102
107
|
for (const [fkCol, fkDef] of Object.entries(foreignKeys)) {
|
|
103
|
-
|
|
108
|
+
const refTable = sanitizeTableName(fkDef.references);
|
|
109
|
+
lines.push(` FOREIGN KEY (\`${fkCol}\`) REFERENCES \`${refTable}\`(\`${fkDef.column}\`) ON DELETE SET NULL`);
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
return `CREATE TABLE IF NOT EXISTS \`${table}\` (\n${lines.join(',\n')}\n)`;
|
|
@@ -130,8 +136,8 @@ export function getTopologicalOrder(schemas) {
|
|
|
130
136
|
if (!schema) return;
|
|
131
137
|
|
|
132
138
|
// Visit dependencies (belongsTo targets) first
|
|
133
|
-
for (const
|
|
134
|
-
visit(
|
|
139
|
+
for (const targetModelName of Object.values(schema.relationships.belongsTo)) {
|
|
140
|
+
visit(targetModelName);
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
order.push(name);
|
package/src/store.js
CHANGED
|
@@ -117,7 +117,7 @@ export default class Store {
|
|
|
117
117
|
*/
|
|
118
118
|
_isMemoryModel(modelName) {
|
|
119
119
|
if (this._memoryResolver) return this._memoryResolver(modelName);
|
|
120
|
-
return
|
|
120
|
+
return true; // default to memory if resolver not set yet
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
set(key, value) {
|