@fmaplabs/meta-manifest 0.3.0 → 0.5.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.
- package/README.md +14 -2
- package/dist/{chunk-ZTWFDJHN.js → chunk-OEJJXMYC.js} +144 -44
- package/dist/chunk-OEJJXMYC.js.map +1 -0
- package/dist/cli/index.cjs +128 -43
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/index.cjs +143 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZTWFDJHN.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -415,6 +415,17 @@ var MetaobjectRefField = class extends GidField {
|
|
|
415
415
|
return [{ name: "metaobject_definition_type", value: resolveType(this.target) }];
|
|
416
416
|
}
|
|
417
417
|
};
|
|
418
|
+
var MixedRefField = class extends GidField {
|
|
419
|
+
constructor(targets, opts) {
|
|
420
|
+
super(opts);
|
|
421
|
+
this.targets = targets;
|
|
422
|
+
}
|
|
423
|
+
targets;
|
|
424
|
+
shopifyType = "mixed_reference";
|
|
425
|
+
validations() {
|
|
426
|
+
return [{ name: "metaobject_definition_types", value: JSON.stringify(this.targets.map(resolveType)) }];
|
|
427
|
+
}
|
|
428
|
+
};
|
|
418
429
|
function product(opts = {}) {
|
|
419
430
|
return new SimpleRefField(opts, "product_reference");
|
|
420
431
|
}
|
|
@@ -433,6 +444,9 @@ function file(opts = {}) {
|
|
|
433
444
|
function ref(target, opts = {}) {
|
|
434
445
|
return new MetaobjectRefField(target, opts);
|
|
435
446
|
}
|
|
447
|
+
function mixedRef(targets, opts = {}) {
|
|
448
|
+
return new MixedRefField(targets, opts);
|
|
449
|
+
}
|
|
436
450
|
|
|
437
451
|
// src/fields/scalar.ts
|
|
438
452
|
var StringScalarField = class extends Field {
|
|
@@ -581,6 +595,7 @@ var m = {
|
|
|
581
595
|
page,
|
|
582
596
|
file,
|
|
583
597
|
ref,
|
|
598
|
+
mixedRef,
|
|
584
599
|
list
|
|
585
600
|
};
|
|
586
601
|
|
|
@@ -759,6 +774,27 @@ function refTarget(field) {
|
|
|
759
774
|
}
|
|
760
775
|
return void 0;
|
|
761
776
|
}
|
|
777
|
+
function refTargets(field) {
|
|
778
|
+
const many = v(field.validations, "metaobject_definition_types");
|
|
779
|
+
if (many) {
|
|
780
|
+
try {
|
|
781
|
+
const arr = JSON.parse(many);
|
|
782
|
+
if (Array.isArray(arr)) return arr.map(String);
|
|
783
|
+
} catch {
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
const single = v(field.validations, "metaobject_definition_type");
|
|
787
|
+
return single ? [single] : [];
|
|
788
|
+
}
|
|
789
|
+
function mixedTargetsLiteral(field, typeToIdent, warnings) {
|
|
790
|
+
const targets = refTargets(field);
|
|
791
|
+
const idents = targets.map((t) => typeToIdent.get(t));
|
|
792
|
+
if (!targets.length || idents.some((i) => !i)) {
|
|
793
|
+
warnings.push(`unresolved mixed reference on field "${field.key}"`);
|
|
794
|
+
return void 0;
|
|
795
|
+
}
|
|
796
|
+
return `[${idents.map((i) => `() => ${i}`).join(", ")}]`;
|
|
797
|
+
}
|
|
762
798
|
function optsLiteral(entries) {
|
|
763
799
|
return entries.length ? `{ ${entries.join(", ")} }` : "";
|
|
764
800
|
}
|
|
@@ -825,6 +861,15 @@ function fieldCall(field, typeToIdent, warnings) {
|
|
|
825
861
|
const opts = optsLiteral(refEntries);
|
|
826
862
|
return opts ? `m.ref(() => ${ident}, ${opts})` : `m.ref(() => ${ident})`;
|
|
827
863
|
}
|
|
864
|
+
if (type === "mixed_reference") {
|
|
865
|
+
const arr = mixedTargetsLiteral(field, typeToIdent, warnings);
|
|
866
|
+
if (!arr) return `m.json() /* TODO: unmapped mixed reference */`;
|
|
867
|
+
const refEntries = [];
|
|
868
|
+
if (field.required) refEntries.push("required: true");
|
|
869
|
+
refEntries.push(...filterableEntry(field));
|
|
870
|
+
const opts = optsLiteral(refEntries);
|
|
871
|
+
return opts ? `m.mixedRef(${arr}, ${opts})` : `m.mixedRef(${arr})`;
|
|
872
|
+
}
|
|
828
873
|
if (type.startsWith("list.")) {
|
|
829
874
|
const inner = type.slice("list.".length);
|
|
830
875
|
const listEntries = [];
|
|
@@ -844,6 +889,10 @@ function fieldCall(field, typeToIdent, warnings) {
|
|
|
844
889
|
return `m.json() /* TODO: unmapped list reference */`;
|
|
845
890
|
}
|
|
846
891
|
innerCall = `m.ref(() => ${ident})`;
|
|
892
|
+
} else if (inner === "mixed_reference") {
|
|
893
|
+
const arr = mixedTargetsLiteral(field, typeToIdent, warnings);
|
|
894
|
+
if (!arr) return `m.json() /* TODO: unmapped list mixed reference */`;
|
|
895
|
+
innerCall = `m.mixedRef(${arr})`;
|
|
847
896
|
} else if (SIMPLE[inner]) {
|
|
848
897
|
innerCall = scalarCall(SIMPLE[inner], { ...field, required: false }, warnings);
|
|
849
898
|
} else {
|
|
@@ -910,6 +959,8 @@ function referencedTypes(def) {
|
|
|
910
959
|
if (f.type === "metaobject_reference" || f.type === "list.metaobject_reference") {
|
|
911
960
|
const t = refTarget(f);
|
|
912
961
|
if (t) out.add(t);
|
|
962
|
+
} else if (f.type === "mixed_reference" || f.type === "list.mixed_reference") {
|
|
963
|
+
for (const t of refTargets(f)) out.add(t);
|
|
913
964
|
}
|
|
914
965
|
}
|
|
915
966
|
return out;
|
|
@@ -1330,25 +1381,35 @@ function definitionUpdateFor(def, changes) {
|
|
|
1330
1381
|
function fieldInputFor(defByType, type, key) {
|
|
1331
1382
|
return defByType.get(type)?.fieldDefinitions.find((f) => f.key === key);
|
|
1332
1383
|
}
|
|
1333
|
-
function
|
|
1384
|
+
function fieldRefTargets(field) {
|
|
1334
1385
|
const out = [];
|
|
1335
|
-
for (const
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
if (
|
|
1343
|
-
for (const t of parsed) if (typeof t === "string") out.push(t);
|
|
1344
|
-
}
|
|
1345
|
-
} catch {
|
|
1386
|
+
for (const v2 of field.validations) {
|
|
1387
|
+
if (v2.name === "metaobject_definition_type") {
|
|
1388
|
+
out.push(v2.value);
|
|
1389
|
+
} else if (v2.name === "metaobject_definition_types") {
|
|
1390
|
+
try {
|
|
1391
|
+
const parsed = JSON.parse(v2.value);
|
|
1392
|
+
if (Array.isArray(parsed)) {
|
|
1393
|
+
for (const t of parsed) if (typeof t === "string") out.push(t);
|
|
1346
1394
|
}
|
|
1395
|
+
} catch {
|
|
1347
1396
|
}
|
|
1348
1397
|
}
|
|
1349
1398
|
}
|
|
1350
1399
|
return out;
|
|
1351
1400
|
}
|
|
1401
|
+
function referenceEdges(def) {
|
|
1402
|
+
return def.fieldDefinitions.flatMap(fieldRefTargets);
|
|
1403
|
+
}
|
|
1404
|
+
function splitCyclicFields(def, cyclicTypes) {
|
|
1405
|
+
const pass1 = [];
|
|
1406
|
+
const deferred = [];
|
|
1407
|
+
for (const f of def.fieldDefinitions) {
|
|
1408
|
+
const breaksCycle = fieldRefTargets(f).some((t) => cyclicTypes.has(t) && t !== def.type);
|
|
1409
|
+
(breaksCycle ? deferred : pass1).push(f);
|
|
1410
|
+
}
|
|
1411
|
+
return { pass1, deferred };
|
|
1412
|
+
}
|
|
1352
1413
|
function topoSortCreates(types, deps) {
|
|
1353
1414
|
const remaining = /* @__PURE__ */ new Map();
|
|
1354
1415
|
const dependents = /* @__PURE__ */ new Map();
|
|
@@ -1391,42 +1452,35 @@ async function push(client, plan, sources, options) {
|
|
|
1391
1452
|
deps.set(op.type, new Set(targets.filter((t) => createTypes.has(t) && t !== op.type)));
|
|
1392
1453
|
}
|
|
1393
1454
|
const { ordered, unordered } = topoSortCreates(createTypes, deps);
|
|
1394
|
-
const orderedSet = new Set(ordered);
|
|
1395
1455
|
const cyclicTypes = new Set(unordered);
|
|
1396
1456
|
const createByType = new Map(createOps.map((x) => [x.op.type, x]));
|
|
1397
|
-
const execOrder = [
|
|
1398
|
-
...ordered.map((t) => createByType.get(t)),
|
|
1399
|
-
...createOps.filter((x) => !orderedSet.has(x.op.type)),
|
|
1400
|
-
...otherOps
|
|
1401
|
-
];
|
|
1402
1457
|
const failedTypes = /* @__PURE__ */ new Set();
|
|
1403
|
-
async function
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
if (
|
|
1417
|
-
failedTypes.add(op.type);
|
|
1418
|
-
return { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
1419
|
-
}
|
|
1420
|
-
const data2 = await execute(client, CREATE_DEFINITION_MUTATION, { definition: def });
|
|
1421
|
-
const payload2 = data2.metaobjectDefinitionCreate;
|
|
1422
|
-
if (payload2.userErrors.length) {
|
|
1458
|
+
async function createDefinition(op, definition) {
|
|
1459
|
+
const data = await execute(client, CREATE_DEFINITION_MUTATION, { definition });
|
|
1460
|
+
const payload = data.metaobjectDefinitionCreate;
|
|
1461
|
+
if (payload.userErrors.length) {
|
|
1462
|
+
failedTypes.add(op.type);
|
|
1463
|
+
return { op, status: "failed", userErrors: payload.userErrors };
|
|
1464
|
+
}
|
|
1465
|
+
const id = payload.metaobjectDefinition?.id;
|
|
1466
|
+
if (id) idByType.set(op.type, id);
|
|
1467
|
+
return { op, status: "applied", id };
|
|
1468
|
+
}
|
|
1469
|
+
async function applyAcyclicCreate(op) {
|
|
1470
|
+
for (const dep of deps.get(op.type) ?? []) {
|
|
1471
|
+
if (failedTypes.has(dep)) {
|
|
1423
1472
|
failedTypes.add(op.type);
|
|
1424
|
-
return { op, status: "
|
|
1473
|
+
return { op, status: "blocked", reason: `blocked: dependency "${dep}" was not created` };
|
|
1425
1474
|
}
|
|
1426
|
-
const id2 = payload2.metaobjectDefinition?.id;
|
|
1427
|
-
if (id2) idByType.set(op.type, id2);
|
|
1428
|
-
return { op, status: "applied", id: id2 };
|
|
1429
1475
|
}
|
|
1476
|
+
const def = defByType.get(op.type);
|
|
1477
|
+
if (!def) {
|
|
1478
|
+
failedTypes.add(op.type);
|
|
1479
|
+
return { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
1480
|
+
}
|
|
1481
|
+
return createDefinition(op, def);
|
|
1482
|
+
}
|
|
1483
|
+
async function applyFieldOp(op) {
|
|
1430
1484
|
const destructive = "destructive" in op && op.destructive === true;
|
|
1431
1485
|
if (destructive && !allowDestructive) return { op, status: "skipped", reason: "destructive" };
|
|
1432
1486
|
if (failedTypes.has(op.type)) return { op, status: "blocked", reason: `blocked: definition "${op.type}" was not created` };
|
|
@@ -1479,7 +1533,53 @@ async function push(client, plan, sources, options) {
|
|
|
1479
1533
|
}
|
|
1480
1534
|
}
|
|
1481
1535
|
const results = new Array(plan.length);
|
|
1482
|
-
for (const
|
|
1536
|
+
for (const type of ordered) {
|
|
1537
|
+
const entry = createByType.get(type);
|
|
1538
|
+
results[entry.index] = await applyAcyclicCreate(entry.op);
|
|
1539
|
+
}
|
|
1540
|
+
const cyclicCreates = createOps.filter((x) => cyclicTypes.has(x.op.type));
|
|
1541
|
+
const deferredByType = /* @__PURE__ */ new Map();
|
|
1542
|
+
for (const { op, index } of cyclicCreates) {
|
|
1543
|
+
const def = defByType.get(op.type);
|
|
1544
|
+
if (!def) {
|
|
1545
|
+
failedTypes.add(op.type);
|
|
1546
|
+
results[index] = { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
const failedDep = [...deps.get(op.type) ?? []].find((d) => !cyclicTypes.has(d) && failedTypes.has(d));
|
|
1550
|
+
if (failedDep) {
|
|
1551
|
+
failedTypes.add(op.type);
|
|
1552
|
+
results[index] = { op, status: "blocked", reason: `blocked: dependency "${failedDep}" was not created` };
|
|
1553
|
+
continue;
|
|
1554
|
+
}
|
|
1555
|
+
const { pass1, deferred } = splitCyclicFields(def, cyclicTypes);
|
|
1556
|
+
deferredByType.set(op.type, deferred);
|
|
1557
|
+
results[index] = await createDefinition(op, { ...def, fieldDefinitions: pass1 });
|
|
1558
|
+
}
|
|
1559
|
+
for (const { op, index } of cyclicCreates) {
|
|
1560
|
+
if (results[index]?.status !== "applied") continue;
|
|
1561
|
+
const deferred = deferredByType.get(op.type) ?? [];
|
|
1562
|
+
if (!deferred.length) continue;
|
|
1563
|
+
const failedTarget = deferred.flatMap(fieldRefTargets).find((t) => failedTypes.has(t));
|
|
1564
|
+
if (failedTarget) {
|
|
1565
|
+
failedTypes.add(op.type);
|
|
1566
|
+
results[index] = { op, status: "blocked", reason: `blocked: dependency "${failedTarget}" was not created` };
|
|
1567
|
+
continue;
|
|
1568
|
+
}
|
|
1569
|
+
const id = idByType.get(op.type);
|
|
1570
|
+
if (id == null) {
|
|
1571
|
+
results[index] = { op, status: "blocked", reason: `no definition id for "${op.type}"` };
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
const definition = { fieldDefinitions: deferred.map((f) => ({ create: f })) };
|
|
1575
|
+
const data = await execute(client, UPDATE_DEFINITION_MUTATION, { id, definition });
|
|
1576
|
+
const payload = data.metaobjectDefinitionUpdate;
|
|
1577
|
+
if (payload.userErrors.length) {
|
|
1578
|
+
failedTypes.add(op.type);
|
|
1579
|
+
results[index] = { op, status: "failed", userErrors: payload.userErrors };
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
for (const { op, index } of otherOps) results[index] = await applyFieldOp(op);
|
|
1483
1583
|
const counts = { applied: 0, skipped: 0, blocked: 0, failed: 0 };
|
|
1484
1584
|
for (const r of results) counts[r.status]++;
|
|
1485
1585
|
return { results, counts, ok: counts.failed === 0 && counts.blocked === 0 };
|