@tachybase/module-collection 1.3.22 → 1.3.23

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.
@@ -1,10 +1,10 @@
1
1
  module.exports = {
2
- "@tachybase/client": "1.3.22",
3
- "@tachybase/module-error-handler": "1.3.22",
4
- "@tego/server": "1.3.39",
2
+ "@tachybase/client": "1.3.23",
3
+ "@tachybase/module-error-handler": "1.3.23",
4
+ "@tego/server": "1.3.43",
5
5
  "async-mutex": "0.5.0",
6
6
  "lodash": "4.17.21",
7
- "@tachybase/test": "1.3.39",
7
+ "@tachybase/test": "1.3.43",
8
8
  "sequelize": "6.37.5",
9
9
  "dayjs": "1.11.13"
10
10
  };
@@ -122,6 +122,7 @@ function afterCreateForForeignKeyField(db) {
122
122
  source
123
123
  } = model.get();
124
124
  if (source) return;
125
+ if (target === "__temp__") return;
125
126
  if (["oho", "o2m"].includes(interfaceType)) {
126
127
  const values = generateFkOptions(target, foreignKey);
127
128
  await createFieldIfNotExists({
@@ -0,0 +1,2 @@
1
+ import { Database } from '@tego/server';
2
+ export declare function afterUpdateForForeignKeyField(db: Database): (model: any, options: any) => Promise<void>;
@@ -0,0 +1,249 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var afterUpdateForForeignKeyField_exports = {};
19
+ __export(afterUpdateForForeignKeyField_exports, {
20
+ afterUpdateForForeignKeyField: () => afterUpdateForForeignKeyField
21
+ });
22
+ module.exports = __toCommonJS(afterUpdateForForeignKeyField_exports);
23
+ function afterUpdateForForeignKeyField(db) {
24
+ function generateFkOptions(collectionName, foreignKey) {
25
+ const collection = db.getCollection(collectionName);
26
+ if (!collection) {
27
+ throw new Error("collection not found");
28
+ }
29
+ const M = collection.model;
30
+ const attr = M.rawAttributes[foreignKey];
31
+ if (!attr) {
32
+ throw new Error(`${collectionName}.${foreignKey} does not exists`);
33
+ }
34
+ return attribute2field(attr);
35
+ }
36
+ function attribute2field(attribute) {
37
+ let type = "bigInt";
38
+ if (attribute.type.constructor.name === "INTEGER") {
39
+ type = "integer";
40
+ } else if (attribute.type.constructor.name === "STRING") {
41
+ type = "string";
42
+ }
43
+ const name = attribute.fieldName;
44
+ const data = {
45
+ interface: "integer",
46
+ name,
47
+ type,
48
+ uiSchema: {
49
+ type: "number",
50
+ title: name,
51
+ "x-component": "InputNumber",
52
+ "x-read-pretty": true
53
+ }
54
+ };
55
+ if (type === "string") {
56
+ data["interface"] = "input";
57
+ data["uiSchema"] = {
58
+ type: "string",
59
+ title: name,
60
+ "x-component": "Input",
61
+ "x-read-pretty": true
62
+ };
63
+ }
64
+ return data;
65
+ }
66
+ async function createFieldIfNotExists({ values, transaction }) {
67
+ const { collectionName, name } = values;
68
+ if (!collectionName || !name) {
69
+ throw new Error(`field options invalid`);
70
+ }
71
+ const r = db.getRepository("fields");
72
+ const instance = await r.findOne({
73
+ filter: {
74
+ collectionName,
75
+ name
76
+ },
77
+ transaction
78
+ });
79
+ if (instance) {
80
+ if (instance.type !== values.type) {
81
+ throw new Error(`fk type invalid`);
82
+ }
83
+ instance.set("sort", 1);
84
+ instance.set("isForeignKey", true);
85
+ await instance.save({ transaction });
86
+ } else {
87
+ const creatInstance = await r.create({
88
+ values: {
89
+ isForeignKey: true,
90
+ ...values
91
+ },
92
+ transaction
93
+ });
94
+ creatInstance.set("sort", 1);
95
+ await creatInstance.save({ transaction });
96
+ }
97
+ await r.update({
98
+ filter: {
99
+ collectionName,
100
+ options: {
101
+ primaryKey: true
102
+ }
103
+ },
104
+ values: {
105
+ sort: 0
106
+ },
107
+ transaction
108
+ });
109
+ }
110
+ const hook = async (model, { transaction, context }) => {
111
+ var _a;
112
+ if (!context) return;
113
+ const {
114
+ interface: interfaceType,
115
+ collectionName,
116
+ target: newTarget,
117
+ foreignKey: newForeignKey,
118
+ otherKey: newOtherKey,
119
+ through,
120
+ source,
121
+ type
122
+ } = model.get();
123
+ if (source || !interfaceType) return;
124
+ if (newTarget === "__temp__") return;
125
+ const { target: oldTarget, foreignKey: oldForeignKey, otherKey: oldOtherKey } = model.previous("options") || {};
126
+ const fieldsRepo = db.getRepository("fields");
127
+ const hasTargetChanged = oldTarget !== void 0 && oldTarget !== newTarget;
128
+ const hasForeignKeyChanged = oldForeignKey !== void 0 && oldForeignKey !== newForeignKey;
129
+ const hasOtherKeyChanged = oldOtherKey !== void 0 && oldOtherKey !== newOtherKey;
130
+ const needUpdate = hasTargetChanged || hasForeignKeyChanged || hasOtherKeyChanged;
131
+ const collection = db.getCollection(model.get("collectionName"));
132
+ collection == null ? void 0 : collection.updateField(model.get("name"), model.get());
133
+ const field = collection == null ? void 0 : collection.getField(model.get("name"));
134
+ if (!needUpdate) return;
135
+ try {
136
+ (_a = field == null ? void 0 : field.unbind) == null ? void 0 : _a.call(field);
137
+ field.bind();
138
+ } catch (e) {
139
+ throw e;
140
+ }
141
+ async function removeOldForeignKeyField(collection2, fkName) {
142
+ if (!collection2 || !fkName) return;
143
+ const exists = await fieldsRepo.findOne({
144
+ filter: {
145
+ collectionName: collection2,
146
+ name: fkName
147
+ // isForeignKey: true,
148
+ },
149
+ transaction
150
+ });
151
+ if (exists) {
152
+ await fieldsRepo.destroy({
153
+ filter: {
154
+ collectionName: collection2,
155
+ name: fkName
156
+ // isForeignKey: true,
157
+ },
158
+ transaction
159
+ });
160
+ }
161
+ }
162
+ if (["oho", "o2m"].includes(interfaceType)) {
163
+ await removeOldForeignKeyField(oldTarget, oldForeignKey);
164
+ const values = generateFkOptions(newTarget, newForeignKey);
165
+ await createFieldIfNotExists({
166
+ values: {
167
+ collectionName: newTarget,
168
+ ...values
169
+ },
170
+ transaction
171
+ });
172
+ } else if (["obo", "m2o"].includes(interfaceType)) {
173
+ await removeOldForeignKeyField(collectionName, oldForeignKey);
174
+ const values = generateFkOptions(collectionName, newForeignKey);
175
+ await createFieldIfNotExists({
176
+ values: {
177
+ collectionName,
178
+ ...values
179
+ },
180
+ transaction
181
+ });
182
+ } else if (["linkTo", "m2m"].includes(interfaceType)) {
183
+ if (type !== "belongsToMany") {
184
+ return;
185
+ }
186
+ const collectionsRepo = db.getRepository("collections");
187
+ const existingThrough = await collectionsRepo.findOne({
188
+ filter: {
189
+ name: through
190
+ },
191
+ transaction
192
+ });
193
+ if (existingThrough) {
194
+ await collectionsRepo.destroy({
195
+ filter: {
196
+ name: through
197
+ },
198
+ transaction
199
+ });
200
+ }
201
+ await collectionsRepo.create({
202
+ values: {
203
+ name: through,
204
+ title: through,
205
+ timestamps: true,
206
+ autoGenId: false,
207
+ hidden: true,
208
+ autoCreate: true,
209
+ isThrough: true,
210
+ sortable: false
211
+ },
212
+ context,
213
+ transaction
214
+ });
215
+ const opts1 = generateFkOptions(through, newForeignKey);
216
+ const opts2 = generateFkOptions(through, newOtherKey);
217
+ await createFieldIfNotExists({
218
+ values: {
219
+ collectionName: through,
220
+ ...opts1
221
+ },
222
+ transaction
223
+ });
224
+ await createFieldIfNotExists({
225
+ values: {
226
+ collectionName: through,
227
+ ...opts2
228
+ },
229
+ transaction
230
+ });
231
+ }
232
+ await model.migrate({
233
+ isNew: true,
234
+ transaction
235
+ });
236
+ };
237
+ return async (model, options) => {
238
+ try {
239
+ await hook(model, options);
240
+ } catch (error) {
241
+ console.error("Failed to update foreign key field:", error);
242
+ throw error;
243
+ }
244
+ };
245
+ }
246
+ // Annotate the CommonJS export names for ESM import in node:
247
+ 0 && (module.exports = {
248
+ afterUpdateForForeignKeyField
249
+ });
@@ -40,6 +40,7 @@ var import_lodash = __toESM(require("lodash"));
40
40
  var import__ = require(".");
41
41
  var import_collectionImportExportMeta = require("./actions/collectionImportExportMeta");
42
42
  var import_hooks = require("./hooks");
43
+ var import_afterUpdateForForeignKeyField = require("./hooks/afterUpdateForForeignKeyField");
43
44
  var import_beforeCreateForValidateField = require("./hooks/beforeCreateForValidateField");
44
45
  var import_beforeCreateForViewCollection = require("./hooks/beforeCreateForViewCollection");
45
46
  var import_models = require("./models");
@@ -147,6 +148,7 @@ class CollectionManagerPlugin extends import_server.Plugin {
147
148
  model.set("sortBy", model.get("foreignKey") + "Sort");
148
149
  }
149
150
  });
151
+ this.app.db.on("fields.afterUpdate", (0, import_afterUpdateForForeignKeyField.afterUpdateForForeignKeyField)(this.app.db));
150
152
  this.app.db.on("fields.afterUpdate", async (model, { context, transaction }) => {
151
153
  const prevOptions = model.previous("options");
152
154
  const currentOptions = model.get("options");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tachybase/module-collection",
3
3
  "displayName": "Data source: Main",
4
- "version": "1.3.22",
4
+ "version": "1.3.23",
5
5
  "description": "TachyBase main database, supports relational databases such as MySQL, PostgreSQL, SQLite and so on.",
6
6
  "keywords": [
7
7
  "Data sources"
@@ -11,16 +11,16 @@
11
11
  "dependencies": {},
12
12
  "devDependencies": {
13
13
  "@hapi/topo": "^6.0.2",
14
- "@tachybase/test": "^1.3.39",
15
- "@tego/client": "^1.3.39",
16
- "@tego/server": "^1.3.39",
14
+ "@tachybase/test": "^1.3.43",
15
+ "@tego/client": "^1.3.43",
16
+ "@tego/server": "^1.3.43",
17
17
  "@types/lodash": "^4.17.20",
18
18
  "async-mutex": "^0.5.0",
19
19
  "lodash": "4.17.21",
20
20
  "sequelize": "^6.37.5",
21
21
  "toposort": "^2.0.2",
22
- "@tachybase/client": "1.3.22",
23
- "@tachybase/module-error-handler": "1.3.22"
22
+ "@tachybase/client": "1.3.23",
23
+ "@tachybase/module-error-handler": "1.3.23"
24
24
  },
25
25
  "description.zh-CN": "TachyBase 主数据库,支持 MySQL、PostgreSQL、SQLite 等关系型数据库。",
26
26
  "displayName.zh-CN": "数据源:主数据库",