@strapi/core 0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393 → 0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834

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.
@@ -6,6 +6,7 @@ declare const _default: Readonly<{
6
6
  }) => Promise<void>;
7
7
  readonly isEE: boolean;
8
8
  readonly seats: number | undefined;
9
+ readonly type: string | undefined;
9
10
  features: Readonly<{
10
11
  list: () => {
11
12
  [key: string]: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ee/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;;;;;;;;;;;;;;;;;iCAsPb,MAAM;;;AAfnC,wBAiBG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ee/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;;;;;;;;;;;;;;;;;;iCA0Pb,MAAM;;;AAnBnC,wBAqBG"}
@@ -1 +1 @@
1
- {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/ee/license.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;CACvE;AAkBD,cAAM,iBAAkB,SAAQ,KAAK;IACnC,cAAc,UAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,cAAc,UAAQ;CAKpD;AAED,QAAA,MAAM,WAAW,cAAe,MAAM,uBASrC,CAAC;AAEF,QAAA,MAAM,aAAa,YAAa,MAAM,gBA2BrC,CAAC;AAMF,QAAA,MAAM,YAAY,eACJ;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE,OAC9B,MAAM,aACA,MAAM,iBA4BlB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/ee/license.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;CACvE;AAmBD,cAAM,iBAAkB,SAAQ,KAAK;IACnC,cAAc,UAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,cAAc,UAAQ;CAKpD;AAED,QAAA,MAAM,WAAW,cAAe,MAAM,uBASrC,CAAC;AAEF,QAAA,MAAM,aAAa,YAAa,MAAM,gBA2BrC,CAAC;AAMF,QAAA,MAAM,YAAY,eACJ;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE,OAC9B,MAAM,aACA,MAAM,iBA4BlB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -312,7 +312,7 @@ const getDirs = ({ appDir, distDir }, config)=>({
312
312
  });
313
313
 
314
314
  var name = "@strapi/core";
315
- var version = "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393";
315
+ var version = "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834";
316
316
  var description = "Core of Strapi";
317
317
  var homepage = "https://strapi.io";
318
318
  var bugs = {
@@ -368,14 +368,14 @@ var dependencies = {
368
368
  "@koa/cors": "5.0.0",
369
369
  "@koa/router": "12.0.2",
370
370
  "@paralleldrive/cuid2": "2.2.2",
371
- "@strapi/admin": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
372
- "@strapi/database": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
373
- "@strapi/generators": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
374
- "@strapi/logger": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
375
- "@strapi/permissions": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
376
- "@strapi/types": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
377
- "@strapi/typescript-utils": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
378
- "@strapi/utils": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
371
+ "@strapi/admin": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
372
+ "@strapi/database": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
373
+ "@strapi/generators": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
374
+ "@strapi/logger": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
375
+ "@strapi/permissions": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
376
+ "@strapi/types": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
377
+ "@strapi/typescript-utils": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
378
+ "@strapi/utils": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
379
379
  bcryptjs: "2.4.3",
380
380
  boxen: "5.1.2",
381
381
  chalk: "4.1.2",
@@ -438,9 +438,9 @@ var devDependencies = {
438
438
  "@types/node": "18.19.24",
439
439
  "@types/node-schedule": "2.1.7",
440
440
  "@types/statuses": "2.0.1",
441
- "eslint-config-custom": "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393",
441
+ "eslint-config-custom": "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834",
442
442
  supertest: "6.3.3",
443
- tsconfig: "0.0.0-next.e98ae27d8c69c68823eb7c46cf329385637ba393"
443
+ tsconfig: "0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834"
444
444
  };
445
445
  var engines = {
446
446
  node: ">=18.0.0 <=22.x.x",
@@ -1201,6 +1201,9 @@ const DEFAULT_FEATURES = {
1201
1201
  options: {
1202
1202
  retentionDays: 99999
1203
1203
  }
1204
+ },
1205
+ {
1206
+ name: 'cms-advanced-preview'
1204
1207
  }
1205
1208
  ]
1206
1209
  };
@@ -1515,6 +1518,9 @@ var index = Object.freeze({
1515
1518
  get seats () {
1516
1519
  return ee.licenseInfo.seats;
1517
1520
  },
1521
+ get type () {
1522
+ return ee.licenseInfo.type;
1523
+ },
1518
1524
  features: Object.freeze({
1519
1525
  list,
1520
1526
  get,
@@ -6770,7 +6776,7 @@ const EVENTS = {
6770
6776
  * Loads lingering relations that need to be updated when overriding a published or draft entry.
6771
6777
  * This is necessary because the relations are uni-directional and the target entry is not aware of the source entry.
6772
6778
  * This is not the case for bi-directional relations, where the target entry is also linked to the source entry.
6773
- */ const load = async (uid, { oldVersions, newVersions })=>{
6779
+ */ const load$1 = async (uid, { oldVersions, newVersions })=>{
6774
6780
  const updates = [];
6775
6781
  // Iterate all components and content types to find relations that need to be updated
6776
6782
  await strapi.db.transaction(async ({ trx })=>{
@@ -6845,7 +6851,7 @@ const EVENTS = {
6845
6851
  * @param oldEntries The old entries that are being overridden
6846
6852
  * @param newEntries The new entries that are overriding the old ones
6847
6853
  * @param oldRelations The relations that were previously loaded with `load` @see load
6848
- */ const sync = async (oldEntries, newEntries, oldRelations)=>{
6854
+ */ const sync$1 = async (oldEntries, newEntries, oldRelations)=>{
6849
6855
  /**
6850
6856
  * Create a map of old entry ids to new entry ids
6851
6857
  *
@@ -6875,6 +6881,146 @@ const EVENTS = {
6875
6881
  });
6876
6882
  };
6877
6883
 
6884
+ /**
6885
+ * Loads all bidirectional relations that need to be synchronized when content entries change state
6886
+ * (e.g., during publish/unpublish operations).
6887
+ *
6888
+ * In Strapi, bidirectional relations allow maintaining order from both sides of the relation.
6889
+ * When an entry is published, the following occurs:
6890
+ *
6891
+ * 1. The old published entry is deleted
6892
+ * 2. A new entry is created with all its relations
6893
+ *
6894
+ * This process affects relation ordering in the following way:
6895
+ *
6896
+ * Initial state (Entry A related to X, Y, Z):
6897
+ * ```
6898
+ * Entry A (draft) Entry A (published)
6899
+ * │ │
6900
+ * ├──(1)→ X ├──(1)→ X
6901
+ * ├──(2)→ Y ├──(2)→ Y
6902
+ * └──(3)→ Z └──(3)→ Z
6903
+ *
6904
+ * X's perspective: Y's perspective: Z's perspective:
6905
+ * └──(2)→ Entry A └──(1)→ Entry A └──(3)→ Entry A
6906
+ * ```
6907
+ *
6908
+ * After publishing Entry A (without relation order sync):
6909
+ * ```
6910
+ * Entry A (draft) Entry A (new published)
6911
+ * │ │
6912
+ * ├──(1)→ X ├──(1)→ X
6913
+ * ├──(2)→ Y ├──(2)→ Y
6914
+ * └──(3)→ Z └──(3)→ Z
6915
+ *
6916
+ * X's perspective: Y's perspective: Z's perspective:
6917
+ * └──(3)→ Entry A └──(3)→ Entry A └──(3)→ Entry A
6918
+ * (all relations appear last in order)
6919
+ * ```
6920
+ *
6921
+ * This module preserves the original ordering from both perspectives by:
6922
+ * 1. Capturing the relation order before the entry state changes
6923
+ * 2. Restoring this order after the new relations are created
6924
+ *
6925
+ * @param uid - The unique identifier of the content type being processed
6926
+ * @param context - Object containing arrays of old and new entry versions
6927
+ * @returns Array of objects containing join table metadata and relations to be updated
6928
+ */ const load = async (uid, { oldVersions })=>{
6929
+ const relationsToUpdate = [];
6930
+ await strapi.db.transaction(async ({ trx })=>{
6931
+ const contentTypes = Object.values(strapi.contentTypes);
6932
+ const components = Object.values(strapi.components);
6933
+ for (const model of [
6934
+ ...contentTypes,
6935
+ ...components
6936
+ ]){
6937
+ const dbModel = strapi.db.metadata.get(model.uid);
6938
+ for (const attribute of Object.values(dbModel.attributes)){
6939
+ // Skip if not a bidirectional relation targeting our content type
6940
+ if (attribute.type !== 'relation' || attribute.target !== uid || !(attribute.inversedBy || attribute.mappedBy)) {
6941
+ continue;
6942
+ }
6943
+ // If it's a self referencing relation, there is no need to sync any relation
6944
+ // The order will already be handled as both sides are inside the same content type
6945
+ if (model.uid === uid) {
6946
+ continue;
6947
+ }
6948
+ const joinTable = attribute.joinTable;
6949
+ if (!joinTable) {
6950
+ continue;
6951
+ }
6952
+ const { name: targetColumnName } = joinTable.inverseJoinColumn;
6953
+ // Load all relations that need their order preserved
6954
+ const oldEntryIds = oldVersions.map((entry)=>entry.id);
6955
+ const existingRelations = await strapi.db.getConnection().select('*').from(joinTable.name).whereIn(targetColumnName, oldEntryIds).transacting(trx);
6956
+ if (existingRelations.length > 0) {
6957
+ relationsToUpdate.push({
6958
+ joinTable,
6959
+ relations: existingRelations
6960
+ });
6961
+ }
6962
+ }
6963
+ }
6964
+ });
6965
+ return relationsToUpdate;
6966
+ };
6967
+ /**
6968
+ * Synchronizes the order of bidirectional relations after content entries have changed state.
6969
+ *
6970
+ * When entries change state (e.g., draft → published), their IDs change and all relations are recreated.
6971
+ * While the order of relations from the entry's perspective is maintained (as they're created in order),
6972
+ * the inverse relations (from related entries' perspective) would all appear last in order since they're new.
6973
+ *
6974
+ * Example:
6975
+ * ```
6976
+ * Before publish:
6977
+ * Article(id:1) →(order:1)→ Category(id:5)
6978
+ * Category(id:5) →(order:3)→ Article(id:1)
6979
+ *
6980
+ * After publish (without sync):
6981
+ * Article(id:2) →(order:1)→ Category(id:5) [order preserved]
6982
+ * Category(id:5) →(order:99)→ Article(id:2) [order lost - appears last]
6983
+ *
6984
+ * After sync:
6985
+ * Article(id:2) →(order:1)→ Category(id:5) [order preserved]
6986
+ * Category(id:5) →(order:3)→ Article(id:2) [order restored]
6987
+ * ```
6988
+ *
6989
+ * @param oldEntries - Array of previous entry versions with their IDs and locales
6990
+ * @param newEntries - Array of new entry versions with their IDs and locales
6991
+ * @param existingRelations - Array of join table data containing the relations to be updated
6992
+ */ const sync = async (oldEntries, newEntries, existingRelations)=>{
6993
+ // Group new entries by locale for easier lookup
6994
+ const newEntriesByLocale = fp.keyBy('locale', newEntries);
6995
+ // Create a mapping of old entry IDs to new entry IDs based on locale
6996
+ const entryIdMapping = oldEntries.reduce((acc, oldEntry)=>{
6997
+ const newEntry = newEntriesByLocale[oldEntry.locale];
6998
+ if (!newEntry) return acc;
6999
+ acc[oldEntry.id] = newEntry.id;
7000
+ return acc;
7001
+ }, {});
7002
+ await strapi.db.transaction(async ({ trx })=>{
7003
+ for (const { joinTable, relations } of existingRelations){
7004
+ const sourceColumn = joinTable.inverseJoinColumn.name;
7005
+ const targetColumn = joinTable.joinColumn.name;
7006
+ const orderColumn = joinTable.orderColumnName;
7007
+ // Failsafe in case those don't exist
7008
+ if (!sourceColumn || !targetColumn || !orderColumn) {
7009
+ continue;
7010
+ }
7011
+ // Update order values for each relation
7012
+ // TODO: Find a way to batch it more efficiently
7013
+ await strapiUtils.async.map(relations, (relation)=>{
7014
+ const { [sourceColumn]: oldSourceId, [targetColumn]: targetId, [orderColumn]: originalOrder } = relation;
7015
+ // Update the order column for the new relation entry
7016
+ return trx.from(joinTable.name).where(sourceColumn, entryIdMapping[oldSourceId]).where(targetColumn, targetId).update({
7017
+ [orderColumn]: originalOrder
7018
+ });
7019
+ });
7020
+ }
7021
+ });
7022
+ };
7023
+
6878
7024
  const textNodeValidator = strapiUtils.yup.object().shape({
6879
7025
  type: strapiUtils.yup.string().equals([
6880
7026
  'text'
@@ -7903,7 +8049,11 @@ const createContentTypeRepository = (uid, validator = entityValidator)=>{
7903
8049
  })
7904
8050
  ]);
7905
8051
  // Load any unidirectional relation targetting the old published entries
7906
- const relationsToSync = await load(uid, {
8052
+ const relationsToSync = await load$1(uid, {
8053
+ newVersions: draftsToPublish,
8054
+ oldVersions: oldPublishedVersions
8055
+ });
8056
+ const bidirectionalRelationsToSync = await load(uid, {
7907
8057
  newVersions: draftsToPublish,
7908
8058
  oldVersions: oldPublishedVersions
7909
8059
  });
@@ -7912,10 +8062,14 @@ const createContentTypeRepository = (uid, validator = entityValidator)=>{
7912
8062
  // Transform draft entry data and create published versions
7913
8063
  const publishedEntries = await strapiUtils.async.map(draftsToPublish, (draft)=>entries.publish(draft, queryParams));
7914
8064
  // Sync unidirectional relations with the new published entries
7915
- await sync([
8065
+ await sync$1([
7916
8066
  ...oldPublishedVersions,
7917
8067
  ...draftsToPublish
7918
8068
  ], publishedEntries, relationsToSync);
8069
+ await sync([
8070
+ ...oldPublishedVersions,
8071
+ ...draftsToPublish
8072
+ ], publishedEntries, bidirectionalRelationsToSync);
7919
8073
  publishedEntries.forEach(emitEvent('entry.publish'));
7920
8074
  return {
7921
8075
  documentId,
@@ -7973,7 +8127,11 @@ const createContentTypeRepository = (uid, validator = entityValidator)=>{
7973
8127
  })
7974
8128
  ]);
7975
8129
  // Load any unidirectional relation targeting the old drafts
7976
- const relationsToSync = await load(uid, {
8130
+ const relationsToSync = await load$1(uid, {
8131
+ newVersions: versionsToDraft,
8132
+ oldVersions: oldDrafts
8133
+ });
8134
+ const bidirectionalRelationsToSync = await load(uid, {
7977
8135
  newVersions: versionsToDraft,
7978
8136
  oldVersions: oldDrafts
7979
8137
  });
@@ -7982,10 +8140,14 @@ const createContentTypeRepository = (uid, validator = entityValidator)=>{
7982
8140
  // Transform published entry data and create draft versions
7983
8141
  const draftEntries = await strapiUtils.async.map(versionsToDraft, (entry)=>entries.discardDraft(entry, queryParams));
7984
8142
  // Sync unidirectional relations with the new draft entries
7985
- await sync([
8143
+ await sync$1([
7986
8144
  ...oldDrafts,
7987
8145
  ...versionsToDraft
7988
8146
  ], draftEntries, relationsToSync);
8147
+ await sync([
8148
+ ...oldDrafts,
8149
+ ...versionsToDraft
8150
+ ], draftEntries, bidirectionalRelationsToSync);
7989
8151
  draftEntries.forEach(emitEvent('entry.draft-discard'));
7990
8152
  return {
7991
8153
  documentId,