@fmaplabs/meta-manifest 0.3.0 → 0.4.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/cli/index.cjs
CHANGED
|
@@ -266,6 +266,27 @@ function refTarget(field) {
|
|
|
266
266
|
}
|
|
267
267
|
return void 0;
|
|
268
268
|
}
|
|
269
|
+
function refTargets(field) {
|
|
270
|
+
const many = v(field.validations, "metaobject_definition_types");
|
|
271
|
+
if (many) {
|
|
272
|
+
try {
|
|
273
|
+
const arr = JSON.parse(many);
|
|
274
|
+
if (Array.isArray(arr)) return arr.map(String);
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const single = v(field.validations, "metaobject_definition_type");
|
|
279
|
+
return single ? [single] : [];
|
|
280
|
+
}
|
|
281
|
+
function mixedTargetsLiteral(field, typeToIdent, warnings) {
|
|
282
|
+
const targets = refTargets(field);
|
|
283
|
+
const idents = targets.map((t) => typeToIdent.get(t));
|
|
284
|
+
if (!targets.length || idents.some((i) => !i)) {
|
|
285
|
+
warnings.push(`unresolved mixed reference on field "${field.key}"`);
|
|
286
|
+
return void 0;
|
|
287
|
+
}
|
|
288
|
+
return `[${idents.map((i) => `() => ${i}`).join(", ")}]`;
|
|
289
|
+
}
|
|
269
290
|
function optsLiteral(entries) {
|
|
270
291
|
return entries.length ? `{ ${entries.join(", ")} }` : "";
|
|
271
292
|
}
|
|
@@ -332,6 +353,15 @@ function fieldCall(field, typeToIdent, warnings) {
|
|
|
332
353
|
const opts = optsLiteral(refEntries);
|
|
333
354
|
return opts ? `m.ref(() => ${ident}, ${opts})` : `m.ref(() => ${ident})`;
|
|
334
355
|
}
|
|
356
|
+
if (type === "mixed_reference") {
|
|
357
|
+
const arr = mixedTargetsLiteral(field, typeToIdent, warnings);
|
|
358
|
+
if (!arr) return `m.json() /* TODO: unmapped mixed reference */`;
|
|
359
|
+
const refEntries = [];
|
|
360
|
+
if (field.required) refEntries.push("required: true");
|
|
361
|
+
refEntries.push(...filterableEntry(field));
|
|
362
|
+
const opts = optsLiteral(refEntries);
|
|
363
|
+
return opts ? `m.mixedRef(${arr}, ${opts})` : `m.mixedRef(${arr})`;
|
|
364
|
+
}
|
|
335
365
|
if (type.startsWith("list.")) {
|
|
336
366
|
const inner = type.slice("list.".length);
|
|
337
367
|
const listEntries = [];
|
|
@@ -351,6 +381,10 @@ function fieldCall(field, typeToIdent, warnings) {
|
|
|
351
381
|
return `m.json() /* TODO: unmapped list reference */`;
|
|
352
382
|
}
|
|
353
383
|
innerCall = `m.ref(() => ${ident})`;
|
|
384
|
+
} else if (inner === "mixed_reference") {
|
|
385
|
+
const arr = mixedTargetsLiteral(field, typeToIdent, warnings);
|
|
386
|
+
if (!arr) return `m.json() /* TODO: unmapped list mixed reference */`;
|
|
387
|
+
innerCall = `m.mixedRef(${arr})`;
|
|
354
388
|
} else if (SIMPLE[inner]) {
|
|
355
389
|
innerCall = scalarCall(SIMPLE[inner], { ...field, required: false }, warnings);
|
|
356
390
|
} else {
|
|
@@ -417,6 +451,8 @@ function referencedTypes(def) {
|
|
|
417
451
|
if (f.type === "metaobject_reference" || f.type === "list.metaobject_reference") {
|
|
418
452
|
const t = refTarget(f);
|
|
419
453
|
if (t) out.add(t);
|
|
454
|
+
} else if (f.type === "mixed_reference" || f.type === "list.mixed_reference") {
|
|
455
|
+
for (const t of refTargets(f)) out.add(t);
|
|
420
456
|
}
|
|
421
457
|
}
|
|
422
458
|
return out;
|
|
@@ -752,25 +788,35 @@ function definitionUpdateFor(def, changes) {
|
|
|
752
788
|
function fieldInputFor(defByType, type, key) {
|
|
753
789
|
return defByType.get(type)?.fieldDefinitions.find((f) => f.key === key);
|
|
754
790
|
}
|
|
755
|
-
function
|
|
791
|
+
function fieldRefTargets(field) {
|
|
756
792
|
const out = [];
|
|
757
|
-
for (const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
if (
|
|
765
|
-
for (const t of parsed) if (typeof t === "string") out.push(t);
|
|
766
|
-
}
|
|
767
|
-
} catch {
|
|
793
|
+
for (const v2 of field.validations) {
|
|
794
|
+
if (v2.name === "metaobject_definition_type") {
|
|
795
|
+
out.push(v2.value);
|
|
796
|
+
} else if (v2.name === "metaobject_definition_types") {
|
|
797
|
+
try {
|
|
798
|
+
const parsed = JSON.parse(v2.value);
|
|
799
|
+
if (Array.isArray(parsed)) {
|
|
800
|
+
for (const t of parsed) if (typeof t === "string") out.push(t);
|
|
768
801
|
}
|
|
802
|
+
} catch {
|
|
769
803
|
}
|
|
770
804
|
}
|
|
771
805
|
}
|
|
772
806
|
return out;
|
|
773
807
|
}
|
|
808
|
+
function referenceEdges(def) {
|
|
809
|
+
return def.fieldDefinitions.flatMap(fieldRefTargets);
|
|
810
|
+
}
|
|
811
|
+
function splitCyclicFields(def, cyclicTypes) {
|
|
812
|
+
const pass1 = [];
|
|
813
|
+
const deferred = [];
|
|
814
|
+
for (const f of def.fieldDefinitions) {
|
|
815
|
+
const breaksCycle = fieldRefTargets(f).some((t) => cyclicTypes.has(t) && t !== def.type);
|
|
816
|
+
(breaksCycle ? deferred : pass1).push(f);
|
|
817
|
+
}
|
|
818
|
+
return { pass1, deferred };
|
|
819
|
+
}
|
|
774
820
|
function topoSortCreates(types, deps) {
|
|
775
821
|
const remaining = /* @__PURE__ */ new Map();
|
|
776
822
|
const dependents = /* @__PURE__ */ new Map();
|
|
@@ -813,42 +859,35 @@ async function push(client, plan, sources, options) {
|
|
|
813
859
|
deps.set(op.type, new Set(targets.filter((t) => createTypes.has(t) && t !== op.type)));
|
|
814
860
|
}
|
|
815
861
|
const { ordered, unordered } = topoSortCreates(createTypes, deps);
|
|
816
|
-
const orderedSet = new Set(ordered);
|
|
817
862
|
const cyclicTypes = new Set(unordered);
|
|
818
863
|
const createByType = new Map(createOps.map((x) => [x.op.type, x]));
|
|
819
|
-
const execOrder = [
|
|
820
|
-
...ordered.map((t) => createByType.get(t)),
|
|
821
|
-
...createOps.filter((x) => !orderedSet.has(x.op.type)),
|
|
822
|
-
...otherOps
|
|
823
|
-
];
|
|
824
864
|
const failedTypes = /* @__PURE__ */ new Set();
|
|
825
|
-
async function
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (
|
|
839
|
-
failedTypes.add(op.type);
|
|
840
|
-
return { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
841
|
-
}
|
|
842
|
-
const data2 = await execute(client, CREATE_DEFINITION_MUTATION, { definition: def });
|
|
843
|
-
const payload2 = data2.metaobjectDefinitionCreate;
|
|
844
|
-
if (payload2.userErrors.length) {
|
|
865
|
+
async function createDefinition(op, definition) {
|
|
866
|
+
const data = await execute(client, CREATE_DEFINITION_MUTATION, { definition });
|
|
867
|
+
const payload = data.metaobjectDefinitionCreate;
|
|
868
|
+
if (payload.userErrors.length) {
|
|
869
|
+
failedTypes.add(op.type);
|
|
870
|
+
return { op, status: "failed", userErrors: payload.userErrors };
|
|
871
|
+
}
|
|
872
|
+
const id = payload.metaobjectDefinition?.id;
|
|
873
|
+
if (id) idByType.set(op.type, id);
|
|
874
|
+
return { op, status: "applied", id };
|
|
875
|
+
}
|
|
876
|
+
async function applyAcyclicCreate(op) {
|
|
877
|
+
for (const dep of deps.get(op.type) ?? []) {
|
|
878
|
+
if (failedTypes.has(dep)) {
|
|
845
879
|
failedTypes.add(op.type);
|
|
846
|
-
return { op, status: "
|
|
880
|
+
return { op, status: "blocked", reason: `blocked: dependency "${dep}" was not created` };
|
|
847
881
|
}
|
|
848
|
-
const id2 = payload2.metaobjectDefinition?.id;
|
|
849
|
-
if (id2) idByType.set(op.type, id2);
|
|
850
|
-
return { op, status: "applied", id: id2 };
|
|
851
882
|
}
|
|
883
|
+
const def = defByType.get(op.type);
|
|
884
|
+
if (!def) {
|
|
885
|
+
failedTypes.add(op.type);
|
|
886
|
+
return { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
887
|
+
}
|
|
888
|
+
return createDefinition(op, def);
|
|
889
|
+
}
|
|
890
|
+
async function applyFieldOp(op) {
|
|
852
891
|
const destructive = "destructive" in op && op.destructive === true;
|
|
853
892
|
if (destructive && !allowDestructive) return { op, status: "skipped", reason: "destructive" };
|
|
854
893
|
if (failedTypes.has(op.type)) return { op, status: "blocked", reason: `blocked: definition "${op.type}" was not created` };
|
|
@@ -901,7 +940,53 @@ async function push(client, plan, sources, options) {
|
|
|
901
940
|
}
|
|
902
941
|
}
|
|
903
942
|
const results = new Array(plan.length);
|
|
904
|
-
for (const
|
|
943
|
+
for (const type of ordered) {
|
|
944
|
+
const entry = createByType.get(type);
|
|
945
|
+
results[entry.index] = await applyAcyclicCreate(entry.op);
|
|
946
|
+
}
|
|
947
|
+
const cyclicCreates = createOps.filter((x) => cyclicTypes.has(x.op.type));
|
|
948
|
+
const deferredByType = /* @__PURE__ */ new Map();
|
|
949
|
+
for (const { op, index } of cyclicCreates) {
|
|
950
|
+
const def = defByType.get(op.type);
|
|
951
|
+
if (!def) {
|
|
952
|
+
failedTypes.add(op.type);
|
|
953
|
+
results[index] = { op, status: "blocked", reason: `no definition input for "${op.type}"` };
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
const failedDep = [...deps.get(op.type) ?? []].find((d) => !cyclicTypes.has(d) && failedTypes.has(d));
|
|
957
|
+
if (failedDep) {
|
|
958
|
+
failedTypes.add(op.type);
|
|
959
|
+
results[index] = { op, status: "blocked", reason: `blocked: dependency "${failedDep}" was not created` };
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
const { pass1, deferred } = splitCyclicFields(def, cyclicTypes);
|
|
963
|
+
deferredByType.set(op.type, deferred);
|
|
964
|
+
results[index] = await createDefinition(op, { ...def, fieldDefinitions: pass1 });
|
|
965
|
+
}
|
|
966
|
+
for (const { op, index } of cyclicCreates) {
|
|
967
|
+
if (results[index]?.status !== "applied") continue;
|
|
968
|
+
const deferred = deferredByType.get(op.type) ?? [];
|
|
969
|
+
if (!deferred.length) continue;
|
|
970
|
+
const failedTarget = deferred.flatMap(fieldRefTargets).find((t) => failedTypes.has(t));
|
|
971
|
+
if (failedTarget) {
|
|
972
|
+
failedTypes.add(op.type);
|
|
973
|
+
results[index] = { op, status: "blocked", reason: `blocked: dependency "${failedTarget}" was not created` };
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
const id = idByType.get(op.type);
|
|
977
|
+
if (id == null) {
|
|
978
|
+
results[index] = { op, status: "blocked", reason: `no definition id for "${op.type}"` };
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
const definition = { fieldDefinitions: deferred.map((f) => ({ create: f })) };
|
|
982
|
+
const data = await execute(client, UPDATE_DEFINITION_MUTATION, { id, definition });
|
|
983
|
+
const payload = data.metaobjectDefinitionUpdate;
|
|
984
|
+
if (payload.userErrors.length) {
|
|
985
|
+
failedTypes.add(op.type);
|
|
986
|
+
results[index] = { op, status: "failed", userErrors: payload.userErrors };
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
for (const { op, index } of otherOps) results[index] = await applyFieldOp(op);
|
|
905
990
|
const counts = { applied: 0, skipped: 0, blocked: 0, failed: 0 };
|
|
906
991
|
for (const r of results) counts[r.status]++;
|
|
907
992
|
return { results, counts, ok: counts.failed === 0 && counts.blocked === 0 };
|