@strapi/content-type-builder 5.17.0 → 5.18.0

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 (43) hide show
  1. package/dist/admin/components/DataManager/DataManagerProvider.js +5 -0
  2. package/dist/admin/components/DataManager/DataManagerProvider.js.map +1 -1
  3. package/dist/admin/components/DataManager/DataManagerProvider.mjs +6 -1
  4. package/dist/admin/components/DataManager/DataManagerProvider.mjs.map +1 -1
  5. package/dist/admin/components/DataManager/utils/cleanData.js +5 -1
  6. package/dist/admin/components/DataManager/utils/cleanData.js.map +1 -1
  7. package/dist/admin/components/DataManager/utils/cleanData.mjs +5 -1
  8. package/dist/admin/components/DataManager/utils/cleanData.mjs.map +1 -1
  9. package/dist/admin/components/FormModal/FormModal.js +16 -1
  10. package/dist/admin/components/FormModal/FormModal.js.map +1 -1
  11. package/dist/admin/components/FormModal/FormModal.mjs +16 -1
  12. package/dist/admin/components/FormModal/FormModal.mjs.map +1 -1
  13. package/dist/admin/pages/ListView/EmptyState.js +27 -19
  14. package/dist/admin/pages/ListView/EmptyState.js.map +1 -1
  15. package/dist/admin/pages/ListView/EmptyState.mjs +29 -21
  16. package/dist/admin/pages/ListView/EmptyState.mjs.map +1 -1
  17. package/dist/admin/src/types.d.ts +3 -0
  18. package/dist/server/controllers/schema.js +2 -1
  19. package/dist/server/controllers/schema.js.map +1 -1
  20. package/dist/server/controllers/schema.mjs +2 -1
  21. package/dist/server/controllers/schema.mjs.map +1 -1
  22. package/dist/server/services/schema-builder/content-type-builder.js +67 -33
  23. package/dist/server/services/schema-builder/content-type-builder.js.map +1 -1
  24. package/dist/server/services/schema-builder/content-type-builder.mjs +67 -33
  25. package/dist/server/services/schema-builder/content-type-builder.mjs.map +1 -1
  26. package/dist/server/services/schema-builder/index.js +6 -2
  27. package/dist/server/services/schema-builder/index.js.map +1 -1
  28. package/dist/server/services/schema-builder/index.mjs +6 -2
  29. package/dist/server/services/schema-builder/index.mjs.map +1 -1
  30. package/dist/server/services/schema.js +5 -1
  31. package/dist/server/services/schema.js.map +1 -1
  32. package/dist/server/services/schema.mjs +5 -1
  33. package/dist/server/services/schema.mjs.map +1 -1
  34. package/dist/server/src/controllers/schema.d.ts.map +1 -1
  35. package/dist/server/src/services/schema-builder/content-type-builder.d.ts +8 -2
  36. package/dist/server/src/services/schema-builder/content-type-builder.d.ts.map +1 -1
  37. package/dist/server/src/services/schema-builder/index.d.ts +6 -2
  38. package/dist/server/src/services/schema-builder/index.d.ts.map +1 -1
  39. package/dist/server/src/services/schema-builder/types.d.ts +23 -0
  40. package/dist/server/src/services/schema-builder/types.d.ts.map +1 -0
  41. package/dist/server/src/services/schema.d.ts +240 -240
  42. package/dist/server/src/services/schema.d.ts.map +1 -1
  43. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"schema.mjs","sources":["../../../server/src/controllers/schema.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { isEmpty } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { validateUpdateSchema } from './validation/schema';\n\nexport default () => {\n const internals = {\n isUpdating: false,\n };\n\n return {\n async getSchema(ctx: Context) {\n const schema = await getService('schema').getSchema();\n\n ctx.send({ data: schema });\n },\n\n async updateSchema(ctx: Context) {\n if (internals.isUpdating === true) {\n return ctx.conflict('Schema update is already in progress.');\n }\n\n try {\n const { data } = await validateUpdateSchema(ctx.request.body);\n\n if (isEmpty(data.components) && isEmpty(data.contentTypes)) {\n ctx.body = {};\n return;\n }\n\n internals.isUpdating = true;\n strapi.reload.isWatching = false;\n\n await getService('schema').updateSchema(data);\n\n // NOTE: we do not set isUpdating to false here.\n // We want to wait for the server to restart to get the isUpdate = false only\n setImmediate(() => {\n strapi.reload();\n });\n\n ctx.body = {};\n } catch (error) {\n internals.isUpdating = false;\n return ctx.send({ error }, 400);\n }\n },\n\n async getUpdateSchemaStatus(ctx: Context) {\n ctx.send({ data: { isUpdating: internals.isUpdating } });\n },\n };\n};\n"],"names":["internals","isUpdating","getSchema","ctx","schema","getService","send","data","updateSchema","conflict","validateUpdateSchema","request","body","isEmpty","components","contentTypes","strapi","reload","isWatching","setImmediate","error","getUpdateSchemaStatus"],"mappings":";;;;AAMA,aAAe,CAAA,IAAA;AACb,IAAA,MAAMA,SAAY,GAAA;QAChBC,UAAY,EAAA;AACd,KAAA;IAEA,OAAO;AACL,QAAA,MAAMC,WAAUC,GAAY,EAAA;AAC1B,YAAA,MAAMC,MAAS,GAAA,MAAMC,UAAW,CAAA,QAAA,CAAA,CAAUH,SAAS,EAAA;AAEnDC,YAAAA,GAAAA,CAAIG,IAAI,CAAC;gBAAEC,IAAMH,EAAAA;AAAO,aAAA,CAAA;AAC1B,SAAA;AAEA,QAAA,MAAMI,cAAaL,GAAY,EAAA;YAC7B,IAAIH,SAAAA,CAAUC,UAAU,KAAK,IAAM,EAAA;gBACjC,OAAOE,GAAAA,CAAIM,QAAQ,CAAC,uCAAA,CAAA;AACtB;YAEA,IAAI;gBACF,MAAM,EAAEF,IAAI,EAAE,GAAG,MAAMG,oBAAqBP,CAAAA,GAAAA,CAAIQ,OAAO,CAACC,IAAI,CAAA;AAE5D,gBAAA,IAAIC,QAAQN,IAAKO,CAAAA,UAAU,KAAKD,OAAQN,CAAAA,IAAAA,CAAKQ,YAAY,CAAG,EAAA;oBAC1DZ,GAAIS,CAAAA,IAAI,GAAG,EAAC;AACZ,oBAAA;AACF;AAEAZ,gBAAAA,SAAAA,CAAUC,UAAU,GAAG,IAAA;gBACvBe,MAAOC,CAAAA,MAAM,CAACC,UAAU,GAAG,KAAA;gBAE3B,MAAMb,UAAAA,CAAW,QAAUG,CAAAA,CAAAA,YAAY,CAACD,IAAAA,CAAAA;;;gBAIxCY,YAAa,CAAA,IAAA;AACXH,oBAAAA,MAAAA,CAAOC,MAAM,EAAA;AACf,iBAAA,CAAA;gBAEAd,GAAIS,CAAAA,IAAI,GAAG,EAAC;AACd,aAAA,CAAE,OAAOQ,KAAO,EAAA;AACdpB,gBAAAA,SAAAA,CAAUC,UAAU,GAAG,KAAA;gBACvB,OAAOE,GAAAA,CAAIG,IAAI,CAAC;AAAEc,oBAAAA;iBAAS,EAAA,GAAA,CAAA;AAC7B;AACF,SAAA;AAEA,QAAA,MAAMC,uBAAsBlB,GAAY,EAAA;AACtCA,YAAAA,GAAAA,CAAIG,IAAI,CAAC;gBAAEC,IAAM,EAAA;AAAEN,oBAAAA,UAAAA,EAAYD,UAAUC;AAAW;AAAE,aAAA,CAAA;AACxD;AACF,KAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"schema.mjs","sources":["../../../server/src/controllers/schema.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { isEmpty } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { validateUpdateSchema } from './validation/schema';\n\nexport default () => {\n const internals = {\n isUpdating: false,\n };\n\n return {\n async getSchema(ctx: Context) {\n const schema = await getService('schema').getSchema();\n\n ctx.send({ data: schema });\n },\n\n async updateSchema(ctx: Context) {\n if (internals.isUpdating === true) {\n return ctx.conflict('Schema update is already in progress.');\n }\n\n try {\n const { data } = await validateUpdateSchema(ctx.request.body);\n\n if (isEmpty(data.components) && isEmpty(data.contentTypes)) {\n ctx.body = {};\n return;\n }\n\n internals.isUpdating = true;\n strapi.reload.isWatching = false;\n\n await getService('schema').updateSchema(data);\n\n // NOTE: we do not set isUpdating to false here.\n // We want to wait for the server to restart to get the isUpdate = false only\n setImmediate(() => {\n strapi.reload();\n });\n\n ctx.body = {};\n } catch (error) {\n internals.isUpdating = false;\n const errorMessage = error instanceof Error ? error.message : String(error);\n return ctx.send({ error: errorMessage }, 400);\n }\n },\n\n async getUpdateSchemaStatus(ctx: Context) {\n ctx.send({ data: { isUpdating: internals.isUpdating } });\n },\n };\n};\n"],"names":["internals","isUpdating","getSchema","ctx","schema","getService","send","data","updateSchema","conflict","validateUpdateSchema","request","body","isEmpty","components","contentTypes","strapi","reload","isWatching","setImmediate","error","errorMessage","Error","message","String","getUpdateSchemaStatus"],"mappings":";;;;AAMA,aAAe,CAAA,IAAA;AACb,IAAA,MAAMA,SAAY,GAAA;QAChBC,UAAY,EAAA;AACd,KAAA;IAEA,OAAO;AACL,QAAA,MAAMC,WAAUC,GAAY,EAAA;AAC1B,YAAA,MAAMC,MAAS,GAAA,MAAMC,UAAW,CAAA,QAAA,CAAA,CAAUH,SAAS,EAAA;AAEnDC,YAAAA,GAAAA,CAAIG,IAAI,CAAC;gBAAEC,IAAMH,EAAAA;AAAO,aAAA,CAAA;AAC1B,SAAA;AAEA,QAAA,MAAMI,cAAaL,GAAY,EAAA;YAC7B,IAAIH,SAAAA,CAAUC,UAAU,KAAK,IAAM,EAAA;gBACjC,OAAOE,GAAAA,CAAIM,QAAQ,CAAC,uCAAA,CAAA;AACtB;YAEA,IAAI;gBACF,MAAM,EAAEF,IAAI,EAAE,GAAG,MAAMG,oBAAqBP,CAAAA,GAAAA,CAAIQ,OAAO,CAACC,IAAI,CAAA;AAE5D,gBAAA,IAAIC,QAAQN,IAAKO,CAAAA,UAAU,KAAKD,OAAQN,CAAAA,IAAAA,CAAKQ,YAAY,CAAG,EAAA;oBAC1DZ,GAAIS,CAAAA,IAAI,GAAG,EAAC;AACZ,oBAAA;AACF;AAEAZ,gBAAAA,SAAAA,CAAUC,UAAU,GAAG,IAAA;gBACvBe,MAAOC,CAAAA,MAAM,CAACC,UAAU,GAAG,KAAA;gBAE3B,MAAMb,UAAAA,CAAW,QAAUG,CAAAA,CAAAA,YAAY,CAACD,IAAAA,CAAAA;;;gBAIxCY,YAAa,CAAA,IAAA;AACXH,oBAAAA,MAAAA,CAAOC,MAAM,EAAA;AACf,iBAAA,CAAA;gBAEAd,GAAIS,CAAAA,IAAI,GAAG,EAAC;AACd,aAAA,CAAE,OAAOQ,KAAO,EAAA;AACdpB,gBAAAA,SAAAA,CAAUC,UAAU,GAAG,KAAA;AACvB,gBAAA,MAAMoB,eAAeD,KAAiBE,YAAAA,KAAAA,GAAQF,KAAMG,CAAAA,OAAO,GAAGC,MAAOJ,CAAAA,KAAAA,CAAAA;gBACrE,OAAOjB,GAAAA,CAAIG,IAAI,CAAC;oBAAEc,KAAOC,EAAAA;iBAAgB,EAAA,GAAA,CAAA;AAC3C;AACF,SAAA;AAEA,QAAA,MAAMI,uBAAsBtB,GAAY,EAAA;AACtCA,YAAAA,GAAAA,CAAIG,IAAI,CAAC;gBAAEC,IAAM,EAAA;AAAEN,oBAAAA,UAAAA,EAAYD,UAAUC;AAAW;AAAE,aAAA,CAAA;AACxD;AACF,KAAA;AACF,CAAA;;;;"}
@@ -16,7 +16,8 @@ const reuseUnsetPreviousProperties = (newAttribute, oldAttribute)=>{
16
16
  'unique',
17
17
  'pluginOptions',
18
18
  'inversedBy',
19
- 'mappedBy'
19
+ 'mappedBy',
20
+ 'conditions'
20
21
  ]));
21
22
  };
22
23
  function createComponentBuilder() {
@@ -33,19 +34,24 @@ function createComponentBuilder() {
33
34
  if (!attribute.targetAttribute) {
34
35
  return;
35
36
  }
37
+ // When generating the inverse relation, preserve existing conditions if they exist
38
+ // If the target attribute already exists and has conditions, preserve them
39
+ const targetAttributeData = targetAttribute || {};
40
+ // If the source doesn't have conditions but the target does, preserve target's conditions
36
41
  targetCT.setAttribute(attribute.targetAttribute, generateRelation({
37
42
  key,
38
43
  attribute,
39
44
  uid,
40
- targetAttribute
45
+ targetAttribute: targetAttributeData
41
46
  }));
42
47
  },
43
48
  unsetRelation (attribute) {
44
- if (!_.has(attribute, 'target')) {
49
+ if (!('target' in attribute) || !attribute.target) {
45
50
  return;
46
51
  }
47
52
  const targetCT = this.contentTypes.get(attribute.target);
48
- const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
53
+ const relationAttribute = attribute;
54
+ const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;
49
55
  const targetAttribute = targetCT.getAttribute(targetAttributeName);
50
56
  if (!targetAttribute) return;
51
57
  return targetCT.deleteAttribute(targetAttributeName);
@@ -66,26 +72,27 @@ function createComponentBuilder() {
66
72
  Object.keys(attributes$1).forEach((key)=>{
67
73
  const attribute = attributes$1[key];
68
74
  if (attributes.isRelation(attribute)) {
75
+ const relationAttribute = attribute;
69
76
  if ([
70
77
  'manyToMany',
71
78
  'oneToOne'
72
- ].includes(attribute.relation)) {
73
- if (attribute.target === uid && attribute.targetAttribute !== undefined) {
79
+ ].includes(relationAttribute.relation)) {
80
+ if (relationAttribute.target === uid && relationAttribute.targetAttribute !== undefined) {
74
81
  // self referencing relation
75
- const targetAttribute = attributes$1[attribute.targetAttribute];
82
+ const targetAttribute = attributes$1[relationAttribute.targetAttribute];
76
83
  if (targetAttribute.dominant === undefined) {
77
- attribute.dominant = true;
84
+ relationAttribute.dominant = true;
78
85
  } else {
79
- attribute.dominant = false;
86
+ relationAttribute.dominant = false;
80
87
  }
81
88
  } else {
82
- attribute.dominant = true;
89
+ relationAttribute.dominant = true;
83
90
  }
84
91
  }
85
92
  this.setRelation({
86
93
  key,
87
94
  uid,
88
- attribute
95
+ attribute: relationAttribute
89
96
  });
90
97
  }
91
98
  });
@@ -136,10 +143,13 @@ function createComponentBuilder() {
136
143
  // remove old relations
137
144
  deletedKeys.forEach((key)=>{
138
145
  const attribute = oldAttributes[key];
139
- const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
140
146
  // if the old relation has a target attribute. we need to remove it in the target type
141
- if (attributes.isConfigurable(attribute) && attributes.isRelation(attribute) && !_.isNil(targetAttributeName)) {
142
- this.unsetRelation(attribute);
147
+ if (attributes.isConfigurable(attribute) && attributes.isRelation(attribute)) {
148
+ const relationAttribute = attribute;
149
+ const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;
150
+ if (targetAttributeName !== null && targetAttributeName !== undefined) {
151
+ this.unsetRelation(attribute);
152
+ }
143
153
  }
144
154
  });
145
155
  remainingKeys.forEach((key)=>{
@@ -149,30 +159,47 @@ function createComponentBuilder() {
149
159
  return this.setRelation({
150
160
  key,
151
161
  uid,
152
- attribute: newAttributes[key]
162
+ attribute: newAttribute
153
163
  });
154
164
  }
155
165
  if (attributes.isRelation(oldAttribute) && !attributes.isRelation(newAttribute)) {
156
166
  return this.unsetRelation(oldAttribute);
157
167
  }
158
168
  if (attributes.isRelation(oldAttribute) && attributes.isRelation(newAttribute)) {
159
- const oldTargetAttributeName = oldAttribute.inversedBy || oldAttribute.mappedBy;
160
- const sameRelation = oldAttribute.relation === newAttribute.relation;
161
- const targetAttributeHasChanged = oldTargetAttributeName !== newAttribute.targetAttribute;
169
+ const relationAttribute = newAttribute;
170
+ const oldRelationAttribute = oldAttribute;
171
+ const oldTargetAttributeName = oldRelationAttribute.inversedBy || oldRelationAttribute.mappedBy;
172
+ const sameRelation = oldAttribute.relation === relationAttribute.relation;
173
+ const targetAttributeHasChanged = oldTargetAttributeName !== relationAttribute.targetAttribute;
162
174
  if (!sameRelation || targetAttributeHasChanged) {
163
175
  this.unsetRelation(oldAttribute);
164
176
  }
165
177
  // keep extra options that were set manually on oldAttribute
166
- reuseUnsetPreviousProperties(newAttribute, oldAttribute);
167
- if (oldAttribute.inversedBy) {
168
- newAttribute.dominant = true;
169
- } else if (oldAttribute.mappedBy) {
170
- newAttribute.dominant = false;
178
+ reuseUnsetPreviousProperties(relationAttribute, oldAttribute);
179
+ // Handle conditions explicitly - only preserve if present and not undefined in new attribute
180
+ const newAttributeFromInfos = newAttributes[key];
181
+ const hasNewConditions = newAttributeFromInfos.conditions !== undefined && newAttributeFromInfos.conditions !== null;
182
+ if (oldAttribute.conditions) {
183
+ if (hasNewConditions) {
184
+ // Conditions are still present, keep them
185
+ relationAttribute.conditions = newAttributeFromInfos.conditions;
186
+ } else {
187
+ // Conditions were removed (undefined or null), ensure they're not preserved
188
+ delete relationAttribute.conditions;
189
+ }
190
+ } else if (hasNewConditions) {
191
+ // New conditions added
192
+ relationAttribute.conditions = newAttributeFromInfos.conditions;
193
+ }
194
+ if (oldRelationAttribute.inversedBy) {
195
+ relationAttribute.dominant = true;
196
+ } else if (oldRelationAttribute.mappedBy) {
197
+ relationAttribute.dominant = false;
171
198
  }
172
199
  return this.setRelation({
173
200
  key,
174
201
  uid,
175
- attribute: newAttribute
202
+ attribute: relationAttribute
176
203
  });
177
204
  }
178
205
  });
@@ -180,26 +207,27 @@ function createComponentBuilder() {
180
207
  newKeys.forEach((key)=>{
181
208
  const attribute = newAttributes[key];
182
209
  if (attributes.isRelation(attribute)) {
210
+ const relationAttribute = attribute;
183
211
  if ([
184
212
  'manyToMany',
185
213
  'oneToOne'
186
- ].includes(attribute.relation)) {
187
- if (attribute.target === uid && attribute.targetAttribute !== undefined) {
214
+ ].includes(relationAttribute.relation)) {
215
+ if (relationAttribute.target === uid && relationAttribute.targetAttribute !== undefined) {
188
216
  // self referencing relation
189
- const targetAttribute = newAttributes[attribute.targetAttribute];
217
+ const targetAttribute = newAttributes[relationAttribute.targetAttribute];
190
218
  if (targetAttribute.dominant === undefined) {
191
- attribute.dominant = true;
219
+ relationAttribute.dominant = true;
192
220
  } else {
193
- attribute.dominant = false;
221
+ relationAttribute.dominant = false;
194
222
  }
195
223
  } else {
196
- attribute.dominant = true;
224
+ relationAttribute.dominant = true;
197
225
  }
198
226
  }
199
227
  this.setRelation({
200
228
  key,
201
229
  uid,
202
- attribute
230
+ attribute: relationAttribute
203
231
  });
204
232
  }
205
233
  });
@@ -241,7 +269,12 @@ const generateRelation = ({ key, attribute, uid, targetAttribute = {} })=>{
241
269
  type: 'relation',
242
270
  target: uid,
243
271
  private: targetAttribute.private || undefined,
244
- pluginOptions: targetAttribute.pluginOptions || undefined
272
+ pluginOptions: targetAttribute.pluginOptions || undefined,
273
+ // Preserve conditions from targetAttribute if they exist
274
+ // This allows each side of the relation to maintain its own conditions
275
+ ...targetAttribute.conditions && {
276
+ conditions: targetAttribute.conditions
277
+ }
245
278
  };
246
279
  switch(attribute.relation){
247
280
  case 'oneToOne':
@@ -279,12 +312,13 @@ const generateRelation = ({ key, attribute, uid, targetAttribute = {} })=>{
279
312
  }
280
313
  // we do this just to make sure we have the same key order when writing to files
281
314
  const { type, relation, target, ...restOptions } = opts;
282
- return {
315
+ const result = {
283
316
  type,
284
317
  relation,
285
318
  target,
286
319
  ...restOptions
287
320
  };
321
+ return result;
288
322
  };
289
323
 
290
324
  module.exports = createComponentBuilder;
@@ -1 +1 @@
1
- {"version":3,"file":"content-type-builder.js","sources":["../../../../server/src/services/schema-builder/content-type-builder.ts"],"sourcesContent":["import path from 'path';\nimport _ from 'lodash';\n\nimport { strings, errors } from '@strapi/utils';\nimport type { Schema, Internal } from '@strapi/types';\nimport { isRelation, isConfigurable } from '../../utils/attributes';\nimport { typeKinds } from '../constants';\nimport createSchemaHandler from './schema-handler';\nimport { CreateContentTypeInput } from '../../controllers/validation/content-type';\n\nconst { ApplicationError } = errors;\n\nconst reuseUnsetPreviousProperties = (\n newAttribute: Schema.Attribute.AnyAttribute,\n oldAttribute: Schema.Attribute.AnyAttribute\n) => {\n _.defaults(\n newAttribute,\n _.omit(oldAttribute, [\n 'configurable',\n 'required',\n 'private',\n 'unique',\n 'pluginOptions',\n 'inversedBy',\n 'mappedBy',\n ])\n );\n};\n\nexport default function createComponentBuilder() {\n return {\n setRelation(this: any, { key, uid, attribute }: any) {\n if (!_.has(attribute, 'target')) {\n return;\n }\n\n const targetCT = this.contentTypes.get(attribute.target);\n\n if (!targetCT) {\n throw new ApplicationError(`Content type ${attribute.target} not found`);\n }\n\n const targetAttribute = targetCT.getAttribute(attribute.targetAttribute);\n\n if (!attribute.targetAttribute) {\n return;\n }\n\n targetCT.setAttribute(\n attribute.targetAttribute,\n generateRelation({ key, attribute, uid, targetAttribute })\n );\n },\n\n unsetRelation(this: any, attribute: any) {\n if (!_.has(attribute, 'target')) {\n return;\n }\n\n const targetCT = this.contentTypes.get(attribute.target);\n\n const targetAttributeName = attribute.inversedBy || attribute.mappedBy;\n const targetAttribute = targetCT.getAttribute(targetAttributeName);\n\n if (!targetAttribute) return;\n\n return targetCT.deleteAttribute(targetAttributeName);\n },\n\n createContentTypeAttributes(\n this: any,\n uid: string,\n attributes: CreateContentTypeInput['attributes']\n ) {\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n const contentType = this.contentTypes.get(uid);\n\n // support self referencing content type relation\n Object.keys(attributes).forEach((key) => {\n const { target } = attributes[key];\n if (target === '__self__') {\n attributes[key].target = uid;\n }\n });\n\n contentType.setAttributes(this.convertAttributes(attributes));\n\n Object.keys(attributes).forEach((key) => {\n const attribute = attributes[key];\n\n if (isRelation(attribute)) {\n if (['manyToMany', 'oneToOne'].includes(attribute.relation)) {\n if (attribute.target === uid && attribute.targetAttribute !== undefined) {\n // self referencing relation\n const targetAttribute = attributes[attribute.targetAttribute];\n\n if (targetAttribute.dominant === undefined) {\n attribute.dominant = true;\n } else {\n attribute.dominant = false;\n }\n } else {\n attribute.dominant = true;\n }\n }\n\n this.setRelation({\n key,\n uid,\n attribute,\n });\n }\n });\n\n return contentType;\n },\n\n /**\n * Creates a content type in memory to be written to files later on\n */\n createContentType(this: any, infos: CreateContentTypeInput) {\n // TODO:: check for unique uid / singularName & pluralName & collectionName\n\n if (infos.uid && infos.uid !== createContentTypeUID(infos)) {\n throw new ApplicationError('contentType.invalidUID');\n }\n\n const uid = infos.uid ?? createContentTypeUID(infos);\n\n if (this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.alreadyExists');\n }\n\n const contentType = createSchemaHandler({\n modelName: infos.singularName,\n dir: path.join(\n strapi.dirs.app.api,\n infos.singularName,\n 'content-types',\n infos.singularName\n ),\n filename: `schema.json`,\n });\n\n this.contentTypes.set(uid, contentType);\n\n contentType\n .setUID(uid)\n .set('kind', infos.kind || typeKinds.COLLECTION_TYPE)\n .set(\n 'collectionName',\n infos.collectionName || strings.nameToCollectionName(infos.pluralName)\n )\n .set('info', {\n singularName: infos.singularName,\n pluralName: infos.pluralName,\n displayName: infos.displayName,\n description: infos.description,\n })\n .set('options', {\n ...(infos.options ?? {}),\n draftAndPublish: infos.draftAndPublish,\n })\n .set('pluginOptions', infos.pluginOptions)\n .set('config', infos.config);\n\n this.createContentTypeAttributes(uid, infos.attributes);\n\n return contentType;\n },\n\n editContentType(this: any, infos: any) {\n const { uid } = infos;\n\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n const contentType = this.contentTypes.get(uid);\n\n const oldAttributes = contentType.schema.attributes;\n\n const newAttributes = _.omitBy(infos.attributes, (attr, key) => {\n return _.has(oldAttributes, key) && !isConfigurable(oldAttributes[key]);\n });\n\n const newKeys = _.difference(Object.keys(newAttributes), Object.keys(oldAttributes));\n const deletedKeys = _.difference(Object.keys(oldAttributes), Object.keys(newAttributes));\n const remainingKeys = _.intersection(Object.keys(oldAttributes), Object.keys(newAttributes));\n\n // remove old relations\n deletedKeys.forEach((key) => {\n const attribute = oldAttributes[key];\n\n const targetAttributeName = attribute.inversedBy || attribute.mappedBy;\n\n // if the old relation has a target attribute. we need to remove it in the target type\n if (isConfigurable(attribute) && isRelation(attribute) && !_.isNil(targetAttributeName)) {\n this.unsetRelation(attribute);\n }\n });\n\n remainingKeys.forEach((key) => {\n const oldAttribute = oldAttributes[key];\n const newAttribute = newAttributes[key];\n\n if (!isRelation(oldAttribute) && isRelation(newAttribute)) {\n return this.setRelation({\n key,\n uid,\n attribute: newAttributes[key],\n });\n }\n\n if (isRelation(oldAttribute) && !isRelation(newAttribute)) {\n return this.unsetRelation(oldAttribute);\n }\n\n if (isRelation(oldAttribute) && isRelation(newAttribute)) {\n const oldTargetAttributeName = oldAttribute.inversedBy || oldAttribute.mappedBy;\n\n const sameRelation = oldAttribute.relation === newAttribute.relation;\n const targetAttributeHasChanged = oldTargetAttributeName !== newAttribute.targetAttribute;\n\n if (!sameRelation || targetAttributeHasChanged) {\n this.unsetRelation(oldAttribute);\n }\n\n // keep extra options that were set manually on oldAttribute\n reuseUnsetPreviousProperties(newAttribute, oldAttribute);\n\n if (oldAttribute.inversedBy) {\n newAttribute.dominant = true;\n } else if (oldAttribute.mappedBy) {\n newAttribute.dominant = false;\n }\n\n return this.setRelation({\n key,\n uid,\n attribute: newAttribute,\n });\n }\n });\n\n // add new relations\n newKeys.forEach((key) => {\n const attribute = newAttributes[key];\n\n if (isRelation(attribute)) {\n if (['manyToMany', 'oneToOne'].includes(attribute.relation)) {\n if (attribute.target === uid && attribute.targetAttribute !== undefined) {\n // self referencing relation\n const targetAttribute = newAttributes[attribute.targetAttribute];\n\n if (targetAttribute.dominant === undefined) {\n attribute.dominant = true;\n } else {\n attribute.dominant = false;\n }\n } else {\n attribute.dominant = true;\n }\n }\n\n this.setRelation({\n key,\n uid,\n attribute,\n });\n }\n });\n\n contentType\n .set('kind', infos.kind || contentType.schema.kind)\n .set(['info', 'displayName'], infos.displayName)\n .set(['info', 'description'], infos.description)\n .set('options', {\n ...(infos.options ?? {}),\n draftAndPublish: infos.draftAndPublish,\n })\n .set('pluginOptions', infos.pluginOptions)\n .setAttributes(this.convertAttributes(newAttributes));\n\n return contentType;\n },\n\n deleteContentType(this: any, uid: string) {\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n this.components.forEach((compo: any) => {\n compo.removeContentType(uid);\n });\n\n this.contentTypes.forEach((ct: any) => {\n ct.removeContentType(uid);\n });\n\n return this.contentTypes.get(uid).delete();\n },\n };\n}\n\n/**\n * Returns a uid from a content type infos\n *\n * @param {object} options options\n * @param {string} options.singularName content-type singularName\n * @returns {string} uid\n */\nconst createContentTypeUID = ({\n singularName,\n}: {\n singularName: string;\n}): Internal.UID.ContentType => `api::${singularName}.${singularName}`;\n\nconst generateRelation = ({ key, attribute, uid, targetAttribute = {} }: any) => {\n const opts: any = {\n type: 'relation',\n target: uid,\n private: targetAttribute.private || undefined,\n pluginOptions: targetAttribute.pluginOptions || undefined,\n };\n\n switch (attribute.relation) {\n case 'oneToOne': {\n opts.relation = 'oneToOne';\n\n if (attribute.dominant) {\n opts.mappedBy = key;\n } else {\n opts.inversedBy = key;\n }\n break;\n }\n case 'oneToMany': {\n opts.relation = 'manyToOne';\n opts.inversedBy = key;\n break;\n }\n case 'manyToOne': {\n opts.relation = 'oneToMany';\n opts.mappedBy = key;\n break;\n }\n case 'manyToMany': {\n opts.relation = 'manyToMany';\n\n if (attribute.dominant) {\n opts.mappedBy = key;\n } else {\n opts.inversedBy = key;\n }\n\n break;\n }\n default:\n }\n\n // we do this just to make sure we have the same key order when writing to files\n const { type, relation, target, ...restOptions } = opts;\n\n return {\n type,\n relation,\n target,\n ...restOptions,\n };\n};\n"],"names":["ApplicationError","errors","reuseUnsetPreviousProperties","newAttribute","oldAttribute","_","defaults","omit","createComponentBuilder","setRelation","key","uid","attribute","has","targetCT","contentTypes","get","target","targetAttribute","getAttribute","setAttribute","generateRelation","unsetRelation","targetAttributeName","inversedBy","mappedBy","deleteAttribute","createContentTypeAttributes","attributes","contentType","Object","keys","forEach","setAttributes","convertAttributes","isRelation","includes","relation","undefined","dominant","createContentType","infos","createContentTypeUID","createSchemaHandler","modelName","singularName","dir","path","join","strapi","dirs","app","api","filename","set","setUID","kind","typeKinds","COLLECTION_TYPE","collectionName","strings","nameToCollectionName","pluralName","displayName","description","options","draftAndPublish","pluginOptions","config","editContentType","oldAttributes","schema","newAttributes","omitBy","attr","isConfigurable","newKeys","difference","deletedKeys","remainingKeys","intersection","isNil","oldTargetAttributeName","sameRelation","targetAttributeHasChanged","deleteContentType","components","compo","removeContentType","ct","delete","opts","type","private","restOptions"],"mappings":"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"}
1
+ {"version":3,"file":"content-type-builder.js","sources":["../../../../server/src/services/schema-builder/content-type-builder.ts"],"sourcesContent":["import path from 'path';\nimport _ from 'lodash';\n\nimport { strings, errors } from '@strapi/utils';\nimport type { Schema, Internal } from '@strapi/types';\nimport { isRelation, isConfigurable } from '../../utils/attributes';\nimport { typeKinds } from '../constants';\nimport createSchemaHandler from './schema-handler';\nimport { CreateContentTypeInput } from '../../controllers/validation/content-type';\nimport type { InternalRelationAttribute, InternalAttribute } from './types';\n\nconst { ApplicationError } = errors;\n\nconst reuseUnsetPreviousProperties = (\n newAttribute: Schema.Attribute.AnyAttribute,\n oldAttribute: Schema.Attribute.AnyAttribute\n) => {\n _.defaults(\n newAttribute,\n _.omit(oldAttribute, [\n 'configurable',\n 'required',\n 'private',\n 'unique',\n 'pluginOptions',\n 'inversedBy',\n 'mappedBy',\n 'conditions', // Don't automatically preserve conditions\n ])\n );\n};\n\nexport default function createComponentBuilder() {\n return {\n setRelation(\n this: any,\n { key, uid, attribute }: { key: string; uid: string; attribute: InternalRelationAttribute }\n ) {\n if (!_.has(attribute, 'target')) {\n return;\n }\n\n const targetCT = this.contentTypes.get(attribute.target);\n\n if (!targetCT) {\n throw new ApplicationError(`Content type ${attribute.target} not found`);\n }\n\n const targetAttribute = targetCT.getAttribute(attribute.targetAttribute);\n\n if (!attribute.targetAttribute) {\n return;\n }\n\n // When generating the inverse relation, preserve existing conditions if they exist\n // If the target attribute already exists and has conditions, preserve them\n const targetAttributeData = targetAttribute || {};\n\n // If the source doesn't have conditions but the target does, preserve target's conditions\n\n targetCT.setAttribute(\n attribute.targetAttribute,\n generateRelation({ key, attribute, uid, targetAttribute: targetAttributeData })\n );\n },\n\n unsetRelation(\n this: any,\n attribute: Schema.Attribute.Relation<Schema.Attribute.RelationKind.Any>\n ) {\n if (!('target' in attribute) || !attribute.target) {\n return;\n }\n\n const targetCT = this.contentTypes.get(attribute.target);\n\n const relationAttribute = attribute as InternalRelationAttribute;\n const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;\n const targetAttribute = targetCT.getAttribute(targetAttributeName);\n\n if (!targetAttribute) return;\n\n return targetCT.deleteAttribute(targetAttributeName);\n },\n\n createContentTypeAttributes(\n this: any,\n uid: string,\n attributes: CreateContentTypeInput['attributes']\n ) {\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n const contentType = this.contentTypes.get(uid);\n\n // support self referencing content type relation\n Object.keys(attributes).forEach((key) => {\n const { target } = attributes[key];\n if (target === '__self__') {\n attributes[key].target = uid;\n }\n });\n\n contentType.setAttributes(this.convertAttributes(attributes));\n\n Object.keys(attributes).forEach((key) => {\n const attribute = attributes[key] as InternalAttribute;\n\n if (isRelation(attribute)) {\n const relationAttribute = attribute as InternalRelationAttribute;\n if (['manyToMany', 'oneToOne'].includes(relationAttribute.relation)) {\n if (\n relationAttribute.target === uid &&\n relationAttribute.targetAttribute !== undefined\n ) {\n // self referencing relation\n const targetAttribute = attributes[\n relationAttribute.targetAttribute\n ] as InternalRelationAttribute;\n\n if (targetAttribute.dominant === undefined) {\n relationAttribute.dominant = true;\n } else {\n relationAttribute.dominant = false;\n }\n } else {\n relationAttribute.dominant = true;\n }\n }\n\n this.setRelation({\n key,\n uid,\n attribute: relationAttribute,\n });\n }\n });\n\n return contentType;\n },\n\n /**\n * Creates a content type in memory to be written to files later on\n */\n createContentType(this: any, infos: CreateContentTypeInput) {\n // TODO:: check for unique uid / singularName & pluralName & collectionName\n\n if (infos.uid && infos.uid !== createContentTypeUID(infos)) {\n throw new ApplicationError('contentType.invalidUID');\n }\n\n const uid = infos.uid ?? createContentTypeUID(infos);\n\n if (this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.alreadyExists');\n }\n\n const contentType = createSchemaHandler({\n modelName: infos.singularName,\n dir: path.join(\n strapi.dirs.app.api,\n infos.singularName,\n 'content-types',\n infos.singularName\n ),\n filename: `schema.json`,\n });\n\n this.contentTypes.set(uid, contentType);\n\n contentType\n .setUID(uid)\n .set('kind', infos.kind || typeKinds.COLLECTION_TYPE)\n .set(\n 'collectionName',\n infos.collectionName || strings.nameToCollectionName(infos.pluralName)\n )\n .set('info', {\n singularName: infos.singularName,\n pluralName: infos.pluralName,\n displayName: infos.displayName,\n description: infos.description,\n })\n .set('options', {\n ...(infos.options ?? {}),\n draftAndPublish: infos.draftAndPublish,\n })\n .set('pluginOptions', infos.pluginOptions)\n .set('config', infos.config);\n\n this.createContentTypeAttributes(uid, infos.attributes);\n\n return contentType;\n },\n\n editContentType(this: any, infos: any) {\n const { uid } = infos;\n\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n const contentType = this.contentTypes.get(uid);\n\n const oldAttributes = contentType.schema.attributes;\n\n const newAttributes = _.omitBy(infos.attributes, (attr, key) => {\n return _.has(oldAttributes, key) && !isConfigurable(oldAttributes[key]);\n });\n\n const newKeys = _.difference(Object.keys(newAttributes), Object.keys(oldAttributes));\n const deletedKeys = _.difference(Object.keys(oldAttributes), Object.keys(newAttributes));\n const remainingKeys = _.intersection(Object.keys(oldAttributes), Object.keys(newAttributes));\n\n // remove old relations\n deletedKeys.forEach((key) => {\n const attribute = oldAttributes[key];\n\n // if the old relation has a target attribute. we need to remove it in the target type\n if (isConfigurable(attribute) && isRelation(attribute)) {\n const relationAttribute = attribute as InternalRelationAttribute;\n const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;\n\n if (targetAttributeName !== null && targetAttributeName !== undefined) {\n this.unsetRelation(attribute);\n }\n }\n });\n\n remainingKeys.forEach((key) => {\n const oldAttribute = oldAttributes[key];\n const newAttribute = newAttributes[key] as InternalAttribute;\n\n if (!isRelation(oldAttribute) && isRelation(newAttribute)) {\n return this.setRelation({\n key,\n uid,\n attribute: newAttribute as InternalRelationAttribute,\n });\n }\n\n if (isRelation(oldAttribute) && !isRelation(newAttribute)) {\n return this.unsetRelation(oldAttribute);\n }\n\n if (isRelation(oldAttribute) && isRelation(newAttribute)) {\n const relationAttribute = newAttribute as InternalRelationAttribute;\n const oldRelationAttribute = oldAttribute as InternalRelationAttribute;\n const oldTargetAttributeName =\n oldRelationAttribute.inversedBy || oldRelationAttribute.mappedBy;\n\n const sameRelation = oldAttribute.relation === relationAttribute.relation;\n const targetAttributeHasChanged =\n oldTargetAttributeName !== relationAttribute.targetAttribute;\n\n if (!sameRelation || targetAttributeHasChanged) {\n this.unsetRelation(oldAttribute);\n }\n\n // keep extra options that were set manually on oldAttribute\n reuseUnsetPreviousProperties(relationAttribute, oldAttribute);\n\n // Handle conditions explicitly - only preserve if present and not undefined in new attribute\n const newAttributeFromInfos = newAttributes[key];\n const hasNewConditions =\n newAttributeFromInfos.conditions !== undefined &&\n newAttributeFromInfos.conditions !== null;\n\n if (oldAttribute.conditions) {\n if (hasNewConditions) {\n // Conditions are still present, keep them\n relationAttribute.conditions = newAttributeFromInfos.conditions;\n } else {\n // Conditions were removed (undefined or null), ensure they're not preserved\n delete relationAttribute.conditions;\n }\n } else if (hasNewConditions) {\n // New conditions added\n relationAttribute.conditions = newAttributeFromInfos.conditions;\n }\n\n if (oldRelationAttribute.inversedBy) {\n relationAttribute.dominant = true;\n } else if (oldRelationAttribute.mappedBy) {\n relationAttribute.dominant = false;\n }\n\n return this.setRelation({\n key,\n uid,\n attribute: relationAttribute,\n });\n }\n });\n\n // add new relations\n newKeys.forEach((key) => {\n const attribute = newAttributes[key] as InternalAttribute;\n\n if (isRelation(attribute)) {\n const relationAttribute = attribute as InternalRelationAttribute;\n if (['manyToMany', 'oneToOne'].includes(relationAttribute.relation)) {\n if (\n relationAttribute.target === uid &&\n relationAttribute.targetAttribute !== undefined\n ) {\n // self referencing relation\n const targetAttribute = newAttributes[\n relationAttribute.targetAttribute\n ] as InternalRelationAttribute;\n\n if (targetAttribute.dominant === undefined) {\n relationAttribute.dominant = true;\n } else {\n relationAttribute.dominant = false;\n }\n } else {\n relationAttribute.dominant = true;\n }\n }\n\n this.setRelation({\n key,\n uid,\n attribute: relationAttribute,\n });\n }\n });\n\n contentType\n .set('kind', infos.kind || contentType.schema.kind)\n .set(['info', 'displayName'], infos.displayName)\n .set(['info', 'description'], infos.description)\n .set('options', {\n ...(infos.options ?? {}),\n draftAndPublish: infos.draftAndPublish,\n })\n .set('pluginOptions', infos.pluginOptions)\n .setAttributes(this.convertAttributes(newAttributes));\n\n return contentType;\n },\n\n deleteContentType(this: any, uid: string) {\n if (!this.contentTypes.has(uid)) {\n throw new ApplicationError('contentType.notFound');\n }\n\n this.components.forEach((compo: any) => {\n compo.removeContentType(uid);\n });\n\n this.contentTypes.forEach((ct: any) => {\n ct.removeContentType(uid);\n });\n\n return this.contentTypes.get(uid).delete();\n },\n };\n}\n\n/**\n * Returns a uid from a content type infos\n *\n * @param {object} options options\n * @param {string} options.singularName content-type singularName\n * @returns {string} uid\n */\nconst createContentTypeUID = ({\n singularName,\n}: {\n singularName: string;\n}): Internal.UID.ContentType => `api::${singularName}.${singularName}`;\n\nconst generateRelation = ({\n key,\n attribute,\n uid,\n targetAttribute = {},\n}: {\n key: string;\n attribute: InternalRelationAttribute;\n uid: string;\n targetAttribute?: Partial<InternalRelationAttribute>;\n}) => {\n const opts: any = {\n type: 'relation',\n target: uid,\n private: targetAttribute.private || undefined,\n pluginOptions: targetAttribute.pluginOptions || undefined,\n // Preserve conditions from targetAttribute if they exist\n // This allows each side of the relation to maintain its own conditions\n ...(targetAttribute.conditions && { conditions: targetAttribute.conditions }),\n };\n\n switch (attribute.relation) {\n case 'oneToOne': {\n opts.relation = 'oneToOne';\n\n if (attribute.dominant) {\n opts.mappedBy = key;\n } else {\n opts.inversedBy = key;\n }\n break;\n }\n case 'oneToMany': {\n opts.relation = 'manyToOne';\n opts.inversedBy = key;\n break;\n }\n case 'manyToOne': {\n opts.relation = 'oneToMany';\n opts.mappedBy = key;\n break;\n }\n case 'manyToMany': {\n opts.relation = 'manyToMany';\n\n if (attribute.dominant) {\n opts.mappedBy = key;\n } else {\n opts.inversedBy = key;\n }\n\n break;\n }\n default:\n }\n\n // we do this just to make sure we have the same key order when writing to files\n const { type, relation, target, ...restOptions } = opts;\n\n const result = {\n type,\n relation,\n target,\n ...restOptions,\n };\n\n return result;\n};\n"],"names":["ApplicationError","errors","reuseUnsetPreviousProperties","newAttribute","oldAttribute","_","defaults","omit","createComponentBuilder","setRelation","key","uid","attribute","has","targetCT","contentTypes","get","target","targetAttribute","getAttribute","targetAttributeData","setAttribute","generateRelation","unsetRelation","relationAttribute","targetAttributeName","inversedBy","mappedBy","deleteAttribute","createContentTypeAttributes","attributes","contentType","Object","keys","forEach","setAttributes","convertAttributes","isRelation","includes","relation","undefined","dominant","createContentType","infos","createContentTypeUID","createSchemaHandler","modelName","singularName","dir","path","join","strapi","dirs","app","api","filename","set","setUID","kind","typeKinds","COLLECTION_TYPE","collectionName","strings","nameToCollectionName","pluralName","displayName","description","options","draftAndPublish","pluginOptions","config","editContentType","oldAttributes","schema","newAttributes","omitBy","attr","isConfigurable","newKeys","difference","deletedKeys","remainingKeys","intersection","oldRelationAttribute","oldTargetAttributeName","sameRelation","targetAttributeHasChanged","newAttributeFromInfos","hasNewConditions","conditions","deleteContentType","components","compo","removeContentType","ct","delete","opts","type","private","restOptions","result"],"mappings":";;;;;;;;;AAWA,MAAM,EAAEA,gBAAgB,EAAE,GAAGC,YAAAA;AAE7B,MAAMC,4BAAAA,GAA+B,CACnCC,YACAC,EAAAA,YAAAA,GAAAA;AAEAC,IAAAA,CAAAA,CAAEC,QAAQ,CACRH,YAAAA,EACAE,CAAEE,CAAAA,IAAI,CAACH,YAAc,EAAA;AACnB,QAAA,cAAA;AACA,QAAA,UAAA;AACA,QAAA,SAAA;AACA,QAAA,QAAA;AACA,QAAA,eAAA;AACA,QAAA,YAAA;AACA,QAAA,UAAA;AACA,QAAA;AACD,KAAA,CAAA,CAAA;AAEL,CAAA;AAEe,SAASI,sBAAAA,GAAAA;IACtB,OAAO;AACLC,QAAAA,WAAAA,CAAAA,CAEE,EAAEC,GAAG,EAAEC,GAAG,EAAEC,SAAS,EAAsE,EAAA;AAE3F,YAAA,IAAI,CAACP,CAAAA,CAAEQ,GAAG,CAACD,WAAW,QAAW,CAAA,EAAA;AAC/B,gBAAA;AACF;YAEA,MAAME,QAAAA,GAAW,IAAI,CAACC,YAAY,CAACC,GAAG,CAACJ,UAAUK,MAAM,CAAA;AAEvD,YAAA,IAAI,CAACH,QAAU,EAAA;gBACb,MAAM,IAAId,iBAAiB,CAAC,aAAa,EAAEY,SAAUK,CAAAA,MAAM,CAAC,UAAU,CAAC,CAAA;AACzE;AAEA,YAAA,MAAMC,eAAkBJ,GAAAA,QAAAA,CAASK,YAAY,CAACP,UAAUM,eAAe,CAAA;YAEvE,IAAI,CAACN,SAAUM,CAAAA,eAAe,EAAE;AAC9B,gBAAA;AACF;;;YAIA,MAAME,mBAAAA,GAAsBF,mBAAmB,EAAC;;AAIhDJ,YAAAA,QAAAA,CAASO,YAAY,CACnBT,SAAUM,CAAAA,eAAe,EACzBI,gBAAiB,CAAA;AAAEZ,gBAAAA,GAAAA;AAAKE,gBAAAA,SAAAA;AAAWD,gBAAAA,GAAAA;gBAAKO,eAAiBE,EAAAA;AAAoB,aAAA,CAAA,CAAA;AAEjF,SAAA;AAEAG,QAAAA,aAAAA,CAAAA,CAEEX,SAAuE,EAAA;YAEvE,IAAI,EAAE,QAAYA,IAAAA,SAAQ,KAAM,CAACA,SAAAA,CAAUK,MAAM,EAAE;AACjD,gBAAA;AACF;YAEA,MAAMH,QAAAA,GAAW,IAAI,CAACC,YAAY,CAACC,GAAG,CAACJ,UAAUK,MAAM,CAAA;AAEvD,YAAA,MAAMO,iBAAoBZ,GAAAA,SAAAA;AAC1B,YAAA,MAAMa,mBAAsBD,GAAAA,iBAAAA,CAAkBE,UAAU,IAAIF,kBAAkBG,QAAQ;YACtF,MAAMT,eAAAA,GAAkBJ,QAASK,CAAAA,YAAY,CAACM,mBAAAA,CAAAA;AAE9C,YAAA,IAAI,CAACP,eAAiB,EAAA;YAEtB,OAAOJ,QAAAA,CAASc,eAAe,CAACH,mBAAAA,CAAAA;AAClC,SAAA;QAEAI,2BAEElB,CAAAA,CAAAA,GAAW,EACXmB,YAAgD,EAAA;AAEhD,YAAA,IAAI,CAAC,IAAI,CAACf,YAAY,CAACF,GAAG,CAACF,GAAM,CAAA,EAAA;AAC/B,gBAAA,MAAM,IAAIX,gBAAiB,CAAA,sBAAA,CAAA;AAC7B;AAEA,YAAA,MAAM+B,cAAc,IAAI,CAAChB,YAAY,CAACC,GAAG,CAACL,GAAAA,CAAAA;;AAG1CqB,YAAAA,MAAAA,CAAOC,IAAI,CAACH,YAAYI,CAAAA,CAAAA,OAAO,CAAC,CAACxB,GAAAA,GAAAA;AAC/B,gBAAA,MAAM,EAAEO,MAAM,EAAE,GAAGa,YAAU,CAACpB,GAAI,CAAA;AAClC,gBAAA,IAAIO,WAAW,UAAY,EAAA;AACzBa,oBAAAA,YAAU,CAACpB,GAAAA,CAAI,CAACO,MAAM,GAAGN,GAAAA;AAC3B;AACF,aAAA,CAAA;AAEAoB,YAAAA,WAAAA,CAAYI,aAAa,CAAC,IAAI,CAACC,iBAAiB,CAACN,YAAAA,CAAAA,CAAAA;AAEjDE,YAAAA,MAAAA,CAAOC,IAAI,CAACH,YAAYI,CAAAA,CAAAA,OAAO,CAAC,CAACxB,GAAAA,GAAAA;gBAC/B,MAAME,SAAAA,GAAYkB,YAAU,CAACpB,GAAI,CAAA;AAEjC,gBAAA,IAAI2B,sBAAWzB,SAAY,CAAA,EAAA;AACzB,oBAAA,MAAMY,iBAAoBZ,GAAAA,SAAAA;oBAC1B,IAAI;AAAC,wBAAA,YAAA;AAAc,wBAAA;AAAW,qBAAA,CAAC0B,QAAQ,CAACd,iBAAkBe,CAAAA,QAAQ,CAAG,EAAA;AACnE,wBAAA,IACEf,kBAAkBP,MAAM,KAAKN,OAC7Ba,iBAAkBN,CAAAA,eAAe,KAAKsB,SACtC,EAAA;;AAEA,4BAAA,MAAMtB,eAAkBY,GAAAA,YAAU,CAChCN,iBAAAA,CAAkBN,eAAe,CAClC;4BAED,IAAIA,eAAAA,CAAgBuB,QAAQ,KAAKD,SAAW,EAAA;AAC1ChB,gCAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,IAAA;6BACxB,MAAA;AACLjB,gCAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,KAAA;AAC/B;yBACK,MAAA;AACLjB,4BAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,IAAA;AAC/B;AACF;oBAEA,IAAI,CAAChC,WAAW,CAAC;AACfC,wBAAAA,GAAAA;AACAC,wBAAAA,GAAAA;wBACAC,SAAWY,EAAAA;AACb,qBAAA,CAAA;AACF;AACF,aAAA,CAAA;YAEA,OAAOO,WAAAA;AACT,SAAA;AAEA;;AAEC,QACDW,mBAA6BC,KAA6B,EAAA;;AAGxD,YAAA,IAAIA,MAAMhC,GAAG,IAAIgC,MAAMhC,GAAG,KAAKiC,qBAAqBD,KAAQ,CAAA,EAAA;AAC1D,gBAAA,MAAM,IAAI3C,gBAAiB,CAAA,wBAAA,CAAA;AAC7B;AAEA,YAAA,MAAMW,GAAMgC,GAAAA,KAAAA,CAAMhC,GAAG,IAAIiC,oBAAqBD,CAAAA,KAAAA,CAAAA;AAE9C,YAAA,IAAI,IAAI,CAAC5B,YAAY,CAACF,GAAG,CAACF,GAAM,CAAA,EAAA;AAC9B,gBAAA,MAAM,IAAIX,gBAAiB,CAAA,2BAAA,CAAA;AAC7B;AAEA,YAAA,MAAM+B,cAAcc,aAAoB,CAAA;AACtCC,gBAAAA,SAAAA,EAAWH,MAAMI,YAAY;AAC7BC,gBAAAA,GAAAA,EAAKC,IAAKC,CAAAA,IAAI,CACZC,MAAAA,CAAOC,IAAI,CAACC,GAAG,CAACC,GAAG,EACnBX,KAAMI,CAAAA,YAAY,EAClB,eAAA,EACAJ,MAAMI,YAAY,CAAA;gBAEpBQ,QAAU,EAAA,CAAC,WAAW;AACxB,aAAA,CAAA;AAEA,YAAA,IAAI,CAACxC,YAAY,CAACyC,GAAG,CAAC7C,GAAKoB,EAAAA,WAAAA,CAAAA;YAE3BA,WACG0B,CAAAA,MAAM,CAAC9C,GAAAA,CAAAA,CACP6C,GAAG,CAAC,MAAQb,EAAAA,KAAAA,CAAMe,IAAI,IAAIC,mBAAUC,CAAAA,eAAe,CACnDJ,CAAAA,GAAG,CACF,gBACAb,EAAAA,KAAAA,CAAMkB,cAAc,IAAIC,aAAQC,CAAAA,oBAAoB,CAACpB,KAAAA,CAAMqB,UAAU,CAAA,CAAA,CAEtER,GAAG,CAAC,MAAQ,EAAA;AACXT,gBAAAA,YAAAA,EAAcJ,MAAMI,YAAY;AAChCiB,gBAAAA,UAAAA,EAAYrB,MAAMqB,UAAU;AAC5BC,gBAAAA,WAAAA,EAAatB,MAAMsB,WAAW;AAC9BC,gBAAAA,WAAAA,EAAavB,MAAMuB;aAEpBV,CAAAA,CAAAA,GAAG,CAAC,SAAW,EAAA;AACd,gBAAA,GAAIb,KAAMwB,CAAAA,OAAO,IAAI,EAAE;AACvBC,gBAAAA,eAAAA,EAAiBzB,MAAMyB;aAExBZ,CAAAA,CAAAA,GAAG,CAAC,eAAA,EAAiBb,KAAM0B,CAAAA,aAAa,EACxCb,GAAG,CAAC,QAAUb,EAAAA,KAAAA,CAAM2B,MAAM,CAAA;AAE7B,YAAA,IAAI,CAACzC,2BAA2B,CAAClB,GAAAA,EAAKgC,MAAMb,UAAU,CAAA;YAEtD,OAAOC,WAAAA;AACT,SAAA;AAEAwC,QAAAA,eAAAA,CAAAA,CAA2B5B,KAAU,EAAA;YACnC,MAAM,EAAEhC,GAAG,EAAE,GAAGgC,KAAAA;AAEhB,YAAA,IAAI,CAAC,IAAI,CAAC5B,YAAY,CAACF,GAAG,CAACF,GAAM,CAAA,EAAA;AAC/B,gBAAA,MAAM,IAAIX,gBAAiB,CAAA,sBAAA,CAAA;AAC7B;AAEA,YAAA,MAAM+B,cAAc,IAAI,CAAChB,YAAY,CAACC,GAAG,CAACL,GAAAA,CAAAA;AAE1C,YAAA,MAAM6D,aAAgBzC,GAAAA,WAAAA,CAAY0C,MAAM,CAAC3C,UAAU;YAEnD,MAAM4C,aAAAA,GAAgBrE,EAAEsE,MAAM,CAAChC,MAAMb,UAAU,EAAE,CAAC8C,IAAMlE,EAAAA,GAAAA,GAAAA;gBACtD,OAAOL,CAAAA,CAAEQ,GAAG,CAAC2D,aAAAA,EAAe9D,QAAQ,CAACmE,yBAAAA,CAAeL,aAAa,CAAC9D,GAAI,CAAA,CAAA;AACxE,aAAA,CAAA;YAEA,MAAMoE,OAAAA,GAAUzE,CAAE0E,CAAAA,UAAU,CAAC/C,MAAAA,CAAOC,IAAI,CAACyC,aAAAA,CAAAA,EAAgB1C,MAAOC,CAAAA,IAAI,CAACuC,aAAAA,CAAAA,CAAAA;YACrE,MAAMQ,WAAAA,GAAc3E,CAAE0E,CAAAA,UAAU,CAAC/C,MAAAA,CAAOC,IAAI,CAACuC,aAAAA,CAAAA,EAAgBxC,MAAOC,CAAAA,IAAI,CAACyC,aAAAA,CAAAA,CAAAA;YACzE,MAAMO,aAAAA,GAAgB5E,CAAE6E,CAAAA,YAAY,CAAClD,MAAAA,CAAOC,IAAI,CAACuC,aAAAA,CAAAA,EAAgBxC,MAAOC,CAAAA,IAAI,CAACyC,aAAAA,CAAAA,CAAAA;;YAG7EM,WAAY9C,CAAAA,OAAO,CAAC,CAACxB,GAAAA,GAAAA;gBACnB,MAAME,SAAAA,GAAY4D,aAAa,CAAC9D,GAAI,CAAA;;gBAGpC,IAAImE,yBAAAA,CAAejE,SAAcyB,CAAAA,IAAAA,qBAAAA,CAAWzB,SAAY,CAAA,EAAA;AACtD,oBAAA,MAAMY,iBAAoBZ,GAAAA,SAAAA;AAC1B,oBAAA,MAAMa,mBAAsBD,GAAAA,iBAAAA,CAAkBE,UAAU,IAAIF,kBAAkBG,QAAQ;oBAEtF,IAAIF,mBAAAA,KAAwB,IAAQA,IAAAA,mBAAAA,KAAwBe,SAAW,EAAA;wBACrE,IAAI,CAACjB,aAAa,CAACX,SAAAA,CAAAA;AACrB;AACF;AACF,aAAA,CAAA;YAEAqE,aAAc/C,CAAAA,OAAO,CAAC,CAACxB,GAAAA,GAAAA;gBACrB,MAAMN,YAAAA,GAAeoE,aAAa,CAAC9D,GAAI,CAAA;gBACvC,MAAMP,YAAAA,GAAeuE,aAAa,CAAChE,GAAI,CAAA;AAEvC,gBAAA,IAAI,CAAC2B,qBAAAA,CAAWjC,YAAiBiC,CAAAA,IAAAA,qBAAAA,CAAWlC,YAAe,CAAA,EAAA;oBACzD,OAAO,IAAI,CAACM,WAAW,CAAC;AACtBC,wBAAAA,GAAAA;AACAC,wBAAAA,GAAAA;wBACAC,SAAWT,EAAAA;AACb,qBAAA,CAAA;AACF;AAEA,gBAAA,IAAIkC,qBAAWjC,CAAAA,YAAAA,CAAAA,IAAiB,CAACiC,qBAAAA,CAAWlC,YAAe,CAAA,EAAA;oBACzD,OAAO,IAAI,CAACoB,aAAa,CAACnB,YAAAA,CAAAA;AAC5B;gBAEA,IAAIiC,qBAAAA,CAAWjC,YAAiBiC,CAAAA,IAAAA,qBAAAA,CAAWlC,YAAe,CAAA,EAAA;AACxD,oBAAA,MAAMqB,iBAAoBrB,GAAAA,YAAAA;AAC1B,oBAAA,MAAMgF,oBAAuB/E,GAAAA,YAAAA;AAC7B,oBAAA,MAAMgF,sBACJD,GAAAA,oBAAAA,CAAqBzD,UAAU,IAAIyD,qBAAqBxD,QAAQ;AAElE,oBAAA,MAAM0D,YAAejF,GAAAA,YAAAA,CAAamC,QAAQ,KAAKf,kBAAkBe,QAAQ;oBACzE,MAAM+C,yBAAAA,GACJF,sBAA2B5D,KAAAA,iBAAAA,CAAkBN,eAAe;oBAE9D,IAAI,CAACmE,gBAAgBC,yBAA2B,EAAA;wBAC9C,IAAI,CAAC/D,aAAa,CAACnB,YAAAA,CAAAA;AACrB;;AAGAF,oBAAAA,4BAAAA,CAA6BsB,iBAAmBpB,EAAAA,YAAAA,CAAAA;;oBAGhD,MAAMmF,qBAAAA,GAAwBb,aAAa,CAAChE,GAAI,CAAA;AAChD,oBAAA,MAAM8E,mBACJD,qBAAsBE,CAAAA,UAAU,KAAKjD,SACrC+C,IAAAA,qBAAAA,CAAsBE,UAAU,KAAK,IAAA;oBAEvC,IAAIrF,YAAAA,CAAaqF,UAAU,EAAE;AAC3B,wBAAA,IAAID,gBAAkB,EAAA;;4BAEpBhE,iBAAkBiE,CAAAA,UAAU,GAAGF,qBAAAA,CAAsBE,UAAU;yBAC1D,MAAA;;AAEL,4BAAA,OAAOjE,kBAAkBiE,UAAU;AACrC;AACF,qBAAA,MAAO,IAAID,gBAAkB,EAAA;;wBAE3BhE,iBAAkBiE,CAAAA,UAAU,GAAGF,qBAAAA,CAAsBE,UAAU;AACjE;oBAEA,IAAIN,oBAAAA,CAAqBzD,UAAU,EAAE;AACnCF,wBAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,IAAA;qBACxB,MAAA,IAAI0C,oBAAqBxD,CAAAA,QAAQ,EAAE;AACxCH,wBAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,KAAA;AAC/B;oBAEA,OAAO,IAAI,CAAChC,WAAW,CAAC;AACtBC,wBAAAA,GAAAA;AACAC,wBAAAA,GAAAA;wBACAC,SAAWY,EAAAA;AACb,qBAAA,CAAA;AACF;AACF,aAAA,CAAA;;YAGAsD,OAAQ5C,CAAAA,OAAO,CAAC,CAACxB,GAAAA,GAAAA;gBACf,MAAME,SAAAA,GAAY8D,aAAa,CAAChE,GAAI,CAAA;AAEpC,gBAAA,IAAI2B,sBAAWzB,SAAY,CAAA,EAAA;AACzB,oBAAA,MAAMY,iBAAoBZ,GAAAA,SAAAA;oBAC1B,IAAI;AAAC,wBAAA,YAAA;AAAc,wBAAA;AAAW,qBAAA,CAAC0B,QAAQ,CAACd,iBAAkBe,CAAAA,QAAQ,CAAG,EAAA;AACnE,wBAAA,IACEf,kBAAkBP,MAAM,KAAKN,OAC7Ba,iBAAkBN,CAAAA,eAAe,KAAKsB,SACtC,EAAA;;AAEA,4BAAA,MAAMtB,eAAkBwD,GAAAA,aAAa,CACnClD,iBAAAA,CAAkBN,eAAe,CAClC;4BAED,IAAIA,eAAAA,CAAgBuB,QAAQ,KAAKD,SAAW,EAAA;AAC1ChB,gCAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,IAAA;6BACxB,MAAA;AACLjB,gCAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,KAAA;AAC/B;yBACK,MAAA;AACLjB,4BAAAA,iBAAAA,CAAkBiB,QAAQ,GAAG,IAAA;AAC/B;AACF;oBAEA,IAAI,CAAChC,WAAW,CAAC;AACfC,wBAAAA,GAAAA;AACAC,wBAAAA,GAAAA;wBACAC,SAAWY,EAAAA;AACb,qBAAA,CAAA;AACF;AACF,aAAA,CAAA;AAEAO,YAAAA,WAAAA,CACGyB,GAAG,CAAC,MAAQb,EAAAA,KAAAA,CAAMe,IAAI,IAAI3B,WAAY0C,CAAAA,MAAM,CAACf,IAAI,CACjDF,CAAAA,GAAG,CAAC;AAAC,gBAAA,MAAA;AAAQ,gBAAA;AAAc,aAAA,EAAEb,KAAMsB,CAAAA,WAAW,CAC9CT,CAAAA,GAAG,CAAC;AAAC,gBAAA,MAAA;AAAQ,gBAAA;AAAc,aAAA,EAAEb,KAAMuB,CAAAA,WAAW,CAC9CV,CAAAA,GAAG,CAAC,SAAW,EAAA;AACd,gBAAA,GAAIb,KAAMwB,CAAAA,OAAO,IAAI,EAAE;AACvBC,gBAAAA,eAAAA,EAAiBzB,MAAMyB;aAExBZ,CAAAA,CAAAA,GAAG,CAAC,eAAA,EAAiBb,KAAM0B,CAAAA,aAAa,CACxClC,CAAAA,aAAa,CAAC,IAAI,CAACC,iBAAiB,CAACsC,aAAAA,CAAAA,CAAAA;YAExC,OAAO3C,WAAAA;AACT,SAAA;AAEA2D,QAAAA,iBAAAA,CAAAA,CAA6B/E,GAAW,EAAA;AACtC,YAAA,IAAI,CAAC,IAAI,CAACI,YAAY,CAACF,GAAG,CAACF,GAAM,CAAA,EAAA;AAC/B,gBAAA,MAAM,IAAIX,gBAAiB,CAAA,sBAAA,CAAA;AAC7B;AAEA,YAAA,IAAI,CAAC2F,UAAU,CAACzD,OAAO,CAAC,CAAC0D,KAAAA,GAAAA;AACvBA,gBAAAA,KAAAA,CAAMC,iBAAiB,CAAClF,GAAAA,CAAAA;AAC1B,aAAA,CAAA;AAEA,YAAA,IAAI,CAACI,YAAY,CAACmB,OAAO,CAAC,CAAC4D,EAAAA,GAAAA;AACzBA,gBAAAA,EAAAA,CAAGD,iBAAiB,CAAClF,GAAAA,CAAAA;AACvB,aAAA,CAAA;AAEA,YAAA,OAAO,IAAI,CAACI,YAAY,CAACC,GAAG,CAACL,KAAKoF,MAAM,EAAA;AAC1C;AACF,KAAA;AACF;AAEA;;;;;;AAMC,IACD,MAAMnD,oBAAAA,GAAuB,CAAC,EAC5BG,YAAY,EAGb,GAA+B,CAAC,KAAK,EAAEA,YAAAA,CAAa,CAAC,EAAEA,aAAa,CAAC;AAEtE,MAAMzB,gBAAmB,GAAA,CAAC,EACxBZ,GAAG,EACHE,SAAS,EACTD,GAAG,EACHO,eAAAA,GAAkB,EAAE,EAMrB,GAAA;AACC,IAAA,MAAM8E,IAAY,GAAA;QAChBC,IAAM,EAAA,UAAA;QACNhF,MAAQN,EAAAA,GAAAA;QACRuF,OAAShF,EAAAA,eAAAA,CAAgBgF,OAAO,IAAI1D,SAAAA;QACpC6B,aAAenD,EAAAA,eAAAA,CAAgBmD,aAAa,IAAI7B,SAAAA;;;QAGhD,GAAItB,eAAAA,CAAgBuE,UAAU,IAAI;AAAEA,YAAAA,UAAAA,EAAYvE,gBAAgBuE;;AAClE,KAAA;AAEA,IAAA,OAAQ7E,UAAU2B,QAAQ;QACxB,KAAK,UAAA;AAAY,YAAA;AACfyD,gBAAAA,IAAAA,CAAKzD,QAAQ,GAAG,UAAA;gBAEhB,IAAI3B,SAAAA,CAAU6B,QAAQ,EAAE;AACtBuD,oBAAAA,IAAAA,CAAKrE,QAAQ,GAAGjB,GAAAA;iBACX,MAAA;AACLsF,oBAAAA,IAAAA,CAAKtE,UAAU,GAAGhB,GAAAA;AACpB;AACA,gBAAA;AACF;QACA,KAAK,WAAA;AAAa,YAAA;AAChBsF,gBAAAA,IAAAA,CAAKzD,QAAQ,GAAG,WAAA;AAChByD,gBAAAA,IAAAA,CAAKtE,UAAU,GAAGhB,GAAAA;AAClB,gBAAA;AACF;QACA,KAAK,WAAA;AAAa,YAAA;AAChBsF,gBAAAA,IAAAA,CAAKzD,QAAQ,GAAG,WAAA;AAChByD,gBAAAA,IAAAA,CAAKrE,QAAQ,GAAGjB,GAAAA;AAChB,gBAAA;AACF;QACA,KAAK,YAAA;AAAc,YAAA;AACjBsF,gBAAAA,IAAAA,CAAKzD,QAAQ,GAAG,YAAA;gBAEhB,IAAI3B,SAAAA,CAAU6B,QAAQ,EAAE;AACtBuD,oBAAAA,IAAAA,CAAKrE,QAAQ,GAAGjB,GAAAA;iBACX,MAAA;AACLsF,oBAAAA,IAAAA,CAAKtE,UAAU,GAAGhB,GAAAA;AACpB;AAEA,gBAAA;AACF;AAEF;;IAGA,MAAM,EAAEuF,IAAI,EAAE1D,QAAQ,EAAEtB,MAAM,EAAE,GAAGkF,WAAAA,EAAa,GAAGH,IAAAA;AAEnD,IAAA,MAAMI,MAAS,GAAA;AACbH,QAAAA,IAAAA;AACA1D,QAAAA,QAAAA;AACAtB,QAAAA,MAAAA;AACA,QAAA,GAAGkF;AACL,KAAA;IAEA,OAAOC,MAAAA;AACT,CAAA;;;;"}
@@ -14,7 +14,8 @@ const reuseUnsetPreviousProperties = (newAttribute, oldAttribute)=>{
14
14
  'unique',
15
15
  'pluginOptions',
16
16
  'inversedBy',
17
- 'mappedBy'
17
+ 'mappedBy',
18
+ 'conditions'
18
19
  ]));
19
20
  };
20
21
  function createComponentBuilder() {
@@ -31,19 +32,24 @@ function createComponentBuilder() {
31
32
  if (!attribute.targetAttribute) {
32
33
  return;
33
34
  }
35
+ // When generating the inverse relation, preserve existing conditions if they exist
36
+ // If the target attribute already exists and has conditions, preserve them
37
+ const targetAttributeData = targetAttribute || {};
38
+ // If the source doesn't have conditions but the target does, preserve target's conditions
34
39
  targetCT.setAttribute(attribute.targetAttribute, generateRelation({
35
40
  key,
36
41
  attribute,
37
42
  uid,
38
- targetAttribute
43
+ targetAttribute: targetAttributeData
39
44
  }));
40
45
  },
41
46
  unsetRelation (attribute) {
42
- if (!_.has(attribute, 'target')) {
47
+ if (!('target' in attribute) || !attribute.target) {
43
48
  return;
44
49
  }
45
50
  const targetCT = this.contentTypes.get(attribute.target);
46
- const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
51
+ const relationAttribute = attribute;
52
+ const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;
47
53
  const targetAttribute = targetCT.getAttribute(targetAttributeName);
48
54
  if (!targetAttribute) return;
49
55
  return targetCT.deleteAttribute(targetAttributeName);
@@ -64,26 +70,27 @@ function createComponentBuilder() {
64
70
  Object.keys(attributes).forEach((key)=>{
65
71
  const attribute = attributes[key];
66
72
  if (isRelation(attribute)) {
73
+ const relationAttribute = attribute;
67
74
  if ([
68
75
  'manyToMany',
69
76
  'oneToOne'
70
- ].includes(attribute.relation)) {
71
- if (attribute.target === uid && attribute.targetAttribute !== undefined) {
77
+ ].includes(relationAttribute.relation)) {
78
+ if (relationAttribute.target === uid && relationAttribute.targetAttribute !== undefined) {
72
79
  // self referencing relation
73
- const targetAttribute = attributes[attribute.targetAttribute];
80
+ const targetAttribute = attributes[relationAttribute.targetAttribute];
74
81
  if (targetAttribute.dominant === undefined) {
75
- attribute.dominant = true;
82
+ relationAttribute.dominant = true;
76
83
  } else {
77
- attribute.dominant = false;
84
+ relationAttribute.dominant = false;
78
85
  }
79
86
  } else {
80
- attribute.dominant = true;
87
+ relationAttribute.dominant = true;
81
88
  }
82
89
  }
83
90
  this.setRelation({
84
91
  key,
85
92
  uid,
86
- attribute
93
+ attribute: relationAttribute
87
94
  });
88
95
  }
89
96
  });
@@ -134,10 +141,13 @@ function createComponentBuilder() {
134
141
  // remove old relations
135
142
  deletedKeys.forEach((key)=>{
136
143
  const attribute = oldAttributes[key];
137
- const targetAttributeName = attribute.inversedBy || attribute.mappedBy;
138
144
  // if the old relation has a target attribute. we need to remove it in the target type
139
- if (isConfigurable(attribute) && isRelation(attribute) && !_.isNil(targetAttributeName)) {
140
- this.unsetRelation(attribute);
145
+ if (isConfigurable(attribute) && isRelation(attribute)) {
146
+ const relationAttribute = attribute;
147
+ const targetAttributeName = relationAttribute.inversedBy || relationAttribute.mappedBy;
148
+ if (targetAttributeName !== null && targetAttributeName !== undefined) {
149
+ this.unsetRelation(attribute);
150
+ }
141
151
  }
142
152
  });
143
153
  remainingKeys.forEach((key)=>{
@@ -147,30 +157,47 @@ function createComponentBuilder() {
147
157
  return this.setRelation({
148
158
  key,
149
159
  uid,
150
- attribute: newAttributes[key]
160
+ attribute: newAttribute
151
161
  });
152
162
  }
153
163
  if (isRelation(oldAttribute) && !isRelation(newAttribute)) {
154
164
  return this.unsetRelation(oldAttribute);
155
165
  }
156
166
  if (isRelation(oldAttribute) && isRelation(newAttribute)) {
157
- const oldTargetAttributeName = oldAttribute.inversedBy || oldAttribute.mappedBy;
158
- const sameRelation = oldAttribute.relation === newAttribute.relation;
159
- const targetAttributeHasChanged = oldTargetAttributeName !== newAttribute.targetAttribute;
167
+ const relationAttribute = newAttribute;
168
+ const oldRelationAttribute = oldAttribute;
169
+ const oldTargetAttributeName = oldRelationAttribute.inversedBy || oldRelationAttribute.mappedBy;
170
+ const sameRelation = oldAttribute.relation === relationAttribute.relation;
171
+ const targetAttributeHasChanged = oldTargetAttributeName !== relationAttribute.targetAttribute;
160
172
  if (!sameRelation || targetAttributeHasChanged) {
161
173
  this.unsetRelation(oldAttribute);
162
174
  }
163
175
  // keep extra options that were set manually on oldAttribute
164
- reuseUnsetPreviousProperties(newAttribute, oldAttribute);
165
- if (oldAttribute.inversedBy) {
166
- newAttribute.dominant = true;
167
- } else if (oldAttribute.mappedBy) {
168
- newAttribute.dominant = false;
176
+ reuseUnsetPreviousProperties(relationAttribute, oldAttribute);
177
+ // Handle conditions explicitly - only preserve if present and not undefined in new attribute
178
+ const newAttributeFromInfos = newAttributes[key];
179
+ const hasNewConditions = newAttributeFromInfos.conditions !== undefined && newAttributeFromInfos.conditions !== null;
180
+ if (oldAttribute.conditions) {
181
+ if (hasNewConditions) {
182
+ // Conditions are still present, keep them
183
+ relationAttribute.conditions = newAttributeFromInfos.conditions;
184
+ } else {
185
+ // Conditions were removed (undefined or null), ensure they're not preserved
186
+ delete relationAttribute.conditions;
187
+ }
188
+ } else if (hasNewConditions) {
189
+ // New conditions added
190
+ relationAttribute.conditions = newAttributeFromInfos.conditions;
191
+ }
192
+ if (oldRelationAttribute.inversedBy) {
193
+ relationAttribute.dominant = true;
194
+ } else if (oldRelationAttribute.mappedBy) {
195
+ relationAttribute.dominant = false;
169
196
  }
170
197
  return this.setRelation({
171
198
  key,
172
199
  uid,
173
- attribute: newAttribute
200
+ attribute: relationAttribute
174
201
  });
175
202
  }
176
203
  });
@@ -178,26 +205,27 @@ function createComponentBuilder() {
178
205
  newKeys.forEach((key)=>{
179
206
  const attribute = newAttributes[key];
180
207
  if (isRelation(attribute)) {
208
+ const relationAttribute = attribute;
181
209
  if ([
182
210
  'manyToMany',
183
211
  'oneToOne'
184
- ].includes(attribute.relation)) {
185
- if (attribute.target === uid && attribute.targetAttribute !== undefined) {
212
+ ].includes(relationAttribute.relation)) {
213
+ if (relationAttribute.target === uid && relationAttribute.targetAttribute !== undefined) {
186
214
  // self referencing relation
187
- const targetAttribute = newAttributes[attribute.targetAttribute];
215
+ const targetAttribute = newAttributes[relationAttribute.targetAttribute];
188
216
  if (targetAttribute.dominant === undefined) {
189
- attribute.dominant = true;
217
+ relationAttribute.dominant = true;
190
218
  } else {
191
- attribute.dominant = false;
219
+ relationAttribute.dominant = false;
192
220
  }
193
221
  } else {
194
- attribute.dominant = true;
222
+ relationAttribute.dominant = true;
195
223
  }
196
224
  }
197
225
  this.setRelation({
198
226
  key,
199
227
  uid,
200
- attribute
228
+ attribute: relationAttribute
201
229
  });
202
230
  }
203
231
  });
@@ -239,7 +267,12 @@ const generateRelation = ({ key, attribute, uid, targetAttribute = {} })=>{
239
267
  type: 'relation',
240
268
  target: uid,
241
269
  private: targetAttribute.private || undefined,
242
- pluginOptions: targetAttribute.pluginOptions || undefined
270
+ pluginOptions: targetAttribute.pluginOptions || undefined,
271
+ // Preserve conditions from targetAttribute if they exist
272
+ // This allows each side of the relation to maintain its own conditions
273
+ ...targetAttribute.conditions && {
274
+ conditions: targetAttribute.conditions
275
+ }
243
276
  };
244
277
  switch(attribute.relation){
245
278
  case 'oneToOne':
@@ -277,12 +310,13 @@ const generateRelation = ({ key, attribute, uid, targetAttribute = {} })=>{
277
310
  }
278
311
  // we do this just to make sure we have the same key order when writing to files
279
312
  const { type, relation, target, ...restOptions } = opts;
280
- return {
313
+ const result = {
281
314
  type,
282
315
  relation,
283
316
  target,
284
317
  ...restOptions
285
318
  };
319
+ return result;
286
320
  };
287
321
 
288
322
  export { createComponentBuilder as default };