sonamu 0.7.14 → 0.7.16

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 (46) hide show
  1. package/dist/api/sonamu.d.ts.map +1 -1
  2. package/dist/api/sonamu.js +4 -3
  3. package/dist/database/base-model.d.ts +16 -6
  4. package/dist/database/base-model.d.ts.map +1 -1
  5. package/dist/database/base-model.js +44 -3
  6. package/dist/database/base-model.types.d.ts +29 -48
  7. package/dist/database/base-model.types.d.ts.map +1 -1
  8. package/dist/database/base-model.types.js +12 -2
  9. package/dist/database/puri.d.ts +2 -1
  10. package/dist/database/puri.d.ts.map +1 -1
  11. package/dist/database/puri.js +2 -1
  12. package/dist/database/puri.types.d.ts +3 -3
  13. package/dist/database/puri.types.d.ts.map +1 -1
  14. package/dist/database/puri.types.js +1 -1
  15. package/dist/entity/entity-manager.d.ts +8 -4
  16. package/dist/entity/entity-manager.d.ts.map +1 -1
  17. package/dist/entity/entity.d.ts +10 -1
  18. package/dist/entity/entity.d.ts.map +1 -1
  19. package/dist/entity/entity.js +84 -39
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  23. package/dist/tasks/workflow-manager.d.ts +3 -3
  24. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  25. package/dist/tasks/workflow-manager.js +15 -11
  26. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  27. package/dist/template/implementations/generated.template.js +8 -6
  28. package/dist/types/types.d.ts +41 -11
  29. package/dist/types/types.d.ts.map +1 -1
  30. package/dist/types/types.js +27 -3
  31. package/dist/ui/api.d.ts.map +1 -1
  32. package/dist/ui/api.js +12 -3
  33. package/dist/ui-web/assets/{index-J9MCfjCd.js → index-BcbbB-BB.js} +42 -42
  34. package/dist/ui-web/index.html +1 -1
  35. package/package.json +3 -3
  36. package/src/api/sonamu.ts +3 -2
  37. package/src/database/base-model.ts +66 -11
  38. package/src/database/base-model.types.ts +79 -76
  39. package/src/database/puri.ts +5 -1
  40. package/src/database/puri.types.ts +3 -6
  41. package/src/entity/entity.ts +83 -34
  42. package/src/index.ts +1 -0
  43. package/src/tasks/workflow-manager.ts +16 -12
  44. package/src/template/implementations/generated.template.ts +17 -3
  45. package/src/types/types.ts +31 -2
  46. package/src/ui/api.ts +11 -2
@@ -14,12 +14,15 @@ import {
14
14
  isBelongsToOneRelationProp,
15
15
  isEnumProp,
16
16
  isHasManyRelationProp,
17
+ isInternalSubsetField,
17
18
  isManyToManyRelationProp,
18
19
  isOneToOneRelationProp,
19
20
  isRelationProp,
21
+ isVirtualCodeProp,
20
22
  isVirtualProp,
23
+ normalizeSubsetField,
21
24
  type RelationProp,
22
- type StringProp,
25
+ type SubsetField,
23
26
  type SubsetQuery,
24
27
  } from "../types/types";
25
28
  import { importMembers } from "../utils/esm-utils";
@@ -50,6 +53,9 @@ export class Entity {
50
53
  subsets: {
51
54
  [key: string]: string[];
52
55
  };
56
+ subsetsInternal: {
57
+ [key: string]: string[];
58
+ };
53
59
  types: {
54
60
  [name: string]: z.ZodTypeAny;
55
61
  } = {};
@@ -98,8 +104,13 @@ export class Entity {
98
104
  // indexes
99
105
  this.indexes = indexes ?? [];
100
106
 
101
- // subsets
102
- this.subsets = subsets ?? {};
107
+ // subsets: SubsetField[]를 파싱하여 subsets(일반)와 subsetsInternal(internal)로 분리
108
+ this.subsets = {};
109
+ this.subsetsInternal = {};
110
+ for (const [key, fields] of Object.entries(subsets ?? {})) {
111
+ this.subsets[key] = fields.filter((f) => !isInternalSubsetField(f)).map(normalizeSubsetField);
112
+ this.subsetsInternal[key] = fields.filter(isInternalSubsetField).map(normalizeSubsetField);
113
+ }
103
114
 
104
115
  // enums
105
116
  this.enumLabels = enums ?? {};
@@ -117,11 +128,18 @@ export class Entity {
117
128
  };
118
129
  }
119
130
 
131
+ /**
132
+ * 쿼리용 서브셋 필드를 반환합니다 (subsets + subsetsInternal 합침)
133
+ */
134
+ getSubsetFieldsForQuery(subsetKey: string): string[] {
135
+ return [...(this.subsets[subsetKey] ?? []), ...(this.subsetsInternal[subsetKey] ?? [])];
136
+ }
137
+
120
138
  /**
121
139
  * 주어진 이름(subsetKey)의 subset을 실제로 가져오는 Puri 코드 구현체 string을 반환합니다.
122
140
  */
123
141
  getPuriSubsetQuery(subsetKey: string): string {
124
- const subset = this.subsets[subsetKey];
142
+ const subset = this.getSubsetFieldsForQuery(subsetKey);
125
143
  const subsetQuery = this.resolveSubsetQuery("", subset);
126
144
 
127
145
  const lines: string[] = [];
@@ -148,7 +166,6 @@ export class Entity {
148
166
 
149
167
  // select - 입체적 구조로 생성
150
168
  const selectObj = this.buildNestedSelectObject(subsetQuery.select);
151
-
152
169
  lines.push(`.select(${this.stringifyNestedSelectObject(selectObj)});`);
153
170
 
154
171
  return lines.join("\n");
@@ -263,7 +280,7 @@ export class Entity {
263
280
  }
264
281
 
265
282
  getPuriLoaderQuery(subsetKey: string): string {
266
- const subset = this.subsets[subsetKey];
283
+ const subset = this.getSubsetFieldsForQuery(subsetKey);
267
284
  const { loaders } = this.resolveSubsetQuery("", subset);
268
285
 
269
286
  const lines: string[] = [`[`];
@@ -370,7 +387,7 @@ export class Entity {
370
387
  subset SELECT/JOIN/LOADER 결과 리턴
371
388
  */
372
389
  getSubsetQuery(subsetKey: string): SubsetQuery {
373
- const subset = this.subsets[subsetKey];
390
+ const subset = this.getSubsetFieldsForQuery(subsetKey);
374
391
 
375
392
  const result: SubsetQuery = this.resolveSubsetQuery("", subset);
376
393
  return result;
@@ -404,12 +421,16 @@ export class Entity {
404
421
  // 현재 테이블 필드셋은 select, virtual에 추가하고 리턴
405
422
  if (groupKey === "") {
406
423
  const realFields = fields.filter((field) => !isVirtualProp(this.propsDict[field]));
407
- const virtualFields = fields.filter((field) => isVirtualProp(this.propsDict[field]));
424
+ // virtualType: "code" (또는 undefined) virtual prop만 r.virtual에 추가
425
+ // virtualType: "query"인 경우 사용자가 appendSelect로 직접 추가하므로 제외
426
+ const virtualCodeFields = fields.filter((field) =>
427
+ isVirtualCodeProp(this.propsDict[field]),
428
+ );
408
429
 
409
430
  if (prefix === "") {
410
431
  // 현재 테이블인 경우
411
432
  r.select = r.select.concat(realFields.map((field) => `${this.table}.${field}`));
412
- r.virtual = r.virtual.concat(virtualFields);
433
+ r.virtual = r.virtual.concat(virtualCodeFields);
413
434
  } else {
414
435
  // 넘어온 테이블인 경우
415
436
  r.select = r.select.concat(
@@ -605,25 +626,12 @@ export class Entity {
605
626
  },
606
627
  );
607
628
 
608
- return Object.keys(groups).flatMap((key) => {
629
+ return Object.keys(groups).flatMap<EntityPropNode, EntityPropNode[]>((key) => {
609
630
  const group = groups[key];
610
631
 
611
632
  // 일반 prop 처리
612
633
  if (key === "") {
613
634
  return group.map((propName) => {
614
- // FIXME: 이거 나중에 없애야함
615
- if (propName === "말도안되는프롭명__이거왜타입처리가꼬여서이러지?") {
616
- return {
617
- nodeType: "plain" as const,
618
- prop: {
619
- type: "string",
620
- name: "uuid",
621
- length: 128,
622
- } as StringProp,
623
- children: [],
624
- } as EntityPropNode;
625
- }
626
-
627
635
  const prop = entity.props.find((p) => p.name === propName);
628
636
  if (prop === undefined) {
629
637
  console.log({ propName, groups });
@@ -632,7 +640,6 @@ export class Entity {
632
640
  return {
633
641
  nodeType: "plain" as const,
634
642
  prop,
635
- children: [],
636
643
  };
637
644
  });
638
645
  }
@@ -656,7 +663,6 @@ export class Entity {
656
663
  name: `${key}_id`,
657
664
  nullable: prop.nullable,
658
665
  },
659
- children: [],
660
666
  };
661
667
  }
662
668
  }
@@ -671,9 +677,9 @@ export class Entity {
671
677
  : ("array" as const);
672
678
 
673
679
  return {
680
+ nodeType,
674
681
  prop,
675
682
  children,
676
- nodeType,
677
683
  };
678
684
  });
679
685
  }
@@ -793,6 +799,17 @@ export class Entity {
793
799
  }
794
800
 
795
801
  toJson(): EntityJson {
802
+ // subsets와 subsetsInternal을 SubsetField[] 형태로 복원
803
+ const subsets: { [key: string]: SubsetField[] } = {};
804
+ for (const key of Object.keys(this.subsets)) {
805
+ const normalFields: SubsetField[] = this.subsets[key];
806
+ const internalFields: SubsetField[] = (this.subsetsInternal[key] ?? []).map((field) => ({
807
+ field,
808
+ internal: true,
809
+ }));
810
+ subsets[key] = [...normalFields, ...internalFields];
811
+ }
812
+
796
813
  return {
797
814
  id: this.id,
798
815
  parentId: this.parentId,
@@ -800,7 +817,7 @@ export class Entity {
800
817
  title: this.title,
801
818
  props: this.props,
802
819
  indexes: this.indexes,
803
- subsets: this.subsets,
820
+ subsets,
804
821
  enums: this.enumLabels,
805
822
  };
806
823
  }
@@ -810,7 +827,12 @@ export class Entity {
810
827
  const subsetRows = this.getSubsetRows();
811
828
  this.subsets = Object.fromEntries(
812
829
  Object.entries(this.subsets).map(([subsetKey]) => {
813
- return [subsetKey, this.subsetRowsToSubsetFields(subsetRows, subsetKey)];
830
+ return [subsetKey, this.subsetRowsToSubsetFields(subsetRows, subsetKey, false)];
831
+ }),
832
+ );
833
+ this.subsetsInternal = Object.fromEntries(
834
+ Object.entries(this.subsetsInternal).map(([subsetKey]) => {
835
+ return [subsetKey, this.subsetRowsToSubsetFields(subsetRows, subsetKey, true)];
814
836
  }),
815
837
  );
816
838
 
@@ -828,6 +850,7 @@ export class Entity {
828
850
 
829
851
  getSubsetRows(
830
852
  _subsets?: { [key: string]: string[] },
853
+ _subsetsInternal?: { [key: string]: string[] },
831
854
  prefixes: string[] = [],
832
855
  ): EntitySubsetRow[] {
833
856
  if (prefixes.length > 10) {
@@ -835,16 +858,23 @@ export class Entity {
835
858
  }
836
859
 
837
860
  const subsets = _subsets ?? this.subsets;
861
+ const subsetsInternal = _subsetsInternal ?? this.subsetsInternal;
838
862
  const subsetKeys = Object.keys(subsets);
839
863
  const allFields = unique(subsetKeys.flatMap((key) => subsets[key]));
864
+ // internal 필드도 allFields에 포함 (relation 탐색용)
865
+ const allInternalFields = unique(subsetKeys.flatMap((key) => subsetsInternal[key] ?? []));
866
+ const combinedFields = unique([...allFields, ...allInternalFields]);
840
867
 
841
868
  return this.props.map((prop) => {
842
869
  if (
843
870
  prop.type === "relation" &&
844
- allFields.find((f) => f.startsWith(`${[...prefixes, prop.name].join(".")}.`))
871
+ combinedFields.find((f) => f.startsWith(`${[...prefixes, prop.name].join(".")}.`))
845
872
  ) {
846
873
  const relEntity = EntityManager.get(prop.with);
847
- const children = relEntity.getSubsetRows(subsets, [...prefixes, `${prop.name}`]);
874
+ const children = relEntity.getSubsetRows(subsets, subsetsInternal, [
875
+ ...prefixes,
876
+ `${prop.name}`,
877
+ ]);
848
878
 
849
879
  return {
850
880
  field: prop.name,
@@ -857,9 +887,15 @@ export class Entity {
857
887
  return [subsetKey, children.every((child) => child.has[subsetKey] === true)];
858
888
  }),
859
889
  ),
890
+ isInternal: Object.fromEntries(
891
+ subsetKeys.map((subsetKey) => {
892
+ return [subsetKey, children.every((child) => child.isInternal[subsetKey] === true)];
893
+ }),
894
+ ),
860
895
  };
861
896
  }
862
897
 
898
+ const field = [...prefixes, prop.name].join(".");
863
899
  return {
864
900
  field: prop.name,
865
901
  children: [],
@@ -869,22 +905,35 @@ export class Entity {
869
905
  subsetKeys.map((subsetKey) => {
870
906
  const subsetFields = subsets[subsetKey];
871
907
  const has = subsetFields.some((f) => {
872
- const field = [...prefixes, prop.name].join(".");
873
908
  return f === field || f.startsWith(`${field}.`);
874
909
  });
875
910
  return [subsetKey, has];
876
911
  }),
877
912
  ),
913
+ isInternal: Object.fromEntries(
914
+ subsetKeys.map((subsetKey) => {
915
+ const internalFields = subsetsInternal[subsetKey] ?? [];
916
+ const isInternal = internalFields.some((f) => {
917
+ return f === field || f.startsWith(`${field}.`);
918
+ });
919
+ return [subsetKey, isInternal];
920
+ }),
921
+ ),
878
922
  };
879
923
  });
880
924
  }
881
925
 
882
- subsetRowsToSubsetFields(subsetRows: EntitySubsetRow[], subsetKey: string): string[] {
926
+ subsetRowsToSubsetFields(
927
+ subsetRows: EntitySubsetRow[],
928
+ subsetKey: string,
929
+ internal: boolean = false,
930
+ ): string[] {
931
+ const hasKey = internal ? "isInternal" : "has";
883
932
  return subsetRows
884
933
  .map((subsetRow) => {
885
934
  if (subsetRow.children.length > 0) {
886
- return this.subsetRowsToSubsetFields(subsetRow.children, subsetKey);
887
- } else if (subsetRow.has[subsetKey]) {
935
+ return this.subsetRowsToSubsetFields(subsetRow.children, subsetKey, internal);
936
+ } else if (subsetRow[hasKey][subsetKey]) {
888
937
  return subsetRow.prefixes.concat(subsetRow.field).join(".");
889
938
  } else {
890
939
  return null;
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export type * from "./api/context";
4
4
  export * from "./api/decorators";
5
5
  export * from "./api/sonamu";
6
6
  export * from "./database/base-model";
7
+ export * from "./database/base-model.types";
7
8
  export * from "./database/db";
8
9
  export * from "./database/puri";
9
10
  export * from "./database/puri.types";
@@ -77,10 +77,14 @@ export class WorkflowManager {
77
77
  }
78
78
  >;
79
79
 
80
- private constructor(backend: BackendPostgres) {
80
+ // BackendPostgres에서 처리하는 것들이 있어서 Knex 커넥션이 아니라 설정값을 넣어줘야함.
81
+ constructor(dbConf: Knex.Config, runMigrations: boolean = true) {
82
+ const backend = new BackendPostgres(dbConf, { runMigrations });
83
+
81
84
  this.#backend = backend;
82
85
  this.#ow = new OpenWorkflow({ backend });
83
86
  this.#worker = null;
87
+
84
88
  this.#workflowsMap = new Map();
85
89
  this.#scheduledTasks = new Map();
86
90
  }
@@ -283,9 +287,18 @@ export class WorkflowManager {
283
287
  }
284
288
 
285
289
  // Worker를 설정 후 시작
286
- async setupWorker(options: WorkflowOptions) {
290
+ setupWorker(options: WorkflowOptions) {
287
291
  this.#worker = this.#ow.newWorker(options);
288
- await this.#worker.start();
292
+ }
293
+
294
+ // Worker를 초기화
295
+ async startWorker() {
296
+ if (!this.#worker) {
297
+ return;
298
+ }
299
+
300
+ await this.#backend.initialize();
301
+ await this.#worker?.start();
289
302
  }
290
303
 
291
304
  // Worker를 중지
@@ -318,13 +331,4 @@ export class WorkflowManager {
318
331
  [Symbol.asyncDispose]() {
319
332
  return this.destroy();
320
333
  }
321
-
322
- // BackendPostgres에서 처리하는 것들이 있어서 Knex 커넥션이 아니라 설정값을 넣어줘야함.
323
- static async create(
324
- dbConf: Knex.Config,
325
- runMigrations: boolean = true,
326
- ): Promise<WorkflowManager> {
327
- const backend = await BackendPostgres.connect(dbConf, { runMigrations });
328
- return new WorkflowManager(backend);
329
- }
330
334
  }
@@ -4,7 +4,12 @@ import { Sonamu } from "../../api";
4
4
  import type { Entity } from "../../entity/entity";
5
5
  import { EntityManager } from "../../entity/entity-manager";
6
6
  import { Naite } from "../../naite/naite";
7
- import { type EntityIndex, type EntityPropNode, isVirtualProp } from "../../types/types";
7
+ import {
8
+ type EntityIndex,
9
+ type EntityPropNode,
10
+ isVirtualCodeProp,
11
+ isVirtualQueryProp,
12
+ } from "../../types/types";
8
13
  import { nonNullable } from "../../utils/utils";
9
14
  import { Template } from "../template";
10
15
  import { propNodeToZodTypeDef, zodTypeToZodCode } from "../zod-converter";
@@ -171,9 +176,14 @@ export class Template__generated extends Template {
171
176
  // TODO: GIN/GiST 인덱스 생성된 컬럼 추출
172
177
  const fulltextColumns: EntityIndex["columns"][] = [];
173
178
 
174
- // virtual props
179
+ // virtual props (virtualType: "code" 또는 undefined인 것만 포함)
175
180
  const virtualProps = entity.props
176
- .filter((prop) => isVirtualProp(prop))
181
+ .filter((prop) => isVirtualCodeProp(prop))
182
+ .map((prop) => prop.name);
183
+
184
+ // query virtual props (virtualType: "query"인 것만 포함)
185
+ const virtualQueryProps = entity.props
186
+ .filter((prop) => isVirtualQueryProp(prop))
177
187
  .map((prop) => prop.name);
178
188
 
179
189
  /**
@@ -209,6 +219,7 @@ export class Template__generated extends Template {
209
219
  const hasMetadata =
210
220
  fulltextColumns.length > 0 ||
211
221
  virtualProps.length > 0 ||
222
+ virtualQueryProps.length > 0 ||
212
223
  hasDefaultColumns.length > 0 ||
213
224
  generatedColumns.length > 0 ||
214
225
  hasVectorColumns.length > 0;
@@ -226,6 +237,9 @@ export class Template__generated extends Template {
226
237
  (virtualProps.length > 0
227
238
  ? `readonly __virtual__: readonly [${virtualProps.map((prop) => `"${prop}"`).join(", ")}],`
228
239
  : "") +
240
+ (virtualQueryProps.length > 0
241
+ ? `readonly __virtual_query__: readonly [${virtualQueryProps.map((prop) => `"${prop}"`).join(", ")}],`
242
+ : "") +
229
243
  (hasDefaultColumns.length > 0
230
244
  ? `readonly __hasDefault__: readonly [${hasDefaultColumns
231
245
  .map((col) => `"${col}"`)
@@ -104,6 +104,7 @@ export type UuidArrayProp = CommonProp & {
104
104
  export type VirtualProp = CommonProp & {
105
105
  type: "virtual";
106
106
  id: string;
107
+ virtualType?: "query" | "code"; // default: "code"
107
108
  }; // PG: none / TS: any(id) / JSON: any
108
109
  export type VectorProp = CommonProp & {
109
110
  type: "vector";
@@ -264,6 +265,17 @@ export type EntityIndex = {
264
265
  */
265
266
  lists?: number;
266
267
  };
268
+
269
+ // SubsetField 타입: string 또는 internal 옵션이 있는 객체
270
+ export type SubsetField = string | { field: string; internal?: boolean };
271
+
272
+ export function normalizeSubsetField(f: SubsetField): string {
273
+ return typeof f === "string" ? f : f.field;
274
+ }
275
+ export function isInternalSubsetField(f: SubsetField): boolean {
276
+ return typeof f !== "string" && f.internal === true;
277
+ }
278
+
267
279
  export type EntityJson = {
268
280
  id: string;
269
281
  parentId?: string;
@@ -272,7 +284,7 @@ export type EntityJson = {
272
284
  props: EntityProp[];
273
285
  indexes: EntityIndex[];
274
286
  subsets: {
275
- [subset: string]: string[];
287
+ [subset: string]: SubsetField[];
276
288
  };
277
289
  enums: {
278
290
  [enumId: string]: {
@@ -285,6 +297,9 @@ export type EntitySubsetRow = {
285
297
  has: {
286
298
  [key: string]: boolean;
287
299
  };
300
+ isInternal: {
301
+ [key: string]: boolean;
302
+ };
288
303
  children: EntitySubsetRow[];
289
304
  prefixes: string[];
290
305
  relationEntity?: string;
@@ -413,6 +428,14 @@ export function isJsonProp(p: unknown): p is JsonProp {
413
428
  export function isVirtualProp(p: unknown): p is VirtualProp {
414
429
  return (p as VirtualProp)?.type === "virtual";
415
430
  }
431
+ export function isVirtualCodeProp(p: unknown): p is VirtualProp {
432
+ if (!isVirtualProp(p)) return false;
433
+ return p.virtualType !== "query"; // undefined도 "code"로 취급
434
+ }
435
+ export function isVirtualQueryProp(p: unknown): p is VirtualProp {
436
+ if (!isVirtualProp(p)) return false;
437
+ return p.virtualType === "query";
438
+ }
416
439
  export function isVectorSingleProp(p: unknown): p is VectorProp {
417
440
  return (p as VectorProp)?.type === "vector";
418
441
  }
@@ -951,6 +974,7 @@ const VirtualPropSchema = z
951
974
  ...BasePropFields,
952
975
  type: z.literal("virtual"),
953
976
  id: z.string(),
977
+ virtualType: z.enum(["query", "code"]).optional(),
954
978
  })
955
979
  .strict();
956
980
 
@@ -1172,7 +1196,12 @@ export const EntityJsonSchema = z
1172
1196
  parentId: z.string().optional().describe("부모 Entity ID"),
1173
1197
  props: z.array(EntityPropSchema),
1174
1198
  indexes: z.array(EntityIndexSchema),
1175
- subsets: z.record(z.string(), z.array(z.string())),
1199
+ subsets: z.record(
1200
+ z.string(),
1201
+ z.array(
1202
+ z.union([z.string(), z.object({ field: z.string(), internal: z.boolean().optional() })]),
1203
+ ),
1204
+ ),
1176
1205
  enums: z.record(z.string(), z.record(z.string(), z.string())),
1177
1206
  })
1178
1207
  .strict();
package/src/ui/api.ts CHANGED
@@ -345,15 +345,23 @@ export async function sonamuUIApiPlugin(fastify: FastifyInstance) {
345
345
  entityId: string;
346
346
  subsetKey: string;
347
347
  fields: string[];
348
+ fieldsInternal?: string[];
348
349
  };
349
350
  }>("/api/entity/modifySubset", async (request) => {
350
351
  return await waitForHMRCompleted(async () => {
351
- const { entityId, subsetKey, fields } = request.body;
352
+ const { entityId, subsetKey, fields, fieldsInternal } = request.body;
352
353
  const entity = EntityManager.get(entityId);
353
354
  entity.subsets[subsetKey] = fields;
355
+ if (fieldsInternal !== undefined) {
356
+ if (fieldsInternal.length > 0) {
357
+ entity.subsetsInternal[subsetKey] = fieldsInternal;
358
+ } else {
359
+ delete entity.subsetsInternal[subsetKey];
360
+ }
361
+ }
354
362
  await entity.save();
355
363
 
356
- return { updated: fields };
364
+ return { updated: fields, updatedInternal: fieldsInternal };
357
365
  });
358
366
  });
359
367
 
@@ -367,6 +375,7 @@ export async function sonamuUIApiPlugin(fastify: FastifyInstance) {
367
375
  const { entityId, subsetKey } = request.body;
368
376
  const entity = EntityManager.get(entityId);
369
377
  delete entity.subsets[subsetKey];
378
+ delete entity.subsetsInternal[subsetKey];
370
379
  await entity.save();
371
380
 
372
381
  return 1;