@milaboratories/pl-middle-layer 1.66.1 → 1.66.3
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.
- package/dist/mutator/project.cjs +2 -2
- package/dist/mutator/project.cjs.map +1 -1
- package/dist/mutator/project.d.ts.map +1 -1
- package/dist/mutator/project.js +2 -2
- package/dist/mutator/project.js.map +1 -1
- package/package.json +21 -21
- package/src/mutator/project-v3.test.ts +67 -0
- package/src/mutator/project.ts +6 -2
|
@@ -553,3 +553,70 @@ test("v3 blocks: migrateBlockPack assigns author marker", async () => {
|
|
|
553
553
|
});
|
|
554
554
|
});
|
|
555
555
|
});
|
|
556
|
+
|
|
557
|
+
// Regression: MILAB-6621. Updating a block whose args() returns undefined (the
|
|
558
|
+
// standard "inputs incomplete/invalid" contract, e.g. `if (!Valid.safeParse(data).success)
|
|
559
|
+
// return undefined`) must not crash. Previously applyStorageAndDeriveArgs passed the
|
|
560
|
+
// undefined value straight to createJsonFieldValue -> Buffer.from(undefined) -> ERR_INVALID_ARG_TYPE,
|
|
561
|
+
// aborting the update-block-pack task (reported by AstraZeneca on mixcr-clonotyping 2.14 -> 2.20).
|
|
562
|
+
// The sentinel input [777] makes the enter-numbers-v3 model's args() return undefined without throwing.
|
|
563
|
+
test("v3 blocks: migrateBlockPack does not crash when args() returns undefined", async () => {
|
|
564
|
+
const quickJs = await getQuickJS();
|
|
565
|
+
|
|
566
|
+
await TestHelpers.withTempRoot(async (pl) => {
|
|
567
|
+
const prj = await pl.withWriteTx("CreatingProject", async (tx) => {
|
|
568
|
+
const prjRef = await createProject(tx);
|
|
569
|
+
tx.createField(field(tx.clientRoot, "prj"), "Dynamic", prjRef);
|
|
570
|
+
await tx.commit();
|
|
571
|
+
return await toGlobalResourceId(prjRef);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
// Add block and set the sentinel state: args() returns undefined (no error).
|
|
575
|
+
await pl.withWriteTx("AddBlock", async (tx) => {
|
|
576
|
+
const mut = await ProjectMutator.load(new ProjectHelper(quickJs), tx, prj);
|
|
577
|
+
mut.addBlock(
|
|
578
|
+
{ id: "enter1", label: "Enter Numbers V3", renderingMode: "Heavy" },
|
|
579
|
+
{
|
|
580
|
+
storageMode: "fromModel",
|
|
581
|
+
blockPack: await TestBPPreparer.prepare(BPSpecEnterV3),
|
|
582
|
+
},
|
|
583
|
+
);
|
|
584
|
+
mut.setStates([
|
|
585
|
+
{
|
|
586
|
+
modelAPIVersion: 2,
|
|
587
|
+
blockId: "enter1",
|
|
588
|
+
payload: { operation: "update-block-data", value: { numbers: [777] } },
|
|
589
|
+
},
|
|
590
|
+
]);
|
|
591
|
+
mut.save();
|
|
592
|
+
await tx.commit();
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// Update the block pack — re-derives args from storage. Must NOT throw even though
|
|
596
|
+
// args() returns undefined (previously crashed inside createJsonFieldValue).
|
|
597
|
+
await pl.withWriteTx("MigrateBlockPack", async (tx) => {
|
|
598
|
+
const mut = await ProjectMutator.load(new ProjectHelper(quickJs), tx, prj);
|
|
599
|
+
mut.migrateBlockPack("enter1", await TestBPPreparer.prepare(BPSpecEnterV3));
|
|
600
|
+
mut.save();
|
|
601
|
+
await tx.commit();
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// Verify: currentArgs cleared (args() undefined), storage preserved, prerunArgs still derived.
|
|
605
|
+
await poll(pl, async (tx) => {
|
|
606
|
+
const prjR = await tx.get(prj);
|
|
607
|
+
|
|
608
|
+
const currentArgsField = prjR.data.fields.find(
|
|
609
|
+
(f) => f.name === projectFieldName("enter1", "currentArgs"),
|
|
610
|
+
);
|
|
611
|
+
expect(currentArgsField).toBeUndefined();
|
|
612
|
+
|
|
613
|
+
const blockStorage = await prjR.get(projectFieldName("enter1", "blockStorage"));
|
|
614
|
+
const storageData = JSON.parse(Buffer.from(blockStorage.data.data!).toString());
|
|
615
|
+
expect(storageData.__data).toStrictEqual({ numbers: [777] });
|
|
616
|
+
|
|
617
|
+
const currentPrerunArgs = await prjR.get(projectFieldName("enter1", "currentPrerunArgs"));
|
|
618
|
+
const prerunData = JSON.parse(Buffer.from(currentPrerunArgs.data.data!).toString());
|
|
619
|
+
expect(prerunData).toStrictEqual({ evenNumbers: [] });
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
});
|
package/src/mutator/project.ts
CHANGED
|
@@ -769,7 +769,9 @@ export class ProjectMutator {
|
|
|
769
769
|
blockConfig,
|
|
770
770
|
initialStorageJson,
|
|
771
771
|
);
|
|
772
|
-
|
|
772
|
+
// args() legitimately returns undefined when inputs are incomplete/invalid;
|
|
773
|
+
// treat that like a derivation failure and clear the field (never JSON-encode undefined).
|
|
774
|
+
if (!deriveArgsResult.error && deriveArgsResult.value !== undefined) {
|
|
773
775
|
this.setBlockFieldObj(
|
|
774
776
|
blockId,
|
|
775
777
|
"currentArgs",
|
|
@@ -1408,7 +1410,9 @@ export class ProjectMutator {
|
|
|
1408
1410
|
}
|
|
1409
1411
|
|
|
1410
1412
|
const deriveArgsResult = this.projectHelper.deriveArgsFromStorage(newConfig, storageJson);
|
|
1411
|
-
|
|
1413
|
+
// args() legitimately returns undefined when inputs are incomplete/invalid;
|
|
1414
|
+
// treat that like a derivation failure and clear the field (never JSON-encode undefined).
|
|
1415
|
+
if (!deriveArgsResult.error && deriveArgsResult.value !== undefined) {
|
|
1412
1416
|
this.setBlockFieldObj(
|
|
1413
1417
|
blockId,
|
|
1414
1418
|
"currentArgs",
|