arkormx 2.0.0-next.22 → 2.0.0-next.24
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/dist/index.cjs +71 -5
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +71 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6010,7 +6010,7 @@ var RelationTableLoader = class {
|
|
|
6010
6010
|
* @author Legacy (3m1n3nc3)
|
|
6011
6011
|
* @since 2.0.0-next.2
|
|
6012
6012
|
*/
|
|
6013
|
-
var SetBasedEagerLoader = class {
|
|
6013
|
+
var SetBasedEagerLoader = class SetBasedEagerLoader {
|
|
6014
6014
|
constructor(models, relations) {
|
|
6015
6015
|
this.models = models;
|
|
6016
6016
|
this.relations = relations;
|
|
@@ -6022,10 +6022,18 @@ var SetBasedEagerLoader = class {
|
|
|
6022
6022
|
*/
|
|
6023
6023
|
async load() {
|
|
6024
6024
|
if (this.models.length === 0) return;
|
|
6025
|
-
|
|
6026
|
-
|
|
6025
|
+
const relationTree = this.buildRelationTree(this.relations);
|
|
6026
|
+
await Promise.all(Array.from(relationTree.entries()).map(async ([name, node]) => {
|
|
6027
|
+
await this.loadRelationNode(name, node);
|
|
6027
6028
|
}));
|
|
6028
6029
|
}
|
|
6030
|
+
async loadRelationNode(name, node) {
|
|
6031
|
+
await this.loadRelation(name, node.constraint);
|
|
6032
|
+
if (node.children.size === 0) return;
|
|
6033
|
+
const relatedModels = this.collectLoadedRelationModels(name);
|
|
6034
|
+
if (relatedModels.length === 0) return;
|
|
6035
|
+
await new SetBasedEagerLoader(relatedModels, this.relationTreeToMap(node.children)).load();
|
|
6036
|
+
}
|
|
6029
6037
|
/**
|
|
6030
6038
|
* Loads a specific relationship for the set of models based on the relationship name
|
|
6031
6039
|
* and an optional constraint.
|
|
@@ -6069,9 +6077,58 @@ var SetBasedEagerLoader = class {
|
|
|
6069
6077
|
*/
|
|
6070
6078
|
resolveRelationResolver(name) {
|
|
6071
6079
|
const resolver = this.models[0][name];
|
|
6072
|
-
if (typeof resolver !== "function")
|
|
6080
|
+
if (typeof resolver !== "function") {
|
|
6081
|
+
const modelName = this.models[0].constructor?.name ?? "Model";
|
|
6082
|
+
throw new RelationResolutionException(`Relation [${name}] is not defined on the model.`, {
|
|
6083
|
+
operation: "eagerLoad",
|
|
6084
|
+
model: modelName,
|
|
6085
|
+
relation: name
|
|
6086
|
+
});
|
|
6087
|
+
}
|
|
6073
6088
|
return resolver;
|
|
6074
6089
|
}
|
|
6090
|
+
buildRelationTree(relations) {
|
|
6091
|
+
const tree = /* @__PURE__ */ new Map();
|
|
6092
|
+
Object.entries(relations).forEach(([path, constraint]) => {
|
|
6093
|
+
const segments = path.split(".").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
6094
|
+
if (segments.length === 0) return;
|
|
6095
|
+
let current = tree;
|
|
6096
|
+
segments.forEach((segment, index) => {
|
|
6097
|
+
const existing = current.get(segment) ?? {
|
|
6098
|
+
constraint: void 0,
|
|
6099
|
+
children: /* @__PURE__ */ new Map()
|
|
6100
|
+
};
|
|
6101
|
+
if (index === segments.length - 1 && constraint) existing.constraint = constraint;
|
|
6102
|
+
current.set(segment, existing);
|
|
6103
|
+
current = existing.children;
|
|
6104
|
+
});
|
|
6105
|
+
});
|
|
6106
|
+
return tree;
|
|
6107
|
+
}
|
|
6108
|
+
relationTreeToMap(tree, prefix = "") {
|
|
6109
|
+
return Array.from(tree.entries()).reduce((all, [name, node]) => {
|
|
6110
|
+
const path = prefix ? `${prefix}.${name}` : name;
|
|
6111
|
+
all[path] = node.constraint;
|
|
6112
|
+
Object.assign(all, this.relationTreeToMap(node.children, path));
|
|
6113
|
+
return all;
|
|
6114
|
+
}, {});
|
|
6115
|
+
}
|
|
6116
|
+
collectLoadedRelationModels(name) {
|
|
6117
|
+
return this.models.reduce((all, model) => {
|
|
6118
|
+
const loaded = model.getAttribute(name);
|
|
6119
|
+
if (loaded instanceof ArkormCollection) {
|
|
6120
|
+
loaded.all().forEach((item) => {
|
|
6121
|
+
if (this.isEagerLoadableModel(item)) all.push(item);
|
|
6122
|
+
});
|
|
6123
|
+
return all;
|
|
6124
|
+
}
|
|
6125
|
+
if (this.isEagerLoadableModel(loaded)) all.push(loaded);
|
|
6126
|
+
return all;
|
|
6127
|
+
}, []);
|
|
6128
|
+
}
|
|
6129
|
+
isEagerLoadableModel(value) {
|
|
6130
|
+
return typeof value === "object" && value !== null && typeof value.getAttribute === "function" && typeof value.setLoadedRelation === "function";
|
|
6131
|
+
}
|
|
6075
6132
|
/**
|
|
6076
6133
|
* Loads a "belongs to" relationship for the set of models.
|
|
6077
6134
|
*
|
|
@@ -7536,12 +7593,14 @@ var QueryBuilder = class QueryBuilder {
|
|
|
7536
7593
|
* @returns
|
|
7537
7594
|
*/
|
|
7538
7595
|
async updateOrInsert(attributes, values = {}) {
|
|
7539
|
-
if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") {
|
|
7596
|
+
if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") try {
|
|
7540
7597
|
await this.executeUpsertRows([{
|
|
7541
7598
|
...attributes,
|
|
7542
7599
|
...values
|
|
7543
7600
|
}], Object.keys(attributes), Object.keys(values));
|
|
7544
7601
|
return true;
|
|
7602
|
+
} catch (error) {
|
|
7603
|
+
if (!this.shouldFallbackUpdateOrInsertUpsert(error)) throw error;
|
|
7545
7604
|
}
|
|
7546
7605
|
const exists = await this.clone().where(attributes).first() != null;
|
|
7547
7606
|
const resolvedValues = typeof values === "function" ? await values(exists) : values;
|
|
@@ -7554,6 +7613,13 @@ var QueryBuilder = class QueryBuilder {
|
|
|
7554
7613
|
}
|
|
7555
7614
|
return await this.clone().where(attributes).update(resolvedValues) != null;
|
|
7556
7615
|
}
|
|
7616
|
+
shouldFallbackUpdateOrInsertUpsert(error) {
|
|
7617
|
+
if (!(error instanceof QueryExecutionException)) return false;
|
|
7618
|
+
const cause = error.cause;
|
|
7619
|
+
const code = typeof cause?.code === "string" ? cause.code : void 0;
|
|
7620
|
+
const message = typeof cause?.message === "string" ? cause.message : error.message;
|
|
7621
|
+
return code === "42P10" || message.includes("there is no unique or exclusion constraint matching the ON CONFLICT specification");
|
|
7622
|
+
}
|
|
7557
7623
|
/**
|
|
7558
7624
|
* Insert new records or update existing records by one or more unique keys.
|
|
7559
7625
|
*
|
package/dist/index.d.cts
CHANGED
|
@@ -2687,6 +2687,7 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
|
|
|
2687
2687
|
* @returns
|
|
2688
2688
|
*/
|
|
2689
2689
|
updateOrInsert(attributes: Record<string, unknown>, values?: Record<string, unknown> | ((exists: boolean) => Record<string, unknown> | Promise<Record<string, unknown>>)): Promise<boolean>;
|
|
2690
|
+
private shouldFallbackUpdateOrInsertUpsert;
|
|
2690
2691
|
/**
|
|
2691
2692
|
* Insert new records or update existing records by one or more unique keys.
|
|
2692
2693
|
*
|
package/dist/index.d.mts
CHANGED
|
@@ -2687,6 +2687,7 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
|
|
|
2687
2687
|
* @returns
|
|
2688
2688
|
*/
|
|
2689
2689
|
updateOrInsert(attributes: Record<string, unknown>, values?: Record<string, unknown> | ((exists: boolean) => Record<string, unknown> | Promise<Record<string, unknown>>)): Promise<boolean>;
|
|
2690
|
+
private shouldFallbackUpdateOrInsertUpsert;
|
|
2690
2691
|
/**
|
|
2691
2692
|
* Insert new records or update existing records by one or more unique keys.
|
|
2692
2693
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -5981,7 +5981,7 @@ var RelationTableLoader = class {
|
|
|
5981
5981
|
* @author Legacy (3m1n3nc3)
|
|
5982
5982
|
* @since 2.0.0-next.2
|
|
5983
5983
|
*/
|
|
5984
|
-
var SetBasedEagerLoader = class {
|
|
5984
|
+
var SetBasedEagerLoader = class SetBasedEagerLoader {
|
|
5985
5985
|
constructor(models, relations) {
|
|
5986
5986
|
this.models = models;
|
|
5987
5987
|
this.relations = relations;
|
|
@@ -5993,10 +5993,18 @@ var SetBasedEagerLoader = class {
|
|
|
5993
5993
|
*/
|
|
5994
5994
|
async load() {
|
|
5995
5995
|
if (this.models.length === 0) return;
|
|
5996
|
-
|
|
5997
|
-
|
|
5996
|
+
const relationTree = this.buildRelationTree(this.relations);
|
|
5997
|
+
await Promise.all(Array.from(relationTree.entries()).map(async ([name, node]) => {
|
|
5998
|
+
await this.loadRelationNode(name, node);
|
|
5998
5999
|
}));
|
|
5999
6000
|
}
|
|
6001
|
+
async loadRelationNode(name, node) {
|
|
6002
|
+
await this.loadRelation(name, node.constraint);
|
|
6003
|
+
if (node.children.size === 0) return;
|
|
6004
|
+
const relatedModels = this.collectLoadedRelationModels(name);
|
|
6005
|
+
if (relatedModels.length === 0) return;
|
|
6006
|
+
await new SetBasedEagerLoader(relatedModels, this.relationTreeToMap(node.children)).load();
|
|
6007
|
+
}
|
|
6000
6008
|
/**
|
|
6001
6009
|
* Loads a specific relationship for the set of models based on the relationship name
|
|
6002
6010
|
* and an optional constraint.
|
|
@@ -6040,9 +6048,58 @@ var SetBasedEagerLoader = class {
|
|
|
6040
6048
|
*/
|
|
6041
6049
|
resolveRelationResolver(name) {
|
|
6042
6050
|
const resolver = this.models[0][name];
|
|
6043
|
-
if (typeof resolver !== "function")
|
|
6051
|
+
if (typeof resolver !== "function") {
|
|
6052
|
+
const modelName = this.models[0].constructor?.name ?? "Model";
|
|
6053
|
+
throw new RelationResolutionException(`Relation [${name}] is not defined on the model.`, {
|
|
6054
|
+
operation: "eagerLoad",
|
|
6055
|
+
model: modelName,
|
|
6056
|
+
relation: name
|
|
6057
|
+
});
|
|
6058
|
+
}
|
|
6044
6059
|
return resolver;
|
|
6045
6060
|
}
|
|
6061
|
+
buildRelationTree(relations) {
|
|
6062
|
+
const tree = /* @__PURE__ */ new Map();
|
|
6063
|
+
Object.entries(relations).forEach(([path, constraint]) => {
|
|
6064
|
+
const segments = path.split(".").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
6065
|
+
if (segments.length === 0) return;
|
|
6066
|
+
let current = tree;
|
|
6067
|
+
segments.forEach((segment, index) => {
|
|
6068
|
+
const existing = current.get(segment) ?? {
|
|
6069
|
+
constraint: void 0,
|
|
6070
|
+
children: /* @__PURE__ */ new Map()
|
|
6071
|
+
};
|
|
6072
|
+
if (index === segments.length - 1 && constraint) existing.constraint = constraint;
|
|
6073
|
+
current.set(segment, existing);
|
|
6074
|
+
current = existing.children;
|
|
6075
|
+
});
|
|
6076
|
+
});
|
|
6077
|
+
return tree;
|
|
6078
|
+
}
|
|
6079
|
+
relationTreeToMap(tree, prefix = "") {
|
|
6080
|
+
return Array.from(tree.entries()).reduce((all, [name, node]) => {
|
|
6081
|
+
const path = prefix ? `${prefix}.${name}` : name;
|
|
6082
|
+
all[path] = node.constraint;
|
|
6083
|
+
Object.assign(all, this.relationTreeToMap(node.children, path));
|
|
6084
|
+
return all;
|
|
6085
|
+
}, {});
|
|
6086
|
+
}
|
|
6087
|
+
collectLoadedRelationModels(name) {
|
|
6088
|
+
return this.models.reduce((all, model) => {
|
|
6089
|
+
const loaded = model.getAttribute(name);
|
|
6090
|
+
if (loaded instanceof ArkormCollection) {
|
|
6091
|
+
loaded.all().forEach((item) => {
|
|
6092
|
+
if (this.isEagerLoadableModel(item)) all.push(item);
|
|
6093
|
+
});
|
|
6094
|
+
return all;
|
|
6095
|
+
}
|
|
6096
|
+
if (this.isEagerLoadableModel(loaded)) all.push(loaded);
|
|
6097
|
+
return all;
|
|
6098
|
+
}, []);
|
|
6099
|
+
}
|
|
6100
|
+
isEagerLoadableModel(value) {
|
|
6101
|
+
return typeof value === "object" && value !== null && typeof value.getAttribute === "function" && typeof value.setLoadedRelation === "function";
|
|
6102
|
+
}
|
|
6046
6103
|
/**
|
|
6047
6104
|
* Loads a "belongs to" relationship for the set of models.
|
|
6048
6105
|
*
|
|
@@ -7507,12 +7564,14 @@ var QueryBuilder = class QueryBuilder {
|
|
|
7507
7564
|
* @returns
|
|
7508
7565
|
*/
|
|
7509
7566
|
async updateOrInsert(attributes, values = {}) {
|
|
7510
|
-
if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") {
|
|
7567
|
+
if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") try {
|
|
7511
7568
|
await this.executeUpsertRows([{
|
|
7512
7569
|
...attributes,
|
|
7513
7570
|
...values
|
|
7514
7571
|
}], Object.keys(attributes), Object.keys(values));
|
|
7515
7572
|
return true;
|
|
7573
|
+
} catch (error) {
|
|
7574
|
+
if (!this.shouldFallbackUpdateOrInsertUpsert(error)) throw error;
|
|
7516
7575
|
}
|
|
7517
7576
|
const exists = await this.clone().where(attributes).first() != null;
|
|
7518
7577
|
const resolvedValues = typeof values === "function" ? await values(exists) : values;
|
|
@@ -7525,6 +7584,13 @@ var QueryBuilder = class QueryBuilder {
|
|
|
7525
7584
|
}
|
|
7526
7585
|
return await this.clone().where(attributes).update(resolvedValues) != null;
|
|
7527
7586
|
}
|
|
7587
|
+
shouldFallbackUpdateOrInsertUpsert(error) {
|
|
7588
|
+
if (!(error instanceof QueryExecutionException)) return false;
|
|
7589
|
+
const cause = error.cause;
|
|
7590
|
+
const code = typeof cause?.code === "string" ? cause.code : void 0;
|
|
7591
|
+
const message = typeof cause?.message === "string" ? cause.message : error.message;
|
|
7592
|
+
return code === "42P10" || message.includes("there is no unique or exclusion constraint matching the ON CONFLICT specification");
|
|
7593
|
+
}
|
|
7528
7594
|
/**
|
|
7529
7595
|
* Insert new records or update existing records by one or more unique keys.
|
|
7530
7596
|
*
|