@simonbackx/simple-database 1.36.0 → 1.36.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.
Files changed (230) hide show
  1. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.cjs +9 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.mjs +9 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/index.cjs +22 -0
  5. package/dist/index.d.cts +10 -0
  6. package/dist/index.d.mts +10 -0
  7. package/dist/index.mjs +10 -0
  8. package/dist/src/classes/Column.cjs +134 -0
  9. package/dist/src/classes/Column.d.cts +34 -0
  10. package/dist/src/classes/Column.d.cts.map +1 -0
  11. package/dist/src/classes/Column.d.mts +34 -0
  12. package/dist/src/classes/Column.d.mts.map +1 -0
  13. package/dist/src/classes/Column.mjs +135 -0
  14. package/dist/src/classes/Column.mjs.map +1 -0
  15. package/dist/src/classes/ColumnType.d.cts +5 -0
  16. package/dist/src/classes/ColumnType.d.cts.map +1 -0
  17. package/dist/src/classes/ColumnType.d.mts +5 -0
  18. package/dist/src/classes/ColumnType.d.mts.map +1 -0
  19. package/dist/src/classes/Database.cjs +157 -0
  20. package/dist/src/classes/Database.d.cts +59 -0
  21. package/dist/src/classes/Database.d.cts.map +1 -0
  22. package/dist/src/classes/Database.d.mts +59 -0
  23. package/dist/src/classes/Database.d.mts.map +1 -0
  24. package/dist/src/classes/Database.mjs +155 -0
  25. package/dist/src/classes/Database.mjs.map +1 -0
  26. package/dist/src/classes/DatabaseStoredValue.d.cts +5 -0
  27. package/dist/src/classes/DatabaseStoredValue.d.cts.map +1 -0
  28. package/dist/src/classes/DatabaseStoredValue.d.mts +5 -0
  29. package/dist/src/classes/DatabaseStoredValue.d.mts.map +1 -0
  30. package/dist/src/classes/Factory.cjs +48 -0
  31. package/dist/src/classes/Factory.d.cts +17 -0
  32. package/dist/src/classes/Factory.d.cts.map +1 -0
  33. package/dist/src/classes/Factory.d.mts +17 -0
  34. package/dist/src/classes/Factory.d.mts.map +1 -0
  35. package/dist/src/classes/Factory.mjs +50 -0
  36. package/dist/src/classes/Factory.mjs.map +1 -0
  37. package/dist/src/classes/ManyToManyRelation.cjs +193 -0
  38. package/dist/src/classes/ManyToManyRelation.d.cts +83 -0
  39. package/dist/src/classes/ManyToManyRelation.d.cts.map +1 -0
  40. package/dist/src/classes/ManyToManyRelation.d.mts +83 -0
  41. package/dist/src/classes/ManyToManyRelation.d.mts.map +1 -0
  42. package/dist/src/classes/ManyToManyRelation.mjs +195 -0
  43. package/dist/src/classes/ManyToManyRelation.mjs.map +1 -0
  44. package/dist/src/classes/ManyToOneRelation.cjs +41 -0
  45. package/dist/src/classes/ManyToOneRelation.d.cts +26 -0
  46. package/dist/src/classes/ManyToOneRelation.d.cts.map +1 -0
  47. package/dist/src/classes/ManyToOneRelation.d.mts +26 -0
  48. package/dist/src/classes/ManyToOneRelation.d.mts.map +1 -0
  49. package/dist/src/classes/ManyToOneRelation.mjs +43 -0
  50. package/dist/src/classes/ManyToOneRelation.mjs.map +1 -0
  51. package/dist/src/classes/Migration.cjs +116 -0
  52. package/dist/src/classes/Migration.d.cts +16 -0
  53. package/dist/src/classes/Migration.d.cts.map +1 -0
  54. package/dist/src/classes/Migration.d.mts +16 -0
  55. package/dist/src/classes/Migration.d.mts.map +1 -0
  56. package/dist/src/classes/Migration.mjs +116 -0
  57. package/dist/src/classes/Migration.mjs.map +1 -0
  58. package/dist/src/classes/Model.cjs +459 -0
  59. package/dist/src/classes/Model.d.cts +162 -0
  60. package/dist/src/classes/Model.d.cts.map +1 -0
  61. package/dist/src/classes/Model.d.mts +162 -0
  62. package/dist/src/classes/Model.d.mts.map +1 -0
  63. package/dist/src/classes/Model.mjs +460 -0
  64. package/dist/src/classes/Model.mjs.map +1 -0
  65. package/dist/src/classes/OneToManyRelation.cjs +66 -0
  66. package/dist/src/classes/OneToManyRelation.d.cts +42 -0
  67. package/dist/src/classes/OneToManyRelation.d.cts.map +1 -0
  68. package/dist/src/classes/OneToManyRelation.d.mts +42 -0
  69. package/dist/src/classes/OneToManyRelation.d.mts.map +1 -0
  70. package/dist/src/classes/OneToManyRelation.mjs +68 -0
  71. package/dist/src/classes/OneToManyRelation.mjs.map +1 -0
  72. package/dist/src/classes/data/boys.cjs +1005 -0
  73. package/dist/src/classes/data/boys.mjs +1007 -0
  74. package/dist/src/classes/data/boys.mjs.map +1 -0
  75. package/dist/src/classes/data/family-names.cjs +1005 -0
  76. package/dist/src/classes/data/family-names.mjs +1007 -0
  77. package/dist/src/classes/data/family-names.mjs.map +1 -0
  78. package/dist/src/classes/data/girls.cjs +1004 -0
  79. package/dist/src/classes/data/girls.mjs +1006 -0
  80. package/dist/src/classes/data/girls.mjs.map +1 -0
  81. package/dist/src/decorators/Column.cjs +26 -0
  82. package/dist/src/decorators/Column.d.cts +22 -0
  83. package/dist/src/decorators/Column.d.cts.map +1 -0
  84. package/dist/src/decorators/Column.d.mts +22 -0
  85. package/dist/src/decorators/Column.d.mts.map +1 -0
  86. package/dist/src/decorators/Column.mjs +28 -0
  87. package/dist/src/decorators/Column.mjs.map +1 -0
  88. package/dist/src/models/Migration.cjs +37 -0
  89. package/dist/src/models/Migration.mjs +39 -0
  90. package/dist/src/models/Migration.mjs.map +1 -0
  91. package/package.json +27 -14
  92. package/dist/cjs/index.d.ts +0 -10
  93. package/dist/cjs/index.d.ts.map +0 -1
  94. package/dist/cjs/index.js +0 -13
  95. package/dist/cjs/index.js.map +0 -1
  96. package/dist/cjs/package.json +0 -1
  97. package/dist/cjs/src/classes/Column.d.ts +0 -30
  98. package/dist/cjs/src/classes/Column.d.ts.map +0 -1
  99. package/dist/cjs/src/classes/Column.js +0 -183
  100. package/dist/cjs/src/classes/Column.js.map +0 -1
  101. package/dist/cjs/src/classes/ColumnType.d.ts +0 -2
  102. package/dist/cjs/src/classes/ColumnType.d.ts.map +0 -1
  103. package/dist/cjs/src/classes/ColumnType.js +0 -3
  104. package/dist/cjs/src/classes/ColumnType.js.map +0 -1
  105. package/dist/cjs/src/classes/Database.d.ts +0 -59
  106. package/dist/cjs/src/classes/Database.d.ts.map +0 -1
  107. package/dist/cjs/src/classes/Database.js +0 -176
  108. package/dist/cjs/src/classes/Database.js.map +0 -1
  109. package/dist/cjs/src/classes/DatabaseStoredValue.d.ts +0 -2
  110. package/dist/cjs/src/classes/DatabaseStoredValue.d.ts.map +0 -1
  111. package/dist/cjs/src/classes/DatabaseStoredValue.js +0 -3
  112. package/dist/cjs/src/classes/DatabaseStoredValue.js.map +0 -1
  113. package/dist/cjs/src/classes/Factory.d.ts +0 -14
  114. package/dist/cjs/src/classes/Factory.d.ts.map +0 -1
  115. package/dist/cjs/src/classes/Factory.js +0 -56
  116. package/dist/cjs/src/classes/Factory.js.map +0 -1
  117. package/dist/cjs/src/classes/ManyToManyRelation.d.ts +0 -79
  118. package/dist/cjs/src/classes/ManyToManyRelation.d.ts.map +0 -1
  119. package/dist/cjs/src/classes/ManyToManyRelation.js +0 -258
  120. package/dist/cjs/src/classes/ManyToManyRelation.js.map +0 -1
  121. package/dist/cjs/src/classes/ManyToOneRelation.d.ts +0 -22
  122. package/dist/cjs/src/classes/ManyToOneRelation.d.ts.map +0 -1
  123. package/dist/cjs/src/classes/ManyToOneRelation.js +0 -51
  124. package/dist/cjs/src/classes/ManyToOneRelation.js.map +0 -1
  125. package/dist/cjs/src/classes/Migration.d.ts +0 -14
  126. package/dist/cjs/src/classes/Migration.d.ts.map +0 -1
  127. package/dist/cjs/src/classes/Migration.js +0 -206
  128. package/dist/cjs/src/classes/Migration.js.map +0 -1
  129. package/dist/cjs/src/classes/Model.d.ts +0 -159
  130. package/dist/cjs/src/classes/Model.d.ts.map +0 -1
  131. package/dist/cjs/src/classes/Model.js +0 -640
  132. package/dist/cjs/src/classes/Model.js.map +0 -1
  133. package/dist/cjs/src/classes/OneToManyRelation.d.ts +0 -38
  134. package/dist/cjs/src/classes/OneToManyRelation.d.ts.map +0 -1
  135. package/dist/cjs/src/classes/OneToManyRelation.js +0 -79
  136. package/dist/cjs/src/classes/OneToManyRelation.js.map +0 -1
  137. package/dist/cjs/src/classes/data/boys.d.ts +0 -3
  138. package/dist/cjs/src/classes/data/boys.d.ts.map +0 -1
  139. package/dist/cjs/src/classes/data/boys.js +0 -1005
  140. package/dist/cjs/src/classes/data/boys.js.map +0 -1
  141. package/dist/cjs/src/classes/data/family-names.d.ts +0 -3
  142. package/dist/cjs/src/classes/data/family-names.d.ts.map +0 -1
  143. package/dist/cjs/src/classes/data/family-names.js +0 -1005
  144. package/dist/cjs/src/classes/data/family-names.js.map +0 -1
  145. package/dist/cjs/src/classes/data/girls.d.ts +0 -3
  146. package/dist/cjs/src/classes/data/girls.d.ts.map +0 -1
  147. package/dist/cjs/src/classes/data/girls.js +0 -1004
  148. package/dist/cjs/src/classes/data/girls.js.map +0 -1
  149. package/dist/cjs/src/classes/data/streets.d.ts +0 -3
  150. package/dist/cjs/src/classes/data/streets.d.ts.map +0 -1
  151. package/dist/cjs/src/classes/data/streets.js +0 -296
  152. package/dist/cjs/src/classes/data/streets.js.map +0 -1
  153. package/dist/cjs/src/decorators/Column.d.ts +0 -18
  154. package/dist/cjs/src/decorators/Column.d.ts.map +0 -1
  155. package/dist/cjs/src/decorators/Column.js +0 -39
  156. package/dist/cjs/src/decorators/Column.js.map +0 -1
  157. package/dist/cjs/src/models/Migration.d.ts +0 -11
  158. package/dist/cjs/src/models/Migration.d.ts.map +0 -1
  159. package/dist/cjs/src/models/Migration.js +0 -52
  160. package/dist/cjs/src/models/Migration.js.map +0 -1
  161. package/dist/cjs/tsconfig.cjs.tsbuildinfo +0 -1
  162. package/dist/esm/index.d.ts +0 -10
  163. package/dist/esm/index.d.ts.map +0 -1
  164. package/dist/esm/index.js +0 -10
  165. package/dist/esm/index.js.map +0 -1
  166. package/dist/esm/src/classes/Column.d.ts +0 -30
  167. package/dist/esm/src/classes/Column.d.ts.map +0 -1
  168. package/dist/esm/src/classes/Column.js +0 -179
  169. package/dist/esm/src/classes/Column.js.map +0 -1
  170. package/dist/esm/src/classes/ColumnType.d.ts +0 -2
  171. package/dist/esm/src/classes/ColumnType.d.ts.map +0 -1
  172. package/dist/esm/src/classes/ColumnType.js +0 -2
  173. package/dist/esm/src/classes/ColumnType.js.map +0 -1
  174. package/dist/esm/src/classes/Database.d.ts +0 -59
  175. package/dist/esm/src/classes/Database.d.ts.map +0 -1
  176. package/dist/esm/src/classes/Database.js +0 -171
  177. package/dist/esm/src/classes/Database.js.map +0 -1
  178. package/dist/esm/src/classes/DatabaseStoredValue.d.ts +0 -2
  179. package/dist/esm/src/classes/DatabaseStoredValue.d.ts.map +0 -1
  180. package/dist/esm/src/classes/DatabaseStoredValue.js +0 -2
  181. package/dist/esm/src/classes/DatabaseStoredValue.js.map +0 -1
  182. package/dist/esm/src/classes/Factory.d.ts +0 -14
  183. package/dist/esm/src/classes/Factory.d.ts.map +0 -1
  184. package/dist/esm/src/classes/Factory.js +0 -51
  185. package/dist/esm/src/classes/Factory.js.map +0 -1
  186. package/dist/esm/src/classes/ManyToManyRelation.d.ts +0 -79
  187. package/dist/esm/src/classes/ManyToManyRelation.d.ts.map +0 -1
  188. package/dist/esm/src/classes/ManyToManyRelation.js +0 -254
  189. package/dist/esm/src/classes/ManyToManyRelation.js.map +0 -1
  190. package/dist/esm/src/classes/ManyToOneRelation.d.ts +0 -22
  191. package/dist/esm/src/classes/ManyToOneRelation.d.ts.map +0 -1
  192. package/dist/esm/src/classes/ManyToOneRelation.js +0 -47
  193. package/dist/esm/src/classes/ManyToOneRelation.js.map +0 -1
  194. package/dist/esm/src/classes/Migration.d.ts +0 -14
  195. package/dist/esm/src/classes/Migration.d.ts.map +0 -1
  196. package/dist/esm/src/classes/Migration.js +0 -168
  197. package/dist/esm/src/classes/Migration.js.map +0 -1
  198. package/dist/esm/src/classes/Model.d.ts +0 -159
  199. package/dist/esm/src/classes/Model.d.ts.map +0 -1
  200. package/dist/esm/src/classes/Model.js +0 -635
  201. package/dist/esm/src/classes/Model.js.map +0 -1
  202. package/dist/esm/src/classes/OneToManyRelation.d.ts +0 -38
  203. package/dist/esm/src/classes/OneToManyRelation.d.ts.map +0 -1
  204. package/dist/esm/src/classes/OneToManyRelation.js +0 -75
  205. package/dist/esm/src/classes/OneToManyRelation.js.map +0 -1
  206. package/dist/esm/src/classes/data/boys.d.ts +0 -3
  207. package/dist/esm/src/classes/data/boys.d.ts.map +0 -1
  208. package/dist/esm/src/classes/data/boys.js +0 -1003
  209. package/dist/esm/src/classes/data/boys.js.map +0 -1
  210. package/dist/esm/src/classes/data/family-names.d.ts +0 -3
  211. package/dist/esm/src/classes/data/family-names.d.ts.map +0 -1
  212. package/dist/esm/src/classes/data/family-names.js +0 -1003
  213. package/dist/esm/src/classes/data/family-names.js.map +0 -1
  214. package/dist/esm/src/classes/data/girls.d.ts +0 -3
  215. package/dist/esm/src/classes/data/girls.d.ts.map +0 -1
  216. package/dist/esm/src/classes/data/girls.js +0 -1002
  217. package/dist/esm/src/classes/data/girls.js.map +0 -1
  218. package/dist/esm/src/classes/data/streets.d.ts +0 -3
  219. package/dist/esm/src/classes/data/streets.d.ts.map +0 -1
  220. package/dist/esm/src/classes/data/streets.js +0 -294
  221. package/dist/esm/src/classes/data/streets.js.map +0 -1
  222. package/dist/esm/src/decorators/Column.d.ts +0 -18
  223. package/dist/esm/src/decorators/Column.d.ts.map +0 -1
  224. package/dist/esm/src/decorators/Column.js +0 -36
  225. package/dist/esm/src/decorators/Column.js.map +0 -1
  226. package/dist/esm/src/models/Migration.d.ts +0 -11
  227. package/dist/esm/src/models/Migration.d.ts.map +0 -1
  228. package/dist/esm/src/models/Migration.js +0 -48
  229. package/dist/esm/src/models/Migration.js.map +0 -1
  230. package/dist/esm/tsconfig.esm.tsbuildinfo +0 -1
@@ -0,0 +1,193 @@
1
+ const require_Database = require("./Database.cjs");
2
+ const require_Model = require("./Model.cjs");
3
+ //#region src/classes/ManyToManyRelation.ts
4
+ var ManyToManyRelation = class ManyToManyRelation {
5
+ modelA;
6
+ modelB;
7
+ modelLink;
8
+ /**
9
+ * E.g. parents
10
+ */
11
+ modelKey;
12
+ /**
13
+ * Sort the loading of this relation
14
+ */
15
+ sortKey;
16
+ sortOrder = "ASC";
17
+ /**
18
+ * E.g. _models_parents
19
+ */
20
+ get linkTable() {
21
+ if (this.modelLink) return this.modelLink.table;
22
+ return "_" + [this.modelA.table, this.modelB.table].sort().join("_");
23
+ }
24
+ /**
25
+ * e.g. modelsId
26
+ */
27
+ get linkKeyA() {
28
+ return this.modelA.table + this.modelA.primary.name.charAt(0).toUpperCase() + this.modelA.primary.name.substring(1) + (this.modelA === this.modelB ? "A" : "");
29
+ }
30
+ /**
31
+ * e.g. parentsId
32
+ */
33
+ get linkKeyB() {
34
+ return this.modelB.table + this.modelB.primary.name.charAt(0).toUpperCase() + this.modelB.primary.name.substring(1) + (this.modelA === this.modelB ? "B" : "");
35
+ }
36
+ constructor(modelA, modelB, modelKey, modelLink) {
37
+ this.modelA = modelA;
38
+ this.modelB = modelB;
39
+ this.modelKey = modelKey;
40
+ this.modelLink = modelLink;
41
+ }
42
+ reverse(modelKey) {
43
+ return new ManyToManyRelation(this.modelB, this.modelA, modelKey, this.modelLink);
44
+ }
45
+ setSort(key, order = "ASC") {
46
+ this.sortKey = key;
47
+ this.sortOrder = order;
48
+ return this;
49
+ }
50
+ joinQuery(namespaceA, namespaceB) {
51
+ const linkNamespace = namespaceA + "_" + namespaceB;
52
+ let str = `LEFT JOIN ${this.linkTable} as ${linkNamespace} on ${linkNamespace}.${this.linkKeyA} = ${namespaceA}.${this.modelA.primary.name}\n`;
53
+ str += `LEFT JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}`;
54
+ return str;
55
+ }
56
+ orderByQuery(namespaceA, namespaceB) {
57
+ if (this.sortKey === void 0) return "";
58
+ let str = `\nORDER BY ${namespaceA + "_" + namespaceB}.${this.sortKey}`;
59
+ if (this.sortOrder === "DESC") str += " DESC";
60
+ return str + "\n";
61
+ }
62
+ async load(modelA, sorted = true, where, whereLink) {
63
+ const namespaceB = "B";
64
+ const linkNamespace = "A_B";
65
+ let select = this.modelB.getDefaultSelect(namespaceB);
66
+ if (this.modelLink) select += ", " + this.modelLink.getDefaultSelect(linkNamespace);
67
+ let str = `SELECT ${select} FROM ${this.linkTable} as ${linkNamespace}\n`;
68
+ str += `JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}\n`;
69
+ str += `WHERE ${linkNamespace}.${this.linkKeyA} = ?`;
70
+ const params = [modelA.getPrimaryKey()];
71
+ if (where) {
72
+ for (const key in where) if (Object.hasOwnProperty.call(where, key)) {
73
+ str += ` AND ${namespaceB}.\`${key}\` = ?`;
74
+ params.push(where[key]);
75
+ }
76
+ }
77
+ if (whereLink) {
78
+ for (const key in whereLink) if (Object.hasOwnProperty.call(whereLink, key)) {
79
+ str += ` AND ${linkNamespace}.\`${key}\` = ?`;
80
+ params.push(whereLink[key]);
81
+ }
82
+ }
83
+ if (sorted) str += this.orderByQuery("A", "B");
84
+ const [rows] = await require_Database.Database.select(str, params);
85
+ const modelsB = this.modelB.fromRows(rows, namespaceB);
86
+ if (this.modelLink) for (const row of rows) {
87
+ const model = this.modelLink.fromRow(row[linkNamespace]);
88
+ const modelB = modelsB.find((m) => m.getPrimaryKey() === row[linkNamespace][this.linkKeyB]);
89
+ if (!modelB) throw new Error("Unexpected linking");
90
+ modelB._link = model;
91
+ }
92
+ modelA.setManyRelation(this, modelsB);
93
+ return modelsB;
94
+ }
95
+ isLoaded(model) {
96
+ return Array.isArray(model[this.modelKey]);
97
+ }
98
+ async setLinkTable(modelA, modelB, linkTableValues) {
99
+ const str = `UPDATE ${this.linkTable} SET ? WHERE ${require_Database.Database.escapeId(this.linkKeyA)} = ? AND ${require_Database.Database.escapeId(this.linkKeyB)} = ?`;
100
+ const [result] = await require_Database.Database.update(str, [
101
+ linkTableValues,
102
+ modelA.getPrimaryKey(),
103
+ modelB.getPrimaryKey()
104
+ ]);
105
+ if (result.changedRows !== 1) throw new Error("Failed to update link table. Check if combination exists");
106
+ }
107
+ async linkIds(modelA, modelsB, linkTableValues) {
108
+ if (modelsB.length === 0) return 0;
109
+ let result;
110
+ if (linkTableValues !== void 0) {
111
+ const linkTableKeys = Object.keys(linkTableValues);
112
+ for (const property in linkTableValues) if (Object.hasOwnProperty.call(linkTableValues, property)) {
113
+ if (linkTableValues[property].length !== modelsB.length) throw new Error("Amount of link table values for key " + property + " (" + linkTableValues[property].length + ") are not equal to amount of models linked (" + modelsB.length + ")");
114
+ }
115
+ const query = `INSERT INTO ${require_Database.Database.escapeId(this.linkTable)} (
116
+ ${require_Database.Database.escapeId(this.linkKeyA)},
117
+ ${require_Database.Database.escapeId(this.linkKeyB)},
118
+ ${linkTableKeys.map((k) => require_Database.Database.escapeId(k)).join(", ")}
119
+ ) VALUES ?`;
120
+ [result] = await require_Database.Database.insert(query, [modelsB.map((modelB, i) => [
121
+ modelA,
122
+ modelB,
123
+ ...linkTableKeys.map((k) => linkTableValues[k][i])
124
+ ])]);
125
+ } else {
126
+ const query = `INSERT INTO ${require_Database.Database.escapeId(this.linkTable)} (
127
+ ${require_Database.Database.escapeId(this.linkKeyA)},
128
+ ${require_Database.Database.escapeId(this.linkKeyB)}
129
+ ) VALUES ?`;
130
+ [result] = await require_Database.Database.insert(query, [modelsB.map((modelB) => [modelA, modelB])]);
131
+ }
132
+ return result.affectedRows;
133
+ }
134
+ async link(modelA, modelsB, linkTableValues) {
135
+ const modelAId = modelA.getPrimaryKey();
136
+ if (!modelAId) throw new Error("Cannot link if model is not saved yet");
137
+ const affectedRows = await this.linkIds(modelAId, modelsB.map((modelB) => {
138
+ const id = modelB.getPrimaryKey();
139
+ if (!id) throw new Error("Cannot link to a model that is not saved yet");
140
+ return id;
141
+ }), linkTableValues);
142
+ if (this.isLoaded(modelA)) if (affectedRows === modelsB.length) modelA[this.modelKey].push(...modelsB);
143
+ else {
144
+ console.warn("Warning: linking expected to affect " + modelsB.length + " rows, but only affected " + affectedRows + " rows");
145
+ throw new Error("Fallback behaviour net yet implemented");
146
+ }
147
+ }
148
+ /**
149
+ * Delete all the links from modelA for this relation
150
+ * @param modelA
151
+ */
152
+ async clearId(modelA) {
153
+ const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ?`;
154
+ const [result] = await require_Database.Database.delete(query, [modelA]);
155
+ if (result.affectedRows === 0 && require_Model.Model.debug) console.warn("Cleared many to many relation, but didn't deleted any entries");
156
+ }
157
+ /**
158
+ * Delete all the links from modelA for this relation
159
+ * @param modelA
160
+ */
161
+ async clear(modelA) {
162
+ await this.clearId(modelA.getPrimaryKey());
163
+ modelA.setManyRelation(this, []);
164
+ }
165
+ /**
166
+ * Delete all the links from modelA for this relation
167
+ * @param modelA
168
+ */
169
+ async syncId(modelA, modelsB, linkTableValues) {
170
+ await this.clearId(modelA);
171
+ await this.linkIds(modelA, modelsB, linkTableValues);
172
+ }
173
+ async unlinkIds(modelA, ...modelsB) {
174
+ const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ? AND ${this.linkKeyB} IN (?)`;
175
+ const [result] = await require_Database.Database.delete(query, [modelA, modelsB]);
176
+ return result;
177
+ }
178
+ async unlink(modelA, ...modelsB) {
179
+ const result = await this.unlinkIds(modelA.getPrimaryKey(), ...modelsB.map((modelB) => modelB.getPrimaryKey()));
180
+ if (this.isLoaded(modelA)) if (result.affectedRows === modelsB.length) {
181
+ const arr = modelA[this.modelKey];
182
+ const idMap = modelsB.map((model) => model.getPrimaryKey());
183
+ modelA.setManyRelation(this, arr.filter((model) => {
184
+ return !idMap.includes(model.getPrimaryKey());
185
+ }));
186
+ } else {
187
+ console.warn("Warning: unlinking expected to affect " + modelsB.length + " rows, but only affected " + result.affectedRows + " rows");
188
+ throw new Error("Fallback behaviour net yet implemented");
189
+ }
190
+ }
191
+ };
192
+ //#endregion
193
+ exports.ManyToManyRelation = ManyToManyRelation;
@@ -0,0 +1,83 @@
1
+ import { Model } from "./Model.cjs";
2
+
3
+ //#region src/classes/ManyToManyRelation.d.ts
4
+ declare class ManyToManyRelation<Key extends keyof any, A extends Model, B extends Model, Link extends Model | undefined = undefined> {
5
+ modelA: {
6
+ new (): A;
7
+ } & typeof Model;
8
+ modelB: {
9
+ new (): B;
10
+ } & typeof Model;
11
+ modelLink?: {
12
+ new (): Link;
13
+ } & typeof Model;
14
+ /**
15
+ * E.g. parents
16
+ */
17
+ modelKey: Key;
18
+ /**
19
+ * Sort the loading of this relation
20
+ */
21
+ sortKey: string | undefined;
22
+ sortOrder: 'ASC' | 'DESC';
23
+ /**
24
+ * E.g. _models_parents
25
+ */
26
+ get linkTable(): string;
27
+ /**
28
+ * e.g. modelsId
29
+ */
30
+ get linkKeyA(): string;
31
+ /**
32
+ * e.g. parentsId
33
+ */
34
+ get linkKeyB(): string;
35
+ constructor(modelA: {
36
+ new (): A;
37
+ } & typeof Model, modelB: {
38
+ new (): B;
39
+ } & typeof Model, modelKey: Key, modelLink?: {
40
+ new (): Link;
41
+ } & typeof Model);
42
+ reverse<Key2 extends keyof any>(modelKey: Key2): ManyToManyRelation<Key2, B, A, Link>;
43
+ setSort(key: string, order?: 'ASC' | 'DESC'): this;
44
+ joinQuery(namespaceA: string, namespaceB: string): string;
45
+ orderByQuery(namespaceA: string, namespaceB: string): string;
46
+ load(modelA: A, sorted?: boolean, where?: object, whereLink?: object): Promise<(B & {
47
+ _link: Link;
48
+ })[]>;
49
+ isLoaded<T extends A>(model: T): model is T & Record<Key, B[]>;
50
+ setLinkTable(modelA: A, modelB: B, linkTableValues: {
51
+ [key: string]: any;
52
+ }): Promise<void>;
53
+ linkIds(modelA: string | number, modelsB: (string | number)[], linkTableValues?: {
54
+ [key: string]: any[];
55
+ }): Promise<number>;
56
+ link(modelA: A, modelsB: B[], linkTableValues?: {
57
+ [key: string]: any[];
58
+ }): Promise<void>;
59
+ /**
60
+ * Delete all the links from modelA for this relation
61
+ * @param modelA
62
+ */
63
+ clearId(modelA: string | number): Promise<void>;
64
+ /**
65
+ * Delete all the links from modelA for this relation
66
+ * @param modelA
67
+ */
68
+ clear(modelA: A): Promise<void>;
69
+ /**
70
+ * Delete all the links from modelA for this relation
71
+ * @param modelA
72
+ */
73
+ syncId(modelA: string | number, modelsB: (string | number)[], linkTableValues?: {
74
+ [key: string]: any[];
75
+ }): Promise<void>;
76
+ unlinkIds(modelA: string | number, ...modelsB: (string | number)[]): Promise<{
77
+ affectedRows: number;
78
+ }>;
79
+ unlink(modelA: A, ...modelsB: B[]): Promise<void>;
80
+ }
81
+ //#endregion
82
+ export { ManyToManyRelation };
83
+ //# sourceMappingURL=ManyToManyRelation.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManyToManyRelation.d.cts","names":[],"sources":["../../../src/classes/ManyToManyRelation.ts"],"mappings":";;;cAGa,kBAAA,kCAAoD,KAAA,YAAiB,KAAA,eAAoB,KAAA;EAClG,MAAA;IAAA,QAAkB,CAAA;EAAA,WAAa,KAAA;EAC/B,MAAA;IAAA,QAAkB,CAAA;EAAA,WAAa,KAAA;EAC/B,SAAA;IAAA,QAAqB,IAAA;EAAA,WAAgB,KAAA;EADnB;;;EAMlB,QAAA,EAAU,GAAA;EAAA;;;EAKV,OAAA;EACA,SAAA;EAoCgG;;;EAAA,IA/B5F,SAAA,CAAA;EAsCgE;;;EAAA,IA5BhE,QAAA,CAAA;EA4B6C;;;EAAA,IAhB7C,QAAA,CAAA;cASQ,MAAA;IAAA,QAAiB,CAAA;EAAA,WAAa,KAAA,EAAO,MAAA;IAAA,QAAiB,CAAA;EAAA,WAAa,KAAA,EAAO,QAAA,EAAU,GAAA,EAAK,SAAA;IAAA,QAAqB,IAAA;EAAA,WAAgB,KAAA;EAO1I,OAAA,wBAAA,CAAgC,QAAA,EAAU,IAAA,GAAO,kBAAA,CAAmB,IAAA,EAAM,CAAA,EAAG,CAAA,EAAG,IAAA;EAIhF,OAAA,CAAQ,GAAA,UAAa,KAAA;EAOrB,SAAA,CAAU,UAAA,UAAoB,UAAA;EAO9B,YAAA,CAAa,UAAA,UAAoB,UAAA;EAa3B,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,MAAA,YAAe,KAAA,WAAgB,SAAA,YAAqB,OAAA,EAAS,CAAA;IAAM,KAAA,EAAO,IAAA;EAAA;EA2DhG,QAAA,WAAmB,CAAA,CAAA,CAAG,KAAA,EAAO,CAAA,GAAI,KAAA,IAAS,CAAA,GAAI,MAAA,CAAO,GAAA,EAAK,CAAA;EAKpD,YAAA,CAAa,MAAA,EAAQ,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,eAAA;IAAA,CAAoB,GAAA;EAAA,IAAmB,OAAA;EAU1E,OAAA,CAAQ,MAAA,mBAAyB,OAAA,uBAA8B,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EA4C5G,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,OAAA,EAAS,CAAA,IAAK,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EA9MrD;;;;EAqPtB,OAAA,CAAQ,MAAA,oBAA0B,OAAA;EArP6C;;;;EAoQ/E,KAAA,CAAM,MAAA,EAAQ,CAAA,GAAI,OAAA;EAlQxB;;;;EA2QM,MAAA,CAAO,MAAA,mBAAyB,OAAA,uBAA8B,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EAM3G,SAAA,CAAU,MAAA,sBAA4B,OAAA,wBAA+B,OAAA;IAAU,YAAA;EAAA;EAS/E,MAAA,CAAO,MAAA,EAAQ,CAAA,KAAM,OAAA,EAAS,CAAA,KAAM,OAAA;AAAA"}
@@ -0,0 +1,83 @@
1
+ import { Model } from "./Model.mjs";
2
+
3
+ //#region src/classes/ManyToManyRelation.d.ts
4
+ declare class ManyToManyRelation<Key extends keyof any, A extends Model, B extends Model, Link extends Model | undefined = undefined> {
5
+ modelA: {
6
+ new (): A;
7
+ } & typeof Model;
8
+ modelB: {
9
+ new (): B;
10
+ } & typeof Model;
11
+ modelLink?: {
12
+ new (): Link;
13
+ } & typeof Model;
14
+ /**
15
+ * E.g. parents
16
+ */
17
+ modelKey: Key;
18
+ /**
19
+ * Sort the loading of this relation
20
+ */
21
+ sortKey: string | undefined;
22
+ sortOrder: 'ASC' | 'DESC';
23
+ /**
24
+ * E.g. _models_parents
25
+ */
26
+ get linkTable(): string;
27
+ /**
28
+ * e.g. modelsId
29
+ */
30
+ get linkKeyA(): string;
31
+ /**
32
+ * e.g. parentsId
33
+ */
34
+ get linkKeyB(): string;
35
+ constructor(modelA: {
36
+ new (): A;
37
+ } & typeof Model, modelB: {
38
+ new (): B;
39
+ } & typeof Model, modelKey: Key, modelLink?: {
40
+ new (): Link;
41
+ } & typeof Model);
42
+ reverse<Key2 extends keyof any>(modelKey: Key2): ManyToManyRelation<Key2, B, A, Link>;
43
+ setSort(key: string, order?: 'ASC' | 'DESC'): this;
44
+ joinQuery(namespaceA: string, namespaceB: string): string;
45
+ orderByQuery(namespaceA: string, namespaceB: string): string;
46
+ load(modelA: A, sorted?: boolean, where?: object, whereLink?: object): Promise<(B & {
47
+ _link: Link;
48
+ })[]>;
49
+ isLoaded<T extends A>(model: T): model is T & Record<Key, B[]>;
50
+ setLinkTable(modelA: A, modelB: B, linkTableValues: {
51
+ [key: string]: any;
52
+ }): Promise<void>;
53
+ linkIds(modelA: string | number, modelsB: (string | number)[], linkTableValues?: {
54
+ [key: string]: any[];
55
+ }): Promise<number>;
56
+ link(modelA: A, modelsB: B[], linkTableValues?: {
57
+ [key: string]: any[];
58
+ }): Promise<void>;
59
+ /**
60
+ * Delete all the links from modelA for this relation
61
+ * @param modelA
62
+ */
63
+ clearId(modelA: string | number): Promise<void>;
64
+ /**
65
+ * Delete all the links from modelA for this relation
66
+ * @param modelA
67
+ */
68
+ clear(modelA: A): Promise<void>;
69
+ /**
70
+ * Delete all the links from modelA for this relation
71
+ * @param modelA
72
+ */
73
+ syncId(modelA: string | number, modelsB: (string | number)[], linkTableValues?: {
74
+ [key: string]: any[];
75
+ }): Promise<void>;
76
+ unlinkIds(modelA: string | number, ...modelsB: (string | number)[]): Promise<{
77
+ affectedRows: number;
78
+ }>;
79
+ unlink(modelA: A, ...modelsB: B[]): Promise<void>;
80
+ }
81
+ //#endregion
82
+ export { ManyToManyRelation };
83
+ //# sourceMappingURL=ManyToManyRelation.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManyToManyRelation.d.mts","names":[],"sources":["../../../src/classes/ManyToManyRelation.ts"],"mappings":";;;cAGa,kBAAA,kCAAoD,KAAA,YAAiB,KAAA,eAAoB,KAAA;EAClG,MAAA;IAAA,QAAkB,CAAA;EAAA,WAAa,KAAA;EAC/B,MAAA;IAAA,QAAkB,CAAA;EAAA,WAAa,KAAA;EAC/B,SAAA;IAAA,QAAqB,IAAA;EAAA,WAAgB,KAAA;EADnB;;;EAMlB,QAAA,EAAU,GAAA;EAAA;;;EAKV,OAAA;EACA,SAAA;EAoCgG;;;EAAA,IA/B5F,SAAA,CAAA;EAsCgE;;;EAAA,IA5BhE,QAAA,CAAA;EA4B6C;;;EAAA,IAhB7C,QAAA,CAAA;cASQ,MAAA;IAAA,QAAiB,CAAA;EAAA,WAAa,KAAA,EAAO,MAAA;IAAA,QAAiB,CAAA;EAAA,WAAa,KAAA,EAAO,QAAA,EAAU,GAAA,EAAK,SAAA;IAAA,QAAqB,IAAA;EAAA,WAAgB,KAAA;EAO1I,OAAA,wBAAA,CAAgC,QAAA,EAAU,IAAA,GAAO,kBAAA,CAAmB,IAAA,EAAM,CAAA,EAAG,CAAA,EAAG,IAAA;EAIhF,OAAA,CAAQ,GAAA,UAAa,KAAA;EAOrB,SAAA,CAAU,UAAA,UAAoB,UAAA;EAO9B,YAAA,CAAa,UAAA,UAAoB,UAAA;EAa3B,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,MAAA,YAAe,KAAA,WAAgB,SAAA,YAAqB,OAAA,EAAS,CAAA;IAAM,KAAA,EAAO,IAAA;EAAA;EA2DhG,QAAA,WAAmB,CAAA,CAAA,CAAG,KAAA,EAAO,CAAA,GAAI,KAAA,IAAS,CAAA,GAAI,MAAA,CAAO,GAAA,EAAK,CAAA;EAKpD,YAAA,CAAa,MAAA,EAAQ,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,eAAA;IAAA,CAAoB,GAAA;EAAA,IAAmB,OAAA;EAU1E,OAAA,CAAQ,MAAA,mBAAyB,OAAA,uBAA8B,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EA4C5G,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,OAAA,EAAS,CAAA,IAAK,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EA9MrD;;;;EAqPtB,OAAA,CAAQ,MAAA,oBAA0B,OAAA;EArP6C;;;;EAoQ/E,KAAA,CAAM,MAAA,EAAQ,CAAA,GAAI,OAAA;EAlQxB;;;;EA2QM,MAAA,CAAO,MAAA,mBAAyB,OAAA,uBAA8B,eAAA;IAAA,CAAqB,GAAA;EAAA,IAAwB,OAAA;EAM3G,SAAA,CAAU,MAAA,sBAA4B,OAAA,wBAA+B,OAAA;IAAU,YAAA;EAAA;EAS/E,MAAA,CAAO,MAAA,EAAQ,CAAA,KAAM,OAAA,EAAS,CAAA,KAAM,OAAA;AAAA"}
@@ -0,0 +1,195 @@
1
+ import { Database } from "./Database.mjs";
2
+ import { Model } from "./Model.mjs";
3
+ //#region src/classes/ManyToManyRelation.ts
4
+ var ManyToManyRelation = class ManyToManyRelation {
5
+ modelA;
6
+ modelB;
7
+ modelLink;
8
+ /**
9
+ * E.g. parents
10
+ */
11
+ modelKey;
12
+ /**
13
+ * Sort the loading of this relation
14
+ */
15
+ sortKey;
16
+ sortOrder = "ASC";
17
+ /**
18
+ * E.g. _models_parents
19
+ */
20
+ get linkTable() {
21
+ if (this.modelLink) return this.modelLink.table;
22
+ return "_" + [this.modelA.table, this.modelB.table].sort().join("_");
23
+ }
24
+ /**
25
+ * e.g. modelsId
26
+ */
27
+ get linkKeyA() {
28
+ return this.modelA.table + this.modelA.primary.name.charAt(0).toUpperCase() + this.modelA.primary.name.substring(1) + (this.modelA === this.modelB ? "A" : "");
29
+ }
30
+ /**
31
+ * e.g. parentsId
32
+ */
33
+ get linkKeyB() {
34
+ return this.modelB.table + this.modelB.primary.name.charAt(0).toUpperCase() + this.modelB.primary.name.substring(1) + (this.modelA === this.modelB ? "B" : "");
35
+ }
36
+ constructor(modelA, modelB, modelKey, modelLink) {
37
+ this.modelA = modelA;
38
+ this.modelB = modelB;
39
+ this.modelKey = modelKey;
40
+ this.modelLink = modelLink;
41
+ }
42
+ reverse(modelKey) {
43
+ return new ManyToManyRelation(this.modelB, this.modelA, modelKey, this.modelLink);
44
+ }
45
+ setSort(key, order = "ASC") {
46
+ this.sortKey = key;
47
+ this.sortOrder = order;
48
+ return this;
49
+ }
50
+ joinQuery(namespaceA, namespaceB) {
51
+ const linkNamespace = namespaceA + "_" + namespaceB;
52
+ let str = `LEFT JOIN ${this.linkTable} as ${linkNamespace} on ${linkNamespace}.${this.linkKeyA} = ${namespaceA}.${this.modelA.primary.name}\n`;
53
+ str += `LEFT JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}`;
54
+ return str;
55
+ }
56
+ orderByQuery(namespaceA, namespaceB) {
57
+ if (this.sortKey === void 0) return "";
58
+ let str = `\nORDER BY ${namespaceA + "_" + namespaceB}.${this.sortKey}`;
59
+ if (this.sortOrder === "DESC") str += " DESC";
60
+ return str + "\n";
61
+ }
62
+ async load(modelA, sorted = true, where, whereLink) {
63
+ const namespaceB = "B";
64
+ const linkNamespace = "A_B";
65
+ let select = this.modelB.getDefaultSelect(namespaceB);
66
+ if (this.modelLink) select += ", " + this.modelLink.getDefaultSelect(linkNamespace);
67
+ let str = `SELECT ${select} FROM ${this.linkTable} as ${linkNamespace}\n`;
68
+ str += `JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}\n`;
69
+ str += `WHERE ${linkNamespace}.${this.linkKeyA} = ?`;
70
+ const params = [modelA.getPrimaryKey()];
71
+ if (where) {
72
+ for (const key in where) if (Object.hasOwnProperty.call(where, key)) {
73
+ str += ` AND ${namespaceB}.\`${key}\` = ?`;
74
+ params.push(where[key]);
75
+ }
76
+ }
77
+ if (whereLink) {
78
+ for (const key in whereLink) if (Object.hasOwnProperty.call(whereLink, key)) {
79
+ str += ` AND ${linkNamespace}.\`${key}\` = ?`;
80
+ params.push(whereLink[key]);
81
+ }
82
+ }
83
+ if (sorted) str += this.orderByQuery("A", "B");
84
+ const [rows] = await Database.select(str, params);
85
+ const modelsB = this.modelB.fromRows(rows, namespaceB);
86
+ if (this.modelLink) for (const row of rows) {
87
+ const model = this.modelLink.fromRow(row[linkNamespace]);
88
+ const modelB = modelsB.find((m) => m.getPrimaryKey() === row[linkNamespace][this.linkKeyB]);
89
+ if (!modelB) throw new Error("Unexpected linking");
90
+ modelB._link = model;
91
+ }
92
+ modelA.setManyRelation(this, modelsB);
93
+ return modelsB;
94
+ }
95
+ isLoaded(model) {
96
+ return Array.isArray(model[this.modelKey]);
97
+ }
98
+ async setLinkTable(modelA, modelB, linkTableValues) {
99
+ const str = `UPDATE ${this.linkTable} SET ? WHERE ${Database.escapeId(this.linkKeyA)} = ? AND ${Database.escapeId(this.linkKeyB)} = ?`;
100
+ const [result] = await Database.update(str, [
101
+ linkTableValues,
102
+ modelA.getPrimaryKey(),
103
+ modelB.getPrimaryKey()
104
+ ]);
105
+ if (result.changedRows !== 1) throw new Error("Failed to update link table. Check if combination exists");
106
+ }
107
+ async linkIds(modelA, modelsB, linkTableValues) {
108
+ if (modelsB.length === 0) return 0;
109
+ let result;
110
+ if (linkTableValues !== void 0) {
111
+ const linkTableKeys = Object.keys(linkTableValues);
112
+ for (const property in linkTableValues) if (Object.hasOwnProperty.call(linkTableValues, property)) {
113
+ if (linkTableValues[property].length !== modelsB.length) throw new Error("Amount of link table values for key " + property + " (" + linkTableValues[property].length + ") are not equal to amount of models linked (" + modelsB.length + ")");
114
+ }
115
+ const query = `INSERT INTO ${Database.escapeId(this.linkTable)} (
116
+ ${Database.escapeId(this.linkKeyA)},
117
+ ${Database.escapeId(this.linkKeyB)},
118
+ ${linkTableKeys.map((k) => Database.escapeId(k)).join(", ")}
119
+ ) VALUES ?`;
120
+ [result] = await Database.insert(query, [modelsB.map((modelB, i) => [
121
+ modelA,
122
+ modelB,
123
+ ...linkTableKeys.map((k) => linkTableValues[k][i])
124
+ ])]);
125
+ } else {
126
+ const query = `INSERT INTO ${Database.escapeId(this.linkTable)} (
127
+ ${Database.escapeId(this.linkKeyA)},
128
+ ${Database.escapeId(this.linkKeyB)}
129
+ ) VALUES ?`;
130
+ [result] = await Database.insert(query, [modelsB.map((modelB) => [modelA, modelB])]);
131
+ }
132
+ return result.affectedRows;
133
+ }
134
+ async link(modelA, modelsB, linkTableValues) {
135
+ const modelAId = modelA.getPrimaryKey();
136
+ if (!modelAId) throw new Error("Cannot link if model is not saved yet");
137
+ const affectedRows = await this.linkIds(modelAId, modelsB.map((modelB) => {
138
+ const id = modelB.getPrimaryKey();
139
+ if (!id) throw new Error("Cannot link to a model that is not saved yet");
140
+ return id;
141
+ }), linkTableValues);
142
+ if (this.isLoaded(modelA)) if (affectedRows === modelsB.length) modelA[this.modelKey].push(...modelsB);
143
+ else {
144
+ console.warn("Warning: linking expected to affect " + modelsB.length + " rows, but only affected " + affectedRows + " rows");
145
+ throw new Error("Fallback behaviour net yet implemented");
146
+ }
147
+ }
148
+ /**
149
+ * Delete all the links from modelA for this relation
150
+ * @param modelA
151
+ */
152
+ async clearId(modelA) {
153
+ const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ?`;
154
+ const [result] = await Database.delete(query, [modelA]);
155
+ if (result.affectedRows === 0 && Model.debug) console.warn("Cleared many to many relation, but didn't deleted any entries");
156
+ }
157
+ /**
158
+ * Delete all the links from modelA for this relation
159
+ * @param modelA
160
+ */
161
+ async clear(modelA) {
162
+ await this.clearId(modelA.getPrimaryKey());
163
+ modelA.setManyRelation(this, []);
164
+ }
165
+ /**
166
+ * Delete all the links from modelA for this relation
167
+ * @param modelA
168
+ */
169
+ async syncId(modelA, modelsB, linkTableValues) {
170
+ await this.clearId(modelA);
171
+ await this.linkIds(modelA, modelsB, linkTableValues);
172
+ }
173
+ async unlinkIds(modelA, ...modelsB) {
174
+ const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ? AND ${this.linkKeyB} IN (?)`;
175
+ const [result] = await Database.delete(query, [modelA, modelsB]);
176
+ return result;
177
+ }
178
+ async unlink(modelA, ...modelsB) {
179
+ const result = await this.unlinkIds(modelA.getPrimaryKey(), ...modelsB.map((modelB) => modelB.getPrimaryKey()));
180
+ if (this.isLoaded(modelA)) if (result.affectedRows === modelsB.length) {
181
+ const arr = modelA[this.modelKey];
182
+ const idMap = modelsB.map((model) => model.getPrimaryKey());
183
+ modelA.setManyRelation(this, arr.filter((model) => {
184
+ return !idMap.includes(model.getPrimaryKey());
185
+ }));
186
+ } else {
187
+ console.warn("Warning: unlinking expected to affect " + modelsB.length + " rows, but only affected " + result.affectedRows + " rows");
188
+ throw new Error("Fallback behaviour net yet implemented");
189
+ }
190
+ }
191
+ };
192
+ //#endregion
193
+ export { ManyToManyRelation };
194
+
195
+ //# sourceMappingURL=ManyToManyRelation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManyToManyRelation.mjs","names":[],"sources":["../../../src/classes/ManyToManyRelation.ts"],"sourcesContent":["import { Database } from './Database.js';\nimport { Model } from './Model.js';\n\nexport class ManyToManyRelation<Key extends keyof any, A extends Model, B extends Model, Link extends Model | undefined = undefined> {\n modelA: { new (): A } & typeof Model;\n modelB: { new (): B } & typeof Model;\n modelLink?: { new(): Link } & typeof Model;\n\n /**\n * E.g. parents\n */\n modelKey: Key;\n\n /**\n * Sort the loading of this relation\n */\n sortKey: string | undefined;\n sortOrder: 'ASC' | 'DESC' = 'ASC';\n\n /**\n * E.g. _models_parents\n */\n get linkTable(): string {\n if (this.modelLink) {\n return this.modelLink.table;\n }\n return '_' + [this.modelA.table, this.modelB.table].sort().join('_');\n }\n\n /**\n * e.g. modelsId\n */\n get linkKeyA(): string {\n return (\n this.modelA.table\n + this.modelA.primary.name.charAt(0).toUpperCase()\n + this.modelA.primary.name.substring(1)\n + ((this.modelA as any) === this.modelB ? 'A' : '')\n );\n }\n\n /**\n * e.g. parentsId\n */\n get linkKeyB(): string {\n return (\n this.modelB.table\n + this.modelB.primary.name.charAt(0).toUpperCase()\n + this.modelB.primary.name.substring(1)\n + ((this.modelA as any) === this.modelB ? 'B' : '')\n );\n }\n\n constructor(modelA: { new(): A } & typeof Model, modelB: { new(): B } & typeof Model, modelKey: Key, modelLink?: { new(): Link } & typeof Model) {\n this.modelA = modelA;\n this.modelB = modelB;\n this.modelKey = modelKey;\n this.modelLink = modelLink;\n }\n\n reverse<Key2 extends keyof any>(modelKey: Key2): ManyToManyRelation<Key2, B, A, Link> {\n return new ManyToManyRelation<Key2, B, A, Link>(this.modelB, this.modelA, modelKey, this.modelLink);\n }\n\n setSort(key: string, order: 'ASC' | 'DESC' = 'ASC'): this {\n this.sortKey = key;\n this.sortOrder = order;\n return this;\n }\n\n /// Generate a join query\n joinQuery(namespaceA: string, namespaceB: string): string {\n const linkNamespace = namespaceA + '_' + namespaceB;\n let str = `LEFT JOIN ${this.linkTable} as ${linkNamespace} on ${linkNamespace}.${this.linkKeyA} = ${namespaceA}.${this.modelA.primary.name}\\n`;\n str += `LEFT JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}`;\n return str;\n }\n\n orderByQuery(namespaceA: string, namespaceB: string): string {\n if (this.sortKey === undefined) {\n return '';\n }\n const linkNamespace = namespaceA + '_' + namespaceB;\n let str = `\\nORDER BY ${linkNamespace}.${this.sortKey}`;\n if (this.sortOrder === 'DESC') {\n str += ' DESC';\n }\n return str + '\\n';\n }\n\n /// Load the relation of a model and return the loaded models\n async load(modelA: A, sorted = true, where?: object, whereLink?: object): Promise<(B & { _link: Link })[]> {\n const namespaceB = 'B';\n const linkNamespace = 'A_B';\n let select = this.modelB.getDefaultSelect(namespaceB);\n\n if (this.modelLink) {\n select += ', ' + this.modelLink.getDefaultSelect(linkNamespace);\n }\n\n let str = `SELECT ${select} FROM ${this.linkTable} as ${linkNamespace}\\n`;\n str += `JOIN ${this.modelB.table} as ${namespaceB} on ${linkNamespace}.${this.linkKeyB} = ${namespaceB}.${this.modelB.primary.name}\\n`;\n str += `WHERE ${linkNamespace}.${this.linkKeyA} = ?`;\n\n const params = [modelA.getPrimaryKey()];\n if (where) {\n for (const key in where) {\n if (Object.hasOwnProperty.call(where, key)) {\n str += ` AND ${namespaceB}.\\`${key}\\` = ?`;\n params.push(where[key] as string);\n }\n }\n }\n if (whereLink) {\n for (const key in whereLink) {\n if (Object.hasOwnProperty.call(whereLink, key)) {\n str += ` AND ${linkNamespace}.\\`${key}\\` = ?`;\n params.push(whereLink[key] as string);\n }\n }\n }\n if (sorted) {\n str += this.orderByQuery('A', 'B');\n }\n\n const [rows] = await Database.select(str, params);\n const modelsB = this.modelB.fromRows(rows, namespaceB) as (B & { _link: Link })[];\n\n // Also load link table if possible\n if (this.modelLink) {\n for (const row of rows) {\n const model = this.modelLink.fromRow(row[linkNamespace]) as Link;\n\n // Fin modelB\n const modelB = modelsB.find(m => m.getPrimaryKey() === row[linkNamespace][this.linkKeyB]);\n\n if (!modelB) {\n throw new Error('Unexpected linking');\n }\n\n // Save link\n modelB._link = model;\n }\n }\n\n modelA.setManyRelation(this, modelsB);\n return modelsB;\n }\n\n /// Whether this relation is loaded\n isLoaded<T extends A>(model: T): model is T & Record<Key, B[]> {\n // Also not loaded if null, since it should be an empty array or an array if it is loaded\n return Array.isArray((model as any)[this.modelKey]);\n }\n\n async setLinkTable(modelA: A, modelB: B, linkTableValues: { [key: string]: any }) {\n const str = `UPDATE ${this.linkTable} SET ? WHERE ${Database.escapeId(this.linkKeyA)} = ? AND ${Database.escapeId(this.linkKeyB)} = ?`;\n\n const [result] = await Database.update(str, [linkTableValues, modelA.getPrimaryKey(), modelB.getPrimaryKey()]);\n if (result.changedRows !== 1) {\n // Todo: add option to fail silently\n throw new Error('Failed to update link table. Check if combination exists');\n }\n }\n\n async linkIds(modelA: string | number, modelsB: (string | number)[], linkTableValues?: { [key: string]: any[] }): Promise<number> {\n if (modelsB.length === 0) {\n return 0;\n }\n // Nested arrays are turned into grouped lists (for bulk inserts), e.g. [['a', 'b'], ['c', 'd']] turns into ('a', 'b'), ('c', 'd')\n let result: {\n affectedRows: number;\n };\n if (linkTableValues !== undefined) {\n const linkTableKeys: string[] = Object.keys(linkTableValues);\n\n for (const property in linkTableValues) {\n if (Object.hasOwnProperty.call(linkTableValues, property)) {\n if (linkTableValues[property].length !== modelsB.length) {\n throw new Error(\n 'Amount of link table values for key '\n + property\n + ' ('\n + linkTableValues[property].length\n + ') are not equal to amount of models linked ('\n + modelsB.length\n + ')',\n );\n }\n }\n }\n\n const query = `INSERT INTO ${Database.escapeId(this.linkTable)} (\n ${Database.escapeId(this.linkKeyA)}, \n ${Database.escapeId(this.linkKeyB)}, \n ${linkTableKeys.map(k => Database.escapeId(k)).join(', ')}\n ) VALUES ?`;\n [result] = await Database.insert(query, [modelsB.map((modelB, i) => [modelA, modelB, ...linkTableKeys.map(k => linkTableValues[k][i])])]);\n }\n else {\n const query = `INSERT INTO ${Database.escapeId(this.linkTable)} (\n ${Database.escapeId(this.linkKeyA)}, \n ${Database.escapeId(this.linkKeyB)}\n ) VALUES ?`;\n [result] = await Database.insert(query, [modelsB.map(modelB => [modelA, modelB])]);\n }\n return result.affectedRows;\n }\n\n async link(modelA: A, modelsB: B[], linkTableValues?: { [key: string]: any[] }): Promise<void> {\n const modelAId = modelA.getPrimaryKey();\n if (!modelAId) {\n throw new Error('Cannot link if model is not saved yet');\n }\n\n const affectedRows = await this.linkIds(\n modelAId,\n modelsB.map((modelB) => {\n const id = modelB.getPrimaryKey();\n if (!id) {\n throw new Error('Cannot link to a model that is not saved yet');\n }\n return id;\n }),\n linkTableValues,\n );\n\n // If the relation is loaded, also modify the value of the relation\n if (this.isLoaded(modelA)) {\n if (affectedRows === modelsB.length) {\n const arr: B[] = (modelA as any)[this.modelKey];\n arr.push(...modelsB);\n }\n else {\n // This could happen in race conditions and simultanious requests\n\n console.warn('Warning: linking expected to affect ' + modelsB.length + ' rows, but only affected ' + affectedRows + ' rows');\n\n // TODO: Manually correct by doing a query (safest)\n throw new Error('Fallback behaviour net yet implemented');\n }\n }\n }\n\n /**\n * Delete all the links from modelA for this relation\n * @param modelA\n */\n async clearId(modelA: string | number): Promise<void> {\n const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ?`;\n\n // Arrays are turned into list, e.g. ['a', 'b'] turns into 'a', 'b'\n const [result] = await Database.delete(query, [modelA]);\n\n if (result.affectedRows === 0 && Model.debug) {\n console.warn(\"Cleared many to many relation, but didn't deleted any entries\");\n }\n }\n\n /**\n * Delete all the links from modelA for this relation\n * @param modelA\n */\n async clear(modelA: A): Promise<void> {\n await this.clearId(modelA.getPrimaryKey()!);\n modelA.setManyRelation(this, []);\n }\n\n /**\n * Delete all the links from modelA for this relation\n * @param modelA\n */\n async syncId(modelA: string | number, modelsB: (string | number)[], linkTableValues?: { [key: string]: any[] }): Promise<void> {\n // todo: add transaction\n await this.clearId(modelA);\n await this.linkIds(modelA, modelsB, linkTableValues);\n }\n\n async unlinkIds(modelA: string | number, ...modelsB: (string | number)[]): Promise<{ affectedRows: number }> {\n const query = `DELETE FROM ${this.linkTable} WHERE ${this.linkKeyA} = ? AND ${this.linkKeyB} IN (?)`;\n\n // Arrays are turned into list, e.g. ['a', 'b'] turns into 'a', 'b'\n const [result] = await Database.delete(query, [modelA, modelsB]);\n\n return result;\n }\n\n async unlink(modelA: A, ...modelsB: B[]): Promise<void> {\n const result = await this.unlinkIds(modelA.getPrimaryKey()!, ...modelsB.map(modelB => modelB.getPrimaryKey()!));\n\n if (this.isLoaded(modelA)) {\n if (result.affectedRows === modelsB.length) {\n const arr: B[] = (modelA as any)[this.modelKey];\n const idMap = modelsB.map(model => model.getPrimaryKey());\n modelA.setManyRelation(\n this,\n arr.filter((model) => {\n return !idMap.includes(model.getPrimaryKey());\n }),\n );\n }\n else {\n // This could happen in race conditions and simultanious requests\n console.warn('Warning: unlinking expected to affect ' + modelsB.length + ' rows, but only affected ' + result.affectedRows + ' rows');\n\n // TODO: Manually correct by doing a query (safest)\n throw new Error('Fallback behaviour net yet implemented');\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ const require_Database = require("./Database.cjs");
2
+ //#region src/classes/ManyToOneRelation.ts
3
+ var ManyToOneRelation = class {
4
+ model;
5
+ /**
6
+ * E.g. addressId
7
+ */
8
+ foreignKey;
9
+ /**
10
+ * E.g. address
11
+ */
12
+ modelKey;
13
+ constructor(model, modelKey) {
14
+ this.model = model;
15
+ this.modelKey = modelKey;
16
+ }
17
+ isLoaded(model) {
18
+ return model[this.modelKey] !== void 0;
19
+ }
20
+ isSet(model) {
21
+ return model[this.modelKey] !== void 0 && model[this.modelKey] !== null;
22
+ }
23
+ joinQuery(namespaceA, namespaceB) {
24
+ return `LEFT JOIN ${this.model.table} as ${namespaceB} on ${namespaceB}.${this.model.primary.name} = ${namespaceA}.${this.foreignKey}\n`;
25
+ }
26
+ async load(modelsA) {
27
+ if (modelsA.length === 0) return [];
28
+ let str = `SELECT ${this.model.getDefaultSelect()} FROM ${this.model.table}\n`;
29
+ str += `WHERE ${this.model.primary.name} IN (?)`;
30
+ const [rows] = await require_Database.Database.select(str, [modelsA.map((m) => m[this.foreignKey])]);
31
+ const modelsB = this.model.fromRows(rows, this.model.table);
32
+ for (const model of modelsA) {
33
+ const found = modelsB.find((m) => m.getPrimaryKey() === model[this.foreignKey]);
34
+ if (!found) throw new Error("Could not load many to one relation: no match found when loading");
35
+ model.setRelation(this, found);
36
+ }
37
+ return modelsA;
38
+ }
39
+ };
40
+ //#endregion
41
+ exports.ManyToOneRelation = ManyToOneRelation;
@@ -0,0 +1,26 @@
1
+ import { Model } from "./Model.cjs";
2
+
3
+ //#region src/classes/ManyToOneRelation.d.ts
4
+ declare class ManyToOneRelation<Key extends keyof any, M extends Model> {
5
+ model: {
6
+ new (): M;
7
+ } & typeof Model;
8
+ /**
9
+ * E.g. addressId
10
+ */
11
+ foreignKey: string;
12
+ /**
13
+ * E.g. address
14
+ */
15
+ modelKey: Key;
16
+ constructor(model: {
17
+ new (): M;
18
+ } & typeof Model, modelKey: Key);
19
+ isLoaded(model: Model): boolean;
20
+ isSet(model: Model): boolean;
21
+ joinQuery(namespaceA: string, namespaceB: string): string;
22
+ load<A extends Model>(modelsA: A[]): Promise<(A & Record<Key, M>)[]>;
23
+ }
24
+ //#endregion
25
+ export { ManyToOneRelation };
26
+ //# sourceMappingURL=ManyToOneRelation.d.cts.map