@milaboratories/pl-middle-layer 1.54.3 → 1.54.4

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.
@@ -118,7 +118,7 @@ function cached<ModId, T>(modIdCb: () => ModId, valueCb: () => T): () => T {
118
118
  lastModId = currentModId;
119
119
  value = valueCb();
120
120
  }
121
- return valueCb();
121
+ return value!;
122
122
  };
123
123
  }
124
124
 
@@ -136,21 +136,35 @@ class BlockInfo {
136
136
 
137
137
  if ((this.fields.prodOutput === undefined) !== (this.fields.prodCtx === undefined))
138
138
  throw new Error("inconsistent prod fields");
139
+ if ((this.fields.prodOutput === undefined) !== (this.fields.prodUiCtx === undefined))
140
+ throw new Error("inconsistent prod fields (prodUiCtx)");
139
141
 
140
142
  if ((this.fields.stagingOutput === undefined) !== (this.fields.stagingCtx === undefined))
141
143
  throw new Error("inconsistent stage fields");
144
+ if ((this.fields.stagingOutput === undefined) !== (this.fields.stagingUiCtx === undefined))
145
+ throw new Error("inconsistent stage fields (stagingUiCtx)");
142
146
 
143
147
  if (
144
148
  (this.fields.prodOutputPrevious === undefined) !==
145
149
  (this.fields.prodCtxPrevious === undefined)
146
150
  )
147
151
  throw new Error("inconsistent prod cache fields");
152
+ if (
153
+ (this.fields.prodOutputPrevious === undefined) !==
154
+ (this.fields.prodUiCtxPrevious === undefined)
155
+ )
156
+ throw new Error("inconsistent prod cache fields (prodUiCtxPrevious)");
148
157
 
149
158
  if (
150
159
  (this.fields.stagingOutputPrevious === undefined) !==
151
160
  (this.fields.stagingCtxPrevious === undefined)
152
161
  )
153
162
  throw new Error("inconsistent stage cache fields");
163
+ if (
164
+ (this.fields.stagingOutputPrevious === undefined) !==
165
+ (this.fields.stagingUiCtxPrevious === undefined)
166
+ )
167
+ throw new Error("inconsistent stage cache fields (stagingUiCtxPrevious)");
154
168
 
155
169
  if (this.fields.blockPack === undefined) throw new Error("no block pack field");
156
170
 
@@ -337,19 +351,28 @@ export class ProjectMutator {
337
351
  ) {}
338
352
 
339
353
  private fixProblemsAndMigrate() {
340
- // Fix inconsistent production fields
354
+ // Fix inconsistent production fields.
355
+ // All four fields (prodArgs, prodOutput, prodCtx, prodUiCtx) must be present together.
356
+ // prodUiCtx can be missing after project duplication: prodCtx uses a holder wrapper
357
+ // (always non-null), but prodUiCtx is a raw FieldRef that may still be NullResourceId
358
+ // at snapshot time and thus not copied.
341
359
  this.blockInfos.forEach((blockInfo) => {
342
360
  if (
343
361
  blockInfo.fields.prodArgs === undefined ||
344
362
  blockInfo.fields.prodOutput === undefined ||
345
- blockInfo.fields.prodCtx === undefined
363
+ blockInfo.fields.prodCtx === undefined ||
364
+ blockInfo.fields.prodUiCtx === undefined
346
365
  )
347
366
  this.deleteBlockFields(blockInfo.id, "prodArgs", "prodOutput", "prodCtx", "prodUiCtx");
348
367
  });
349
368
 
350
- // Fix inconsistent staging fields
369
+ // Fix inconsistent staging fields (same FieldRef issue for stagingUiCtx)
351
370
  this.blockInfos.forEach((blockInfo) => {
352
- if (blockInfo.fields.stagingOutput === undefined || blockInfo.fields.stagingCtx === undefined)
371
+ if (
372
+ blockInfo.fields.stagingOutput === undefined ||
373
+ blockInfo.fields.stagingCtx === undefined ||
374
+ blockInfo.fields.stagingUiCtx === undefined
375
+ )
353
376
  this.deleteBlockFields(blockInfo.id, "stagingOutput", "stagingCtx", "stagingUiCtx");
354
377
  });
355
378
 
@@ -357,7 +380,8 @@ export class ProjectMutator {
357
380
  this.blockInfos.forEach((blockInfo) => {
358
381
  if (
359
382
  blockInfo.fields.prodOutputPrevious === undefined ||
360
- blockInfo.fields.prodCtxPrevious === undefined
383
+ blockInfo.fields.prodCtxPrevious === undefined ||
384
+ blockInfo.fields.prodUiCtxPrevious === undefined
361
385
  )
362
386
  this.deleteBlockFields(
363
387
  blockInfo.id,
@@ -367,7 +391,8 @@ export class ProjectMutator {
367
391
  );
368
392
  if (
369
393
  blockInfo.fields.stagingOutputPrevious === undefined ||
370
- blockInfo.fields.stagingCtxPrevious === undefined
394
+ blockInfo.fields.stagingCtxPrevious === undefined ||
395
+ blockInfo.fields.stagingUiCtxPrevious === undefined
371
396
  )
372
397
  this.deleteBlockFields(
373
398
  blockInfo.id,
@@ -1984,11 +2009,16 @@ export async function duplicateProject(
1984
2009
  tx.setKValue(newPrj, ProjectCreatedTimestamp, ts);
1985
2010
  tx.setKValue(newPrj, ProjectLastModifiedTimestamp, ts);
1986
2011
 
1987
- // Copy all dynamic fields by sharing references
2012
+ // Copy only persistent block fields (FieldsToDuplicate).
2013
+ // Transient fields (prodChainCtx, staging*, *Previous) are rebuilt on project open
2014
+ // by fixProblemsAndMigrate(). Copying them is both unnecessary and dangerous:
2015
+ // some fields use raw FieldRefs (not holder-wrapped) whose values may be NullResourceId
2016
+ // at snapshot time, leading to partially copied field groups and broken project state.
1988
2017
  for (const f of sourceData.fields) {
1989
- if (isNotNullResourceId(f.value)) {
1990
- tx.createField(field(newPrj, f.name), "Dynamic", f.value);
1991
- }
2018
+ if (isNullResourceId(f.value)) continue;
2019
+ const parsed = parseProjectField(f.name);
2020
+ if (parsed !== undefined && !FieldsToDuplicate.has(parsed.fieldName)) continue;
2021
+ tx.createField(field(newPrj, f.name), "Dynamic", f.value);
1992
2022
  }
1993
2023
 
1994
2024
  return newPrj;