adminizer 4.1.0-build.18 → 4.1.0-build.19

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.
@@ -4,6 +4,7 @@ export declare function mapSequelizeToWaterline(model: ModelStatic<any>): Record
4
4
  export declare class SequelizeModel<T> extends AbstractModel<T> {
5
5
  private model;
6
6
  constructor(modelName: string, model: ModelStatic<any>);
7
+ _assignAssociations(instance: any, assocData: Record<string, any>): Promise<void>;
7
8
  protected _create(data: Record<string, any>): Promise<T>;
8
9
  protected _findOne(criteria: Partial<T>): Promise<T | null>;
9
10
  protected _find(criteria?: Partial<T>, options?: FindOptions): Promise<T[]>;
@@ -136,23 +136,6 @@ export function mapSequelizeToWaterline(model) {
136
136
  }
137
137
  return result;
138
138
  }
139
- // function resolveType(type: any): AbstractFieldType {
140
- // try {
141
- // const sqlType = typeof type.toString === "function"
142
- // ? type.toString().toLowerCase()
143
- // : "";
144
- // if (sqlType.includes("string")) return "string";
145
- // if (sqlType.includes("uuid")) return "string";
146
- // if (sqlType.includes("int") || sqlType.includes("float") || sqlType.includes("decimal")) return "number";
147
- // if (sqlType.includes("bool")) return "boolean";
148
- // if (sqlType.includes("json")) return "json";
149
- // if (sqlType.includes("date")) return "string";
150
- // return "ref";
151
- // } catch {
152
- // return "ref";
153
- // }
154
- // }
155
- /** SequelizeModel — реализация модели, совместимая с AbstractModel */
156
139
  function capitalize(str) {
157
140
  return str.charAt(0).toUpperCase() + str.slice(1);
158
141
  }
@@ -243,6 +226,33 @@ export class SequelizeModel extends AbstractModel {
243
226
  super(modelName, mapSequelizeToWaterline(model), model.primaryKeyAttribute, model.name);
244
227
  this.model = model;
245
228
  }
229
+ async _assignAssociations(instance, assocData) {
230
+ for (const [alias, ids] of Object.entries(assocData)) {
231
+ const assoc = this.model.associations[alias];
232
+ if (!assoc)
233
+ continue;
234
+ //@ts-ignore
235
+ const { set: setAccessor, add: addAccessor } = assoc.accessors;
236
+ if (Array.isArray(ids)) {
237
+ if (typeof instance[setAccessor] === 'function') {
238
+ await instance[setAccessor](ids);
239
+ continue;
240
+ }
241
+ if (typeof instance[addAccessor] === 'function') {
242
+ for (const id of ids) {
243
+ await instance[addAccessor](id);
244
+ }
245
+ continue;
246
+ }
247
+ }
248
+ if (typeof instance[setAccessor] === 'function') {
249
+ await instance[setAccessor](ids);
250
+ }
251
+ else if (typeof instance[addAccessor] === 'function') {
252
+ await instance[addAccessor](ids);
253
+ }
254
+ }
255
+ }
246
256
  // --- CREATE ---
247
257
  async _create(data) {
248
258
  // console.clear()
@@ -389,26 +399,79 @@ export class SequelizeModel extends AbstractModel {
389
399
  async _updateOne(criteria, data) {
390
400
  const { where } = convertWaterlineCriteriaToSequelizeOptions(criteria);
391
401
  const record = await this.model.findOne({ where });
392
- if (!record) {
402
+ if (!record)
393
403
  return null;
404
+ const assocNames = Object.keys(this.model.associations);
405
+ const plainData = {};
406
+ const assocData = {};
407
+ for (const [key, val] of Object.entries(data)) {
408
+ if (assocNames.includes(key)) {
409
+ assocData[key] = val;
410
+ }
411
+ else {
412
+ plainData[key] = val;
413
+ }
394
414
  }
395
- await record.update(data);
396
- const result = await this.model.findByPk(record.get(this.primaryKey), { raw: true });
397
- return result;
415
+ await record.update(plainData);
416
+ await this._assignAssociations(record, assocData);
417
+ await record.reload({ include: Object.values(this.model.associations) });
418
+ return record.get({ plain: true });
398
419
  }
399
420
  // --- UPDATE MANY ---
400
421
  async _update(criteria, data) {
401
422
  const { where } = convertWaterlineCriteriaToSequelizeOptions(criteria);
402
- await this.model.update(data, { where });
403
- const result = await this.model.findAll({ where, raw: true });
404
- return result;
423
+ const assocNames = Object.keys(this.model.associations);
424
+ const plainData = {};
425
+ const assocData = {};
426
+ for (const [key, val] of Object.entries(data)) {
427
+ if (assocNames.includes(key)) {
428
+ assocData[key] = val;
429
+ }
430
+ else {
431
+ plainData[key] = val;
432
+ }
433
+ }
434
+ const records = await this.model.findAll({ where });
435
+ for (const record of records) {
436
+ await record.update(plainData);
437
+ await this._assignAssociations(record, assocData);
438
+ }
439
+ const reloaded = await this.model.findAll({
440
+ where,
441
+ include: Object.values(this.model.associations)
442
+ });
443
+ return reloaded.map(r => r.get({ plain: true }));
405
444
  }
406
445
  // --- DESTROY ONE ---
407
446
  async _destroyOne(criteria) {
408
447
  const { where } = convertWaterlineCriteriaToSequelizeOptions(criteria);
409
448
  const record = await this.model.findOne({ where });
410
- if (!record) {
449
+ if (!record)
411
450
  return null;
451
+ const assocNames = Object.keys(this.model.associations);
452
+ for (const alias of assocNames) {
453
+ const assoc = this.model.associations[alias];
454
+ // @ts-ignore: accessors should exist
455
+ const getAccessor = assoc.accessors?.get;
456
+ if (typeof record[getAccessor] === "function") {
457
+ try {
458
+ const related = await record[getAccessor]();
459
+ // 🧹 Удаляем связанные записи
460
+ if (Array.isArray(related)) {
461
+ for (const r of related) {
462
+ if (typeof r.destroy === "function") {
463
+ await r.destroy();
464
+ }
465
+ }
466
+ }
467
+ else if (related && typeof related.destroy === "function") {
468
+ await related.destroy();
469
+ }
470
+ }
471
+ catch (e) {
472
+ // console.warn(`Failed to fetch/delete relation "${alias}":`, e);
473
+ }
474
+ }
412
475
  }
413
476
  const raw = record.get({ plain: true });
414
477
  await record.destroy();
@@ -418,6 +481,35 @@ export class SequelizeModel extends AbstractModel {
418
481
  async _destroy(criteria) {
419
482
  const { where } = convertWaterlineCriteriaToSequelizeOptions(criteria);
420
483
  const records = await this.model.findAll({ where });
484
+ const assocNames = Object.keys(this.model.associations);
485
+ for (const record of records) {
486
+ for (const alias of assocNames) {
487
+ const assoc = this.model.associations[alias];
488
+ // 🛑 Не трогаем родительские связи
489
+ if (assoc.associationType === "BelongsTo")
490
+ continue;
491
+ // @ts-ignore accessor exists
492
+ const getAccessor = assoc.accessors?.get;
493
+ if (typeof record[getAccessor] === "function") {
494
+ try {
495
+ const related = await record[getAccessor]();
496
+ if (Array.isArray(related)) {
497
+ for (const rel of related) {
498
+ if (typeof rel.destroy === "function") {
499
+ await rel.destroy();
500
+ }
501
+ }
502
+ }
503
+ else if (related && typeof related.destroy === "function") {
504
+ await related.destroy();
505
+ }
506
+ }
507
+ catch (e) {
508
+ // console.warn(`Failed to delete relation ${alias}:`, e);
509
+ }
510
+ }
511
+ }
512
+ }
421
513
  const raw = records.map(r => r.get({ plain: true }));
422
514
  await this.model.destroy({ where });
423
515
  return raw;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "adminizer",
3
3
  "type": "module",
4
- "version": "4.1.0-build.18",
4
+ "version": "4.1.0-build.19",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "vitest --reporter verbose",