outlet-orm 9.0.2 → 11.1.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 +103 -5
- package/bin/reverse.js +0 -1
- package/package.json +1 -1
- package/skills/outlet-orm/ADVANCED.md +29 -0
- package/skills/outlet-orm/AI.md +23 -23
- package/skills/outlet-orm/API.md +33 -3
- package/skills/outlet-orm/MODELS.md +144 -2
- package/skills/outlet-orm/QUERIES.md +136 -3
- package/skills/outlet-orm/RELATIONS.md +44 -0
- package/skills/outlet-orm/SEEDS.md +2 -2
- package/skills/outlet-orm/SKILL.md +8 -6
- package/skills/outlet-orm/TYPESCRIPT.md +98 -0
- package/src/AI/{AiBridgeManager.js → AIManager.js} +61 -61
- package/src/AI/AIPromptEnhancer.js +1 -1
- package/src/AI/AIQueryBuilder.js +4 -4
- package/src/AI/AIQueryOptimizer.js +3 -3
- package/src/AI/AISeeder.js +1 -1
- package/src/AI/Builders/TextBuilder.js +2 -2
- package/src/AI/Contracts/AudioProviderContract.js +2 -2
- package/src/AI/Contracts/ChatProviderContract.js +3 -2
- package/src/AI/Contracts/EmbeddingsProviderContract.js +1 -1
- package/src/AI/Contracts/ImageProviderContract.js +1 -1
- package/src/AI/Contracts/ModelsProviderContract.js +1 -1
- package/src/AI/Contracts/ToolContract.js +1 -1
- package/src/AI/Facades/{AiBridge.js → AI.js} +11 -11
- package/src/AI/MCPServer.js +16 -16
- package/src/AI/Providers/CustomOpenAIProvider.js +0 -2
- package/src/AI/Providers/GeminiProvider.js +2 -2
- package/src/AI/Providers/OpenAIProvider.js +0 -5
- package/src/AI/Support/DocumentAttachmentMapper.js +37 -37
- package/src/AI/Support/FileSecurity.js +1 -1
- package/src/AI/Support/ToolChatRunner.js +1 -1
- package/src/Backup/BackupManager.js +6 -6
- package/src/Backup/BackupScheduler.js +1 -1
- package/src/Backup/BackupSocketServer.js +2 -2
- package/src/DatabaseConnection.js +51 -0
- package/src/Model.js +245 -5
- package/src/QueryBuilder.js +191 -0
- package/src/Relations/HasOneRelation.js +114 -114
- package/src/Relations/HasOneThroughRelation.js +105 -105
- package/src/Relations/MorphOneRelation.js +4 -2
- package/src/Relations/Relation.js +35 -0
- package/src/index.js +6 -6
- package/types/index.d.ts +78 -12
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
const Relation = require('./Relation');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Has One Relation
|
|
5
|
-
* Represents a one-to-one relationship
|
|
6
|
-
*/
|
|
7
|
-
class HasOneRelation extends Relation {
|
|
8
|
-
/**
|
|
9
|
-
* Get the related model
|
|
10
|
-
* @returns {Promise<Model|null>}
|
|
11
|
-
*/
|
|
12
|
-
async get() {
|
|
13
|
-
const result = await this.related
|
|
14
|
-
.where(this.foreignKey, this.parent.getAttribute(this.localKey))
|
|
15
|
-
.first();
|
|
16
|
-
|
|
17
|
-
return result;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Eager load the relationship for a collection of parent models
|
|
22
|
-
* @param {Array<Model>} models
|
|
23
|
-
* @param {string} relationName
|
|
24
|
-
* @returns {Promise<void>}
|
|
25
|
-
*/
|
|
26
|
-
async eagerLoad(models, relationName, constraint) {
|
|
27
|
-
const keys = models
|
|
28
|
-
.map(model => model.getAttribute(this.localKey))
|
|
29
|
-
.filter(key => key !== null && key !== undefined);
|
|
30
|
-
|
|
31
|
-
if (keys.length === 0) return;
|
|
32
|
-
|
|
33
|
-
const qb = this.related.whereIn(this.foreignKey, keys);
|
|
34
|
-
if (typeof constraint === 'function') constraint(qb);
|
|
35
|
-
const relatedModels = await qb.get();
|
|
36
|
-
|
|
37
|
-
const relatedMap = {};
|
|
38
|
-
relatedModels.forEach(model => {
|
|
39
|
-
const foreignKeyValue = model.getAttribute(this.foreignKey);
|
|
40
|
-
relatedMap[foreignKeyValue] = model;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
models.forEach(model => {
|
|
44
|
-
const localKeyValue = model.getAttribute(this.localKey);
|
|
45
|
-
model.relations[relationName] = relatedMap[localKeyValue] ||
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Add a where clause to the relation query
|
|
51
|
-
* @param {string} column
|
|
52
|
-
* @param {string|any} operator
|
|
53
|
-
* @param {any} value
|
|
54
|
-
* @returns {QueryBuilder}
|
|
55
|
-
*/
|
|
56
|
-
where(column, operator, value) {
|
|
57
|
-
return this.related
|
|
58
|
-
.where(this.foreignKey, this.parent.getAttribute(this.localKey))
|
|
59
|
-
.where(column, operator, value);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Create a new related model and associate it
|
|
64
|
-
* @param {Object} attributes
|
|
65
|
-
* @returns {Promise<Model>}
|
|
66
|
-
*/
|
|
67
|
-
async create(attributes = {}) {
|
|
68
|
-
const model = new this.related.model(attributes);
|
|
69
|
-
model.setAttribute(this.foreignKey, this.parent.getAttribute(this.localKey));
|
|
70
|
-
await model.save();
|
|
71
|
-
return model;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Save an existing model and associate it
|
|
76
|
-
* @param {Model} model
|
|
77
|
-
* @returns {Promise<Model>}
|
|
78
|
-
*/
|
|
79
|
-
async save(model) {
|
|
80
|
-
model.setAttribute(this.foreignKey, this.parent.getAttribute(this.localKey));
|
|
81
|
-
await model.save();
|
|
82
|
-
return model;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Create multiple related models and associate them
|
|
87
|
-
* @param {Array<Object>} attributesArray
|
|
88
|
-
* @returns {Promise<Array<Model>>}
|
|
89
|
-
*/
|
|
90
|
-
async createMany(attributesArray) {
|
|
91
|
-
const models = [];
|
|
92
|
-
for (const attributes of attributesArray) {
|
|
93
|
-
const model = await this.create(attributes);
|
|
94
|
-
models.push(model);
|
|
95
|
-
}
|
|
96
|
-
return models;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Save multiple existing models and associate them
|
|
101
|
-
* @param {Array<Model>} models
|
|
102
|
-
* @returns {Promise<Array<Model>>}
|
|
103
|
-
*/
|
|
104
|
-
async saveMany(models) {
|
|
105
|
-
const savedModels = [];
|
|
106
|
-
for (const model of models) {
|
|
107
|
-
const saved = await this.save(model);
|
|
108
|
-
savedModels.push(saved);
|
|
109
|
-
}
|
|
110
|
-
return savedModels;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
module.exports = HasOneRelation;
|
|
1
|
+
const Relation = require('./Relation');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Has One Relation
|
|
5
|
+
* Represents a one-to-one relationship
|
|
6
|
+
*/
|
|
7
|
+
class HasOneRelation extends Relation {
|
|
8
|
+
/**
|
|
9
|
+
* Get the related model
|
|
10
|
+
* @returns {Promise<Model|null>}
|
|
11
|
+
*/
|
|
12
|
+
async get() {
|
|
13
|
+
const result = await this.related
|
|
14
|
+
.where(this.foreignKey, this.parent.getAttribute(this.localKey))
|
|
15
|
+
.first();
|
|
16
|
+
|
|
17
|
+
return result || this._buildDefault();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Eager load the relationship for a collection of parent models
|
|
22
|
+
* @param {Array<Model>} models
|
|
23
|
+
* @param {string} relationName
|
|
24
|
+
* @returns {Promise<void>}
|
|
25
|
+
*/
|
|
26
|
+
async eagerLoad(models, relationName, constraint) {
|
|
27
|
+
const keys = models
|
|
28
|
+
.map(model => model.getAttribute(this.localKey))
|
|
29
|
+
.filter(key => key !== null && key !== undefined);
|
|
30
|
+
|
|
31
|
+
if (keys.length === 0) return;
|
|
32
|
+
|
|
33
|
+
const qb = this.related.whereIn(this.foreignKey, keys);
|
|
34
|
+
if (typeof constraint === 'function') constraint(qb);
|
|
35
|
+
const relatedModels = await qb.get();
|
|
36
|
+
|
|
37
|
+
const relatedMap = {};
|
|
38
|
+
relatedModels.forEach(model => {
|
|
39
|
+
const foreignKeyValue = model.getAttribute(this.foreignKey);
|
|
40
|
+
relatedMap[foreignKeyValue] = model;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
models.forEach(model => {
|
|
44
|
+
const localKeyValue = model.getAttribute(this.localKey);
|
|
45
|
+
model.relations[relationName] = relatedMap[localKeyValue] || this._buildDefault();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Add a where clause to the relation query
|
|
51
|
+
* @param {string} column
|
|
52
|
+
* @param {string|any} operator
|
|
53
|
+
* @param {any} value
|
|
54
|
+
* @returns {QueryBuilder}
|
|
55
|
+
*/
|
|
56
|
+
where(column, operator, value) {
|
|
57
|
+
return this.related
|
|
58
|
+
.where(this.foreignKey, this.parent.getAttribute(this.localKey))
|
|
59
|
+
.where(column, operator, value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a new related model and associate it
|
|
64
|
+
* @param {Object} attributes
|
|
65
|
+
* @returns {Promise<Model>}
|
|
66
|
+
*/
|
|
67
|
+
async create(attributes = {}) {
|
|
68
|
+
const model = new this.related.model(attributes);
|
|
69
|
+
model.setAttribute(this.foreignKey, this.parent.getAttribute(this.localKey));
|
|
70
|
+
await model.save();
|
|
71
|
+
return model;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Save an existing model and associate it
|
|
76
|
+
* @param {Model} model
|
|
77
|
+
* @returns {Promise<Model>}
|
|
78
|
+
*/
|
|
79
|
+
async save(model) {
|
|
80
|
+
model.setAttribute(this.foreignKey, this.parent.getAttribute(this.localKey));
|
|
81
|
+
await model.save();
|
|
82
|
+
return model;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create multiple related models and associate them
|
|
87
|
+
* @param {Array<Object>} attributesArray
|
|
88
|
+
* @returns {Promise<Array<Model>>}
|
|
89
|
+
*/
|
|
90
|
+
async createMany(attributesArray) {
|
|
91
|
+
const models = [];
|
|
92
|
+
for (const attributes of attributesArray) {
|
|
93
|
+
const model = await this.create(attributes);
|
|
94
|
+
models.push(model);
|
|
95
|
+
}
|
|
96
|
+
return models;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Save multiple existing models and associate them
|
|
101
|
+
* @param {Array<Model>} models
|
|
102
|
+
* @returns {Promise<Array<Model>>}
|
|
103
|
+
*/
|
|
104
|
+
async saveMany(models) {
|
|
105
|
+
const savedModels = [];
|
|
106
|
+
for (const model of models) {
|
|
107
|
+
const saved = await this.save(model);
|
|
108
|
+
savedModels.push(saved);
|
|
109
|
+
}
|
|
110
|
+
return savedModels;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = HasOneRelation;
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
const Relation = require('./Relation');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Has One Through Relation
|
|
5
|
-
* parent -> through -> related (final) - returns single model
|
|
6
|
-
*/
|
|
7
|
-
class HasOneThroughRelation extends Relation {
|
|
8
|
-
/**
|
|
9
|
-
* @param {import('../Model')} parent
|
|
10
|
-
* @param {typeof import('../Model')} relatedFinal
|
|
11
|
-
* @param {typeof import('../Model')} through
|
|
12
|
-
* @param {string} [foreignKeyOnThrough] - FK on through referencing parent
|
|
13
|
-
* @param {string} [throughKeyOnFinal] - FK on final referencing through
|
|
14
|
-
* @param {string} [localKey] - PK on parent
|
|
15
|
-
* @param {string} [throughLocalKey] - PK on through
|
|
16
|
-
*/
|
|
17
|
-
constructor(parent, relatedFinal, through, foreignKeyOnThrough, throughKeyOnFinal, localKey, throughLocalKey) {
|
|
18
|
-
super(parent, relatedFinal, foreignKeyOnThrough, localKey);
|
|
19
|
-
this.through = through;
|
|
20
|
-
// Defaults based on naming conventions
|
|
21
|
-
this.localKey = localKey || parent.constructor.primaryKey || 'id';
|
|
22
|
-
this.throughLocalKey = throughLocalKey || through.primaryKey || 'id';
|
|
23
|
-
this.foreignKeyOnThrough = foreignKeyOnThrough || `${parent.constructor.table.slice(0, -1)}_id`;
|
|
24
|
-
this.throughKeyOnFinal = throughKeyOnFinal || `${through.table.slice(0, -1)}_id`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Get final related model (single)
|
|
29
|
-
* @returns {Promise<import('../Model')|null>}
|
|
30
|
-
*/
|
|
31
|
-
async get() {
|
|
32
|
-
const parentKeyValue = this.parent.getAttribute(this.localKey);
|
|
33
|
-
if (parentKeyValue === undefined || parentKeyValue === null) return
|
|
34
|
-
|
|
35
|
-
const throughRow = await this.through
|
|
36
|
-
.where(this.foreignKeyOnThrough, parentKeyValue)
|
|
37
|
-
.first();
|
|
38
|
-
|
|
39
|
-
if (!throughRow) return
|
|
40
|
-
|
|
41
|
-
const throughId = throughRow.getAttribute(this.throughLocalKey);
|
|
42
|
-
const result = await this.related
|
|
43
|
-
.where(this.throughKeyOnFinal, throughId)
|
|
44
|
-
.first();
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Eager load hasOneThrough for a batch of parents
|
|
50
|
-
* @param {Array} models
|
|
51
|
-
* @param {string} relationName
|
|
52
|
-
* @param {(qb: any) => void} [constraint]
|
|
53
|
-
*/
|
|
54
|
-
async eagerLoad(models, relationName, constraint) {
|
|
55
|
-
const parentKeys = models
|
|
56
|
-
.map(m => m.getAttribute(this.localKey))
|
|
57
|
-
.filter(v => v !== undefined && v !== null);
|
|
58
|
-
|
|
59
|
-
if (parentKeys.length === 0) {
|
|
60
|
-
models.forEach(m => { m.relations[relationName] = null; });
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Fetch through rows for all parent keys
|
|
65
|
-
const throughRows = await this.through
|
|
66
|
-
.whereIn(this.foreignKeyOnThrough, parentKeys)
|
|
67
|
-
.get();
|
|
68
|
-
|
|
69
|
-
if (throughRows.length === 0) {
|
|
70
|
-
models.forEach(m => { m.relations[relationName] = null; });
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Map parentKey -> throughId (assuming one through per parent)
|
|
75
|
-
const parentToThroughId = {};
|
|
76
|
-
for (const row of throughRows) {
|
|
77
|
-
const pKey = row.getAttribute(this.foreignKeyOnThrough);
|
|
78
|
-
const tId = row.getAttribute(this.throughLocalKey);
|
|
79
|
-
parentToThroughId[pKey] = tId; // overwrite if multiple, take last
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const allThroughIds = Object.values(parentToThroughId);
|
|
83
|
-
|
|
84
|
-
// Fetch finals in one query (with optional constraint)
|
|
85
|
-
const qb = this.related.whereIn(this.throughKeyOnFinal, allThroughIds);
|
|
86
|
-
if (typeof constraint === 'function') constraint(qb);
|
|
87
|
-
const finals = await qb.get();
|
|
88
|
-
|
|
89
|
-
// Map through id to final
|
|
90
|
-
const finalsByThrough = {};
|
|
91
|
-
for (const f of finals) {
|
|
92
|
-
const key = f.getAttribute(this.throughKeyOnFinal);
|
|
93
|
-
finalsByThrough[key] = f; // assume one per through
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Assign to each parent
|
|
97
|
-
for (const m of models) {
|
|
98
|
-
const pKey = m.getAttribute(this.localKey);
|
|
99
|
-
const tId = parentToThroughId[pKey];
|
|
100
|
-
m.relations[relationName] = tId ? finalsByThrough[tId] || null : null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = HasOneThroughRelation;
|
|
1
|
+
const Relation = require('./Relation');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Has One Through Relation
|
|
5
|
+
* parent -> through -> related (final) - returns single model
|
|
6
|
+
*/
|
|
7
|
+
class HasOneThroughRelation extends Relation {
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('../Model')} parent
|
|
10
|
+
* @param {typeof import('../Model')} relatedFinal
|
|
11
|
+
* @param {typeof import('../Model')} through
|
|
12
|
+
* @param {string} [foreignKeyOnThrough] - FK on through referencing parent
|
|
13
|
+
* @param {string} [throughKeyOnFinal] - FK on final referencing through
|
|
14
|
+
* @param {string} [localKey] - PK on parent
|
|
15
|
+
* @param {string} [throughLocalKey] - PK on through
|
|
16
|
+
*/
|
|
17
|
+
constructor(parent, relatedFinal, through, foreignKeyOnThrough, throughKeyOnFinal, localKey, throughLocalKey) {
|
|
18
|
+
super(parent, relatedFinal, foreignKeyOnThrough, localKey);
|
|
19
|
+
this.through = through;
|
|
20
|
+
// Defaults based on naming conventions
|
|
21
|
+
this.localKey = localKey || parent.constructor.primaryKey || 'id';
|
|
22
|
+
this.throughLocalKey = throughLocalKey || through.primaryKey || 'id';
|
|
23
|
+
this.foreignKeyOnThrough = foreignKeyOnThrough || `${parent.constructor.table.slice(0, -1)}_id`;
|
|
24
|
+
this.throughKeyOnFinal = throughKeyOnFinal || `${through.table.slice(0, -1)}_id`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get final related model (single)
|
|
29
|
+
* @returns {Promise<import('../Model')|null>}
|
|
30
|
+
*/
|
|
31
|
+
async get() {
|
|
32
|
+
const parentKeyValue = this.parent.getAttribute(this.localKey);
|
|
33
|
+
if (parentKeyValue === undefined || parentKeyValue === null) return this._buildDefault();
|
|
34
|
+
|
|
35
|
+
const throughRow = await this.through
|
|
36
|
+
.where(this.foreignKeyOnThrough, parentKeyValue)
|
|
37
|
+
.first();
|
|
38
|
+
|
|
39
|
+
if (!throughRow) return this._buildDefault();
|
|
40
|
+
|
|
41
|
+
const throughId = throughRow.getAttribute(this.throughLocalKey);
|
|
42
|
+
const result = await this.related
|
|
43
|
+
.where(this.throughKeyOnFinal, throughId)
|
|
44
|
+
.first();
|
|
45
|
+
return result || this._buildDefault();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Eager load hasOneThrough for a batch of parents
|
|
50
|
+
* @param {Array} models
|
|
51
|
+
* @param {string} relationName
|
|
52
|
+
* @param {(qb: any) => void} [constraint]
|
|
53
|
+
*/
|
|
54
|
+
async eagerLoad(models, relationName, constraint) {
|
|
55
|
+
const parentKeys = models
|
|
56
|
+
.map(m => m.getAttribute(this.localKey))
|
|
57
|
+
.filter(v => v !== undefined && v !== null);
|
|
58
|
+
|
|
59
|
+
if (parentKeys.length === 0) {
|
|
60
|
+
models.forEach(m => { m.relations[relationName] = null; });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Fetch through rows for all parent keys
|
|
65
|
+
const throughRows = await this.through
|
|
66
|
+
.whereIn(this.foreignKeyOnThrough, parentKeys)
|
|
67
|
+
.get();
|
|
68
|
+
|
|
69
|
+
if (throughRows.length === 0) {
|
|
70
|
+
models.forEach(m => { m.relations[relationName] = null; });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Map parentKey -> throughId (assuming one through per parent)
|
|
75
|
+
const parentToThroughId = {};
|
|
76
|
+
for (const row of throughRows) {
|
|
77
|
+
const pKey = row.getAttribute(this.foreignKeyOnThrough);
|
|
78
|
+
const tId = row.getAttribute(this.throughLocalKey);
|
|
79
|
+
parentToThroughId[pKey] = tId; // overwrite if multiple, take last
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const allThroughIds = Object.values(parentToThroughId);
|
|
83
|
+
|
|
84
|
+
// Fetch finals in one query (with optional constraint)
|
|
85
|
+
const qb = this.related.whereIn(this.throughKeyOnFinal, allThroughIds);
|
|
86
|
+
if (typeof constraint === 'function') constraint(qb);
|
|
87
|
+
const finals = await qb.get();
|
|
88
|
+
|
|
89
|
+
// Map through id to final
|
|
90
|
+
const finalsByThrough = {};
|
|
91
|
+
for (const f of finals) {
|
|
92
|
+
const key = f.getAttribute(this.throughKeyOnFinal);
|
|
93
|
+
finalsByThrough[key] = f; // assume one per through
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Assign to each parent
|
|
97
|
+
for (const m of models) {
|
|
98
|
+
const pKey = m.getAttribute(this.localKey);
|
|
99
|
+
const tId = parentToThroughId[pKey];
|
|
100
|
+
m.relations[relationName] = tId ? finalsByThrough[tId] || null : null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = HasOneThroughRelation;
|
|
@@ -16,10 +16,12 @@ class MorphOneRelation extends Relation {
|
|
|
16
16
|
* @returns {Promise<Model|null>}
|
|
17
17
|
*/
|
|
18
18
|
async get() {
|
|
19
|
-
|
|
19
|
+
const result = await this.related
|
|
20
20
|
.where(this.foreignKey, this.parent.getAttribute(this.localKey))
|
|
21
21
|
.where(`${this.morphType}_type`, this.parent.constructor.table)
|
|
22
22
|
.first();
|
|
23
|
+
|
|
24
|
+
return result || this._buildDefault();
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -46,7 +48,7 @@ class MorphOneRelation extends Relation {
|
|
|
46
48
|
|
|
47
49
|
for (const model of models) {
|
|
48
50
|
const key = model.getAttribute(this.localKey);
|
|
49
|
-
model.relations[relationName] = relatedMap[key] ||
|
|
51
|
+
model.relations[relationName] = relatedMap[key] || this._buildDefault();
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -7,6 +7,41 @@ class Relation {
|
|
|
7
7
|
this.related = related;
|
|
8
8
|
this.foreignKey = foreignKey;
|
|
9
9
|
this.localKey = localKey;
|
|
10
|
+
this._defaultValue = undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Set a default value/model to return when the relation is empty
|
|
15
|
+
* @param {Object|Function|boolean} [value=true] - Default attributes, factory fn, or true for empty model
|
|
16
|
+
* @returns {this}
|
|
17
|
+
*/
|
|
18
|
+
withDefault(value = true) {
|
|
19
|
+
this._defaultValue = value;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Build the default model when the relation result is null
|
|
25
|
+
* @returns {Model|null}
|
|
26
|
+
* @protected
|
|
27
|
+
*/
|
|
28
|
+
_buildDefault() {
|
|
29
|
+
if (this._defaultValue === undefined) return null;
|
|
30
|
+
if (typeof this._defaultValue === 'function') return this._defaultValue();
|
|
31
|
+
if (this._defaultValue === true) {
|
|
32
|
+
// Return an empty instance of the related model
|
|
33
|
+
const RelatedModel = typeof this.related === 'function' && this.related.prototype
|
|
34
|
+
? this.related
|
|
35
|
+
: this.related.constructor;
|
|
36
|
+
return new RelatedModel();
|
|
37
|
+
}
|
|
38
|
+
if (typeof this._defaultValue === 'object' && this._defaultValue !== null) {
|
|
39
|
+
const RelatedModel = typeof this.related === 'function' && this.related.prototype
|
|
40
|
+
? this.related
|
|
41
|
+
: this.related.constructor;
|
|
42
|
+
return new RelatedModel(this._defaultValue);
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
10
45
|
}
|
|
11
46
|
|
|
12
47
|
/**
|
package/src/index.js
CHANGED
|
@@ -33,9 +33,9 @@ const MCPServer = require('./AI/MCPServer');
|
|
|
33
33
|
const AISafetyGuardrails = require('./AI/AISafetyGuardrails');
|
|
34
34
|
const PromptGenerator = require('./AI/PromptGenerator');
|
|
35
35
|
|
|
36
|
-
// AI
|
|
37
|
-
const
|
|
38
|
-
const
|
|
36
|
+
// AI (v8.0.0) — Multi-provider LLM abstraction
|
|
37
|
+
const AIManager = require('./AI/AIManager');
|
|
38
|
+
const AIFacade = require('./AI/Facades/AI');
|
|
39
39
|
const TextBuilder = require('./AI/Builders/TextBuilder');
|
|
40
40
|
const ChatProviderContract = require('./AI/Contracts/ChatProviderContract');
|
|
41
41
|
const EmbeddingsProviderContract = require('./AI/Contracts/EmbeddingsProviderContract');
|
|
@@ -110,9 +110,9 @@ module.exports = {
|
|
|
110
110
|
AISafetyGuardrails,
|
|
111
111
|
PromptGenerator,
|
|
112
112
|
|
|
113
|
-
// AI
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
// AI (v8.0.0)
|
|
114
|
+
AIManager,
|
|
115
|
+
AIFacade,
|
|
116
116
|
TextBuilder,
|
|
117
117
|
ChatProviderContract,
|
|
118
118
|
EmbeddingsProviderContract,
|