@wildwinter/toolkit 0.2.0 → 0.2.2

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.
@@ -406,7 +406,7 @@ function targetProblems(host, kind, target, path, settings, out) {
406
406
  if (!SCALAR_TYPES.includes(claim.type)) {
407
407
  out.push(err2("claim-type", atKey(at, "type"), "a claim presents a host field, which is a scalar"));
408
408
  } else {
409
- typeProblems(host, claim, at, false, out);
409
+ typeProblems(host, claim, at, false, out, true);
410
410
  }
411
411
  if (typeof claim.setting !== "string" || !settings.has(claim.setting)) {
412
412
  out.push(err2("claim-setting", atKey(at, "setting"), `a claim names its field through a setting, and "${String(claim.setting)}" is not one of the manifest's settings`));
@@ -449,7 +449,7 @@ function fieldListProblems(host, fields, path, topLevel, out) {
449
449
  }
450
450
  });
451
451
  }
452
- function typeProblems(host, decl, path, named, out) {
452
+ function typeProblems(host, decl, path, named, out, claim = false) {
453
453
  const typeAt = atKey(path, "type");
454
454
  if (decl.type === "string") {
455
455
  out.push(err2("string-type", typeAt, 'the text type is spelled "text"'));
@@ -465,6 +465,7 @@ function typeProblems(host, decl, path, named, out) {
465
465
  case "enum":
466
466
  case "flags": {
467
467
  const values = decl.values;
468
+ if (claim && values === void 0) break;
468
469
  if (!Array.isArray(values) || values.length === 0) {
469
470
  out.push(err2("values-empty", at("values"), `an ${decl.type === "enum" ? "enum" : "flags field"} lists its values`));
470
471
  sound = false;
@@ -483,6 +484,7 @@ function typeProblems(host, decl, path, named, out) {
483
484
  break;
484
485
  }
485
486
  case "quality": {
487
+ if (claim && decl.stages === void 0) break;
486
488
  for (const p of expr.qualityDeclarationProblems(decl.stages)) {
487
489
  out.push(err2(
488
490
  `quality-${p.kind === "default-not-a-stage" ? "default" : p.kind}`,
@@ -542,7 +544,11 @@ function typeProblems(host, decl, path, named, out) {
542
544
  }
543
545
  }
544
546
  if (decl.renamedStages !== void 0) renamedStagesProblems(decl, at("renamedStages"), out);
545
- if (decl.valueHelp !== void 0) {
547
+ if (decl.valueHelp !== void 0 && claim) {
548
+ if (!isObject(decl.valueHelp) || !["enum", "flags", "quality"].includes(decl.type)) {
549
+ out.push(err2("value-help", at("valueHelp"), "value help describes the values of an enum or flags field, or a quality's stages"));
550
+ }
551
+ } else if (decl.valueHelp !== void 0) {
546
552
  const vocabulary = decl.type === "quality" ? decl.stages : decl.type === "enum" || decl.type === "flags" ? decl.values : void 0;
547
553
  if (vocabulary === void 0 || !isObject(decl.valueHelp)) {
548
554
  out.push(err2("value-help", at("valueHelp"), "value help describes the values of an enum or flags field, or a quality's stages"));
@@ -623,10 +629,19 @@ function targetOf(manifest, host, kind) {
623
629
  const kinds = manifest?.targets[host];
624
630
  return kinds !== void 0 && own(kinds, kind) ? kinds[kind] : void 0;
625
631
  }
632
+ function effectiveClaim(claim, hostDecl) {
633
+ return {
634
+ ...claim,
635
+ ...claim.values === void 0 && hostDecl.values !== void 0 ? { values: hostDecl.values } : {},
636
+ ...claim.stages === void 0 && hostDecl.stages !== void 0 ? { stages: hostDecl.stages } : {},
637
+ ...claim.default === void 0 && hostDecl.default !== void 0 ? { default: hostDecl.default } : {}
638
+ };
639
+ }
626
640
 
627
641
  // src/extensions/merge.ts
628
642
  var ATOMIC = { kind: "atomic" };
629
643
  var SET = { kind: "set" };
644
+ var COMMENTS = { kind: "comments" };
630
645
  var mapOf = (of) => ({ kind: "map", of });
631
646
  var keyedBy = (key, of, opts) => ({
632
647
  kind: "keyed",
@@ -669,6 +684,7 @@ function hasShape(spec, v) {
669
684
  return true;
670
685
  case "set":
671
686
  case "keyed":
687
+ case "comments":
672
688
  return Array.isArray(v);
673
689
  case "map":
674
690
  case "object":
@@ -708,6 +724,8 @@ function mergeValue(spec, b, o, t, id, path, ctx) {
708
724
  }
709
725
  case "keyed":
710
726
  return mergeKeyed(spec, asArr(b), o, t, path, ctx);
727
+ case "comments":
728
+ return mergeThreads(asArr(b), o, t, path, ctx);
711
729
  }
712
730
  }
713
731
  function mergeKeyed(spec, B, O, T, path, ctx) {
@@ -786,6 +804,70 @@ function preservedOrder(B, O, T, survivors, path, ctx) {
786
804
  for (const k of [...survivors.keys()].sort()) if (!result.includes(k)) result.push(k);
787
805
  return result;
788
806
  }
807
+ function mergeComments(base, ours, theirs, opts) {
808
+ return mergeTree(COMMENTS, base, ours, theirs, opts);
809
+ }
810
+ function mergeThreads(B, O, T, path, ctx) {
811
+ const index = (arr) => {
812
+ const m = /* @__PURE__ */ new Map();
813
+ for (const c of arr) if (isObject(c) && typeof c["id"] === "string") m.set(c["id"], c);
814
+ return m;
815
+ };
816
+ const Bm = index(B), Om = index(O), Tm = index(T);
817
+ const out = [];
818
+ for (const id of /* @__PURE__ */ new Set([...Bm.keys(), ...Om.keys(), ...Tm.keys()])) {
819
+ const b = Bm.get(id), o = Om.get(id), t = Tm.get(id);
820
+ const here = `${path}[${id}]`;
821
+ if (o === void 0 && t === void 0) continue;
822
+ if (![b, o, t].some((c) => Array.isArray(c?.["messages"]))) {
823
+ const v = o !== void 0 && t !== void 0 ? merge3(b, o, t, id, here, ctx) : b !== void 0 && ctx.eq(o ?? t, b) ? void 0 : o ?? t;
824
+ if (isObject(v)) out.push(v);
825
+ continue;
826
+ }
827
+ const messages = mergeMessages(b, o, t, id, here, ctx);
828
+ if (messages.length === 0 || messages.every((m) => m["deleted"] === true)) continue;
829
+ const fields = {};
830
+ if (o !== void 0 && t !== void 0) {
831
+ const B0 = b ?? {};
832
+ const flag = (c, k) => k === "resolved" ? c[k] === true ? true : void 0 : c[k];
833
+ for (const k of /* @__PURE__ */ new Set([...Object.keys(o), ...Object.keys(t), ...Object.keys(B0)])) {
834
+ if (k === "messages") continue;
835
+ const v = merge3(flag(B0, k), flag(o, k), flag(t, k), id, `${here}.${k}`, ctx);
836
+ if (v !== void 0) fields[k] = v;
837
+ }
838
+ } else {
839
+ for (const [k, v] of Object.entries(o ?? t)) if (k !== "messages") fields[k] = v;
840
+ }
841
+ out.push({ ...fields, messages });
842
+ }
843
+ const first = (c) => {
844
+ const m = asArr(c["messages"])[0];
845
+ return isObject(m) && typeof m["ts"] === "string" ? m["ts"] : "";
846
+ };
847
+ return out.sort((x, y) => first(x).localeCompare(first(y)) || String(x["id"]).localeCompare(String(y["id"])));
848
+ }
849
+ function mergeMessages(b, o, t, id, here, ctx) {
850
+ const keyOf = (m) => `${String(m["author"] ?? "")}|${String(m["ts"] ?? "")}`;
851
+ const index = (c) => {
852
+ const m = /* @__PURE__ */ new Map();
853
+ for (const x of asArr(c?.["messages"])) if (isObject(x)) m.set(keyOf(x), x);
854
+ return m;
855
+ };
856
+ const Bm = index(b), Om = index(o), Tm = index(t);
857
+ const out = [];
858
+ for (const k of /* @__PURE__ */ new Set([...Bm.keys(), ...Om.keys(), ...Tm.keys()])) {
859
+ const mb = Bm.get(k), mo = Om.get(k), mt = Tm.get(k);
860
+ if ([mb, mo, mt].some((m) => m?.["deleted"] === true) || mb !== void 0 && (mo === void 0 || mt === void 0)) {
861
+ out.push({ ...mo ?? mt ?? mb, body: "", deleted: true });
862
+ } else if (mo !== void 0 && mt !== void 0) {
863
+ out.push(merge3(mb, mo, mt, id, `${here}.messages[${k}]`, ctx));
864
+ } else {
865
+ out.push(mo ?? mt);
866
+ }
867
+ }
868
+ const ts = (m) => String(m["ts"] ?? "");
869
+ return out.sort((x, y) => ts(x).localeCompare(ts(y)) || String(x["author"] ?? "").localeCompare(String(y["author"] ?? "")));
870
+ }
789
871
  function strategyForType(decl) {
790
872
  switch (decl.type) {
791
873
  case "flags":
@@ -894,6 +976,7 @@ function orphanedEntries(data, exists) {
894
976
  }
895
977
 
896
978
  exports.ATOMIC = ATOMIC;
979
+ exports.COMMENTS = COMMENTS;
897
980
  exports.HOSTS = HOSTS;
898
981
  exports.MANIFEST_FILE_SUFFIX = MANIFEST_FILE_SUFFIX;
899
982
  exports.MANIFEST_SCHEMA = MANIFEST_SCHEMA;
@@ -907,12 +990,14 @@ exports.claimClashes = claimClashes;
907
990
  exports.compileEntry = compileEntry;
908
991
  exports.compiledTarget = compiledTarget;
909
992
  exports.defaultOf = defaultOf;
993
+ exports.effectiveClaim = effectiveClaim;
910
994
  exports.entryProblems = entryProblems;
911
995
  exports.extensionDataStrategy = extensionDataStrategy;
912
996
  exports.keyedBy = keyedBy;
913
997
  exports.manifestProblems = manifestProblems;
914
998
  exports.mapOf = mapOf;
915
999
  exports.markUnresolved = markUnresolved;
1000
+ exports.mergeComments = mergeComments;
916
1001
  exports.mergeExtensionData = mergeExtensionData;
917
1002
  exports.mergeTree = mergeTree;
918
1003
  exports.objectOf = objectOf;