@slicemachine/manager 0.24.14-alpha.jp-update-cr-links-unit.3 → 0.24.14-alpha.jp-update-cr-links-remove-recursion.1

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.
@@ -188,6 +188,129 @@ export class CustomTypesManager extends BaseManager {
188
188
  };
189
189
  }
190
190
 
191
+ private updateCRCustomType(
192
+ args: { customType: CrCustomType } & CustomTypeFieldIdChangedMeta,
193
+ ): CrCustomType {
194
+ const { previousPath, newPath } = args;
195
+
196
+ const customType = shallowClone(args.customType);
197
+
198
+ const [previousId] = previousPath;
199
+ const [newId] = newPath;
200
+
201
+ if (!previousId || !newId || typeof customType === "string") {
202
+ return customType;
203
+ }
204
+
205
+ if (customType.fields) {
206
+ const newFields = customType.fields.map((fieldArg) => {
207
+ const field = shallowClone(fieldArg);
208
+
209
+ const previousId = previousPath[1];
210
+ const newId = newPath[1];
211
+
212
+ if (!previousId || !newId) {
213
+ return field;
214
+ }
215
+
216
+ if (typeof field === "string") {
217
+ if (field === previousId && field !== newId) {
218
+ // We have reached a field id that matches the id that was renamed,
219
+ // so we update it new one. The field is a string, so return the new
220
+ // id.
221
+ return newId;
222
+ }
223
+
224
+ return field;
225
+ }
226
+
227
+ if (field.id === previousId && field.id !== newId) {
228
+ // We have reached a field id that matches the id that was renamed,
229
+ // so we update it new one.
230
+ // Since field is not a string, we don't exit, as we might have
231
+ // something to update further down in customtypes.
232
+ field.id = newId;
233
+ }
234
+
235
+ return {
236
+ ...field,
237
+ customtypes: field.customtypes.map((customTypeArg) => {
238
+ const customType = shallowClone(customTypeArg);
239
+ const previousId = previousPath[2];
240
+ const newId = newPath[2];
241
+
242
+ if (!previousId || !newId) {
243
+ return customType;
244
+ }
245
+
246
+ if (typeof customType === "string") {
247
+ if (customType === previousId && customType !== newId) {
248
+ // Matches the previous id, so we update it.
249
+ return newId;
250
+ }
251
+
252
+ return customType;
253
+ }
254
+
255
+ if (customType.id === previousId && customType.id !== newId) {
256
+ // Matches the previous id, so we update it and return because
257
+ // it's the last level.
258
+ return { ...customType, id: newId };
259
+ }
260
+
261
+ return customType;
262
+ }),
263
+ };
264
+ });
265
+
266
+ return { ...customType, fields: newFields };
267
+ }
268
+
269
+ return customType;
270
+ }
271
+
272
+ /**
273
+ * Map over the custom types of a Content Relationship Link and update the API
274
+ * IDs that were changed during the custom type update.
275
+ */
276
+ private updateCRCustomTypes(
277
+ args: { customTypes: CrCustomTypes } & CustomTypeFieldIdChangedMeta,
278
+ ): CrCustomTypes {
279
+ const { customTypes, ...updateMeta } = args;
280
+
281
+ return customTypes.map((customType) => {
282
+ return this.updateCRCustomType({ customType, ...updateMeta });
283
+ });
284
+ }
285
+
286
+ /**
287
+ * Update the Content Relationship API IDs of a single field. The change is
288
+ * determined by the `previousPath` and `newPath` properties.
289
+ */
290
+ private updateFieldContentRelationships<
291
+ T extends UID | NestableWidget | Group | NestedGroup,
292
+ >(args: { field: T } & CustomTypeFieldIdChangedMeta): T {
293
+ const { field, ...updateMeta } = args;
294
+ if (
295
+ field.type !== "Link" ||
296
+ field.config?.select !== "document" ||
297
+ !field.config?.customtypes
298
+ ) {
299
+ // not a content relationship field
300
+ return field;
301
+ }
302
+
303
+ const newCustomTypes = this.updateCRCustomTypes({
304
+ ...updateMeta,
305
+ customTypes: field.config.customtypes,
306
+ });
307
+
308
+ return {
309
+ ...field,
310
+ config: { ...field.config, customtypes: newCustomTypes },
311
+ };
312
+ }
313
+
191
314
  /**
192
315
  * Update the Content Relationship API IDs for all existing custom types and
193
316
  * slices. The change is determined by properties inside the `updateMeta`
@@ -213,19 +336,24 @@ export class CustomTypesManager extends BaseManager {
213
336
  // any custom type and update them to use the new one.
214
337
  const customTypes = await this.readAllCustomTypes();
215
338
 
216
- updateCustomTypeContentRelationships({
217
- models: customTypes.models,
218
- onUpdate: (model) => {
219
- pushIfDefined(
220
- crUpdates,
221
- this.sliceMachinePluginRunner?.callHook("custom-type:update", {
222
- model,
223
- }),
224
- );
225
- },
226
- previousPath,
227
- newPath,
228
- });
339
+ for (const customType of customTypes.models) {
340
+ const updatedCustomTypeModel = traverseCustomType({
341
+ customType: customType.model,
342
+ onField: ({ field }) => {
343
+ return this.updateFieldContentRelationships({
344
+ field,
345
+ previousPath,
346
+ newPath,
347
+ });
348
+ },
349
+ });
350
+
351
+ crUpdates.push(
352
+ this.sliceMachinePluginRunner.callHook("custom-type:update", {
353
+ model: updatedCustomTypeModel,
354
+ }),
355
+ );
356
+ }
229
357
 
230
358
  // Find existing slice with content relationships that link to the renamed
231
359
  // field id in all libraries and update them to use the new one.
@@ -236,20 +364,26 @@ export class CustomTypesManager extends BaseManager {
236
364
  libraryID: library.libraryID,
237
365
  });
238
366
 
239
- updateSharedSliceContentRelationships({
240
- models: slices.models,
241
- onUpdate: (model) => {
242
- pushIfDefined(
243
- crUpdates,
244
- this.sliceMachinePluginRunner?.callHook("slice:update", {
245
- libraryID: library.libraryID,
246
- model,
247
- }),
248
- );
249
- },
250
- previousPath,
251
- newPath,
252
- });
367
+ for (const slice of slices.models) {
368
+ const updatedSliceModel = traverseSharedSlice({
369
+ path: ["."],
370
+ slice: slice.model,
371
+ onField: ({ field }) => {
372
+ return this.updateFieldContentRelationships({
373
+ field,
374
+ previousPath,
375
+ newPath,
376
+ });
377
+ },
378
+ });
379
+
380
+ crUpdates.push(
381
+ this.sliceMachinePluginRunner.callHook("slice:update", {
382
+ libraryID: library.libraryID,
383
+ model: updatedSliceModel,
384
+ }),
385
+ );
386
+ }
253
387
  }
254
388
 
255
389
  // Process all the Content Relationship updates at once.
@@ -495,178 +629,10 @@ const InferSliceResponse = z.object({
495
629
  langSmithUrl: z.string().url().optional(),
496
630
  });
497
631
 
498
- function updateCRCustomType<T extends CrCustomType | CrCustomTypeFieldLeaf>(
499
- args: {
500
- customType: T;
501
- } & CustomTypeFieldIdChangedMeta,
502
- ): T {
503
- const { previousPath, newPath } = args;
504
-
505
- const customType = shallowCloneIfObject(args.customType);
506
-
507
- const [previousId] = previousPath;
508
- const [newId] = newPath;
509
-
510
- if (!previousId || !newId || typeof customType === "string") {
511
- return customType;
512
- }
513
-
514
- if (customType.fields) {
515
- const newFields = customType.fields.map((fieldArg) => {
516
- const field = shallowCloneIfObject(fieldArg);
517
-
518
- const previousId = previousPath[1];
519
- const newId = newPath[1];
520
-
521
- if (!previousId || !newId) {
522
- return field;
523
- }
524
-
525
- if (typeof field === "string") {
526
- if (field === previousId && field !== newId) {
527
- // We have reached a field id that matches the id that was renamed,
528
- // so we update it new one. The field is a string, so return the new
529
- // id.
530
- return newId;
531
- }
532
-
533
- return field;
534
- }
535
-
536
- if (field.id === previousId && field.id !== newId) {
537
- // We have reached a field id that matches the id that was renamed,
538
- // so we update it new one.
539
- // Since field is not a string, we don't exit, as we might have
540
- // something to update further down in customtypes.
541
- field.id = newId;
542
- }
543
-
544
- return {
545
- ...field,
546
- customtypes: field.customtypes.map((customType) => {
547
- return updateCRCustomType({
548
- customType,
549
- previousPath,
550
- newPath,
551
- });
552
- }),
553
- };
554
- });
555
-
556
- // @ts-expect-error We know that at this level we are returning the
557
- // right properties, but TypeScript will not trust it because it might
558
- // also have customtypes. This is because the type is not fully
559
- // recursive, it just has two levels of depth.
560
- return {
561
- id: customType.id,
562
- fields: newFields,
563
- };
564
- }
565
-
566
- return customType;
567
- }
568
-
569
- /**
570
- * Map over the custom types of a Content Relationship Link and update the API
571
- * IDs that were changed during the custom type update.
572
- */
573
- function updateCRCustomTypes(
574
- args: { customTypes: CrCustomTypes } & CustomTypeFieldIdChangedMeta,
575
- ): CrCustomTypes {
576
- const { customTypes, ...updateMeta } = args;
577
-
578
- return customTypes.map((customType) => {
579
- return updateCRCustomType({ customType, ...updateMeta });
580
- });
581
- }
582
-
583
- /**
584
- * Update the Content Relationship API IDs of a single field. The change is
585
- * determined by the `previousPath` and `newPath` properties.
586
- */
587
- function updateFieldContentRelationships<
588
- T extends UID | NestableWidget | Group | NestedGroup,
589
- >(args: { field: T } & CustomTypeFieldIdChangedMeta): T {
590
- const { field, ...updateMeta } = args;
591
- if (
592
- field.type !== "Link" ||
593
- field.config?.select !== "document" ||
594
- !field.config?.customtypes
595
- ) {
596
- // not a content relationship field
597
- return field;
598
- }
599
-
600
- const newCustomTypes = updateCRCustomTypes({
601
- ...updateMeta,
602
- customTypes: field.config.customtypes,
603
- });
604
-
605
- return {
606
- ...field,
607
- config: { ...field.config, customtypes: newCustomTypes },
608
- };
609
- }
610
-
611
- export function updateCustomTypeContentRelationships(
612
- args: {
613
- models: { model: CustomType }[];
614
- onUpdate: (model: CustomType) => void;
615
- } & CustomTypeFieldIdChangedMeta,
616
- ): void {
617
- const { models, previousPath, newPath, onUpdate } = args;
618
-
619
- for (const customType of models) {
620
- const updatedCustomTypeModel = traverseCustomType({
621
- customType: customType.model,
622
- onField: ({ field }) => {
623
- return updateFieldContentRelationships({
624
- field,
625
- previousPath,
626
- newPath,
627
- });
628
- },
629
- });
630
-
631
- onUpdate(updatedCustomTypeModel);
632
- }
633
- }
634
-
635
- export function updateSharedSliceContentRelationships(
636
- args: {
637
- models: { model: SharedSlice }[];
638
- onUpdate: (model: SharedSlice) => void;
639
- } & CustomTypeFieldIdChangedMeta,
640
- ): void {
641
- const { models, previousPath, newPath, onUpdate } = args;
642
-
643
- for (const slice of models) {
644
- const updatedSliceModel = traverseSharedSlice({
645
- path: ["."],
646
- slice: slice.model,
647
- onField: ({ field }) => {
648
- return updateFieldContentRelationships({
649
- field,
650
- previousPath,
651
- newPath,
652
- });
653
- },
654
- });
655
-
656
- onUpdate(updatedSliceModel);
657
- }
658
- }
659
-
660
- function shallowCloneIfObject<T>(value: T): T {
632
+ function shallowClone<T>(value: T): T {
661
633
  if (typeof value === "object") {
662
634
  return { ...value };
663
635
  }
664
636
 
665
637
  return value;
666
638
  }
667
-
668
- function pushIfDefined<T>(array: T[], value: T | undefined) {
669
- if (value) {
670
- array.push(value);
671
- }
672
- }