@absolutejs/changelog 0.4.0 → 0.5.1

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/index.d.ts CHANGED
@@ -3,8 +3,8 @@ export { change, manual, moved, renamed } from "./authoring";
3
3
  export { builtSurface, changelogPaths, loadUnreleased, readJsonFile, type LoadedEntries, type LoadedEntry, } from "./entries";
4
4
  export { changesBetween, disruptiveBetween, mechanicalMigrations, migrationsBetween, parseChangelog, releasesBetween, symbolsDisturbedBetween, validateChange, type ChangeAt, type ChangelogRead, type MigrationAt, } from "./read";
5
5
  export { describeReconciliation, reconcile, type Reconciliation, type Unannounced, } from "./reconcile";
6
- export { isPackageName, packageArchive, packageVersions, publishedChangelog, publishedSurface, type PackageVersions, type RegistryOptions, } from "./registry";
7
- export { changeShape, declaresTypes, diffSurface, notable, surfaceOfArchive, surfaceOfFiles, typeEntriesOf, type ChangeShape, type PackageSurface, type SurfaceChange, type SurfaceDiff, } from "./surface";
6
+ export { forgetRegistry, isPackageName, packageArchive, packageVersions, publishedChangelog, publishedSurface, type PackageVersions, type RegistryOptions, } from "./registry";
7
+ export { changeShape, declaresTypes, diffSurface, notable, surfaceOfArchive, surfaceOfFiles, typeEntriesOf, type ChangeShape, type PackageSurface, type SurfaceChange, type SurfaceDiff, type SurfaceName, type TypeEntry, type Withdrawal, } from "./surface";
8
8
  export { asText, readTar, type TarLimits } from "./tarball";
9
9
  export { CHANGELOG_CONTRACT, CHANGELOG_FILE, CHANGELOG_MARKDOWN, CHANGE_KINDS, DISRUPTIVE_KINDS, isDisruptive, isMechanical, UNRELEASED_DIRECTORY, type Change, type ChangeKind, type Changelog, type DisruptiveChange, type DisruptiveKind, type Migration, type NonEmpty, type OrdinaryChange, type Release, } from "./types";
10
10
  export { compareVersions, isPrerelease, nextVersion, parseVersion, releaseKindFor, type ReleaseKind, } from "./versioning";
package/dist/index.js CHANGED
@@ -410,7 +410,14 @@ var isKind = (value) => typeof value === "string" && CHANGE_KINDS.some((known) =
410
410
  var isDisruptiveKind = (kind) => kind === "breaking" || kind === "removed";
411
411
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
412
412
  var isText = (value) => typeof value === "string" && value.trim().length > 0;
413
- var textList = (value) => Array.isArray(value) && value.length > 0 && value.every(isText) ? value : undefined;
413
+ var textList = (value, where, problems) => {
414
+ if (value === undefined)
415
+ return;
416
+ if (Array.isArray(value) && value.length > 0 && value.every(isText))
417
+ return value.filter((entry) => typeof entry === "string");
418
+ problems.push(`${where}: symbols is not a list of names`);
419
+ return;
420
+ };
414
421
  var readMigration = (value, where, problems) => {
415
422
  if (!isRecord(value) || !isText(value.instruction)) {
416
423
  problems.push(`${where}: migration needs an instruction`);
@@ -459,7 +466,7 @@ var readChange = (value, where, problems) => {
459
466
  ...isText(value.reference) ? { reference: value.reference } : {},
460
467
  summary: value.summary
461
468
  };
462
- const symbols = textList(value.symbols);
469
+ const symbols = textList(value.symbols, where, problems);
463
470
  const [first, ...rest] = symbols ?? [];
464
471
  if (kind === "breaking" || kind === "removed") {
465
472
  const migration = readMigration(value.migration, where, problems);
@@ -490,7 +497,8 @@ var readRelease = (value, where, problems) => {
490
497
  problems.push(`${where}: not an object`);
491
498
  return;
492
499
  }
493
- if (!isText(value.version) || parseVersion(value.version) === undefined) {
500
+ const version = isText(value.version) ? value.version.trim() : undefined;
501
+ if (version === undefined || parseVersion(version) === undefined) {
494
502
  problems.push(`${where}: version is not a version`);
495
503
  return;
496
504
  }
@@ -513,7 +521,7 @@ var readRelease = (value, where, problems) => {
513
521
  changes: [head, ...tail],
514
522
  date: value.date,
515
523
  ...isText(value.note) ? { note: value.note } : {},
516
- version: value.version
524
+ version
517
525
  };
518
526
  return release;
519
527
  };
@@ -533,7 +541,7 @@ var parseChangelog = (value) => {
533
541
  return { problems: ["not an object"] };
534
542
  if (!isText(value.name))
535
543
  problems.push("needs a package name");
536
- if (typeof value.contract !== "number" || value.contract > CHANGELOG_CONTRACT)
544
+ if (!Number.isInteger(value.contract) || Number(value.contract) > CHANGELOG_CONTRACT)
537
545
  problems.push(`contract ${JSON.stringify(value.contract)} is newer than ${CHANGELOG_CONTRACT}, which this reader understands`);
538
546
  const raw = value.releases;
539
547
  if (!Array.isArray(raw))
@@ -735,33 +743,55 @@ var surfaceOfArchive = (archive) => {
735
743
  };
736
744
  var surfaceOfFiles = (files, entries) => {
737
745
  const surface = new Map;
738
- for (const entry of entries)
739
- for (const [name, text] of exportsOf(files, entry, new Set))
740
- if (!surface.has(name))
741
- surface.set(name, text);
746
+ const offered = entries.flatMap((entry) => [...exportsOf(files, entry.path, new Set)].map(([name, declaration]) => ({ declaration, name, specifier: entry.specifier })));
747
+ for (const { declaration, name, specifier } of offered) {
748
+ const known = surface.get(name);
749
+ if (known === undefined)
750
+ surface.set(name, { declaration, entries: [specifier] });
751
+ else if (!known.entries.includes(specifier))
752
+ known.entries.push(specifier);
753
+ }
754
+ for (const value of surface.values())
755
+ value.entries.sort();
742
756
  return surface;
743
757
  };
744
- var typeCandidatesIn = (value) => {
758
+ var exportEntries = (value, packageName, specifier) => {
759
+ const here = specifier ?? packageName;
745
760
  if (typeof value === "string")
746
- return [value];
761
+ return [{ specifier: here, value }];
747
762
  if (typeof value !== "object" || value === null)
748
763
  return [];
749
- return Object.entries(value).flatMap(([key, nested]) => key === "types" || key === "typings" ? typeCandidatesIn(nested) : typeCandidatesIn(nested));
764
+ return Object.entries(value).flatMap(([key, nested]) => key.startsWith(".") ? exportEntries(nested, packageName, key === "." ? packageName : `${packageName}${key.slice(1)}`) : exportEntries(nested, packageName, here));
750
765
  };
751
766
  var typeEntriesOf = (manifest, files) => {
752
767
  const record = typeof manifest === "object" && manifest !== null ? new Map(Object.entries(manifest)) : new Map;
753
- const claimed = [
754
- record.get("types"),
755
- record.get("typings"),
756
- ...typeCandidatesIn(record.get("exports"))
768
+ const named = record.get("name");
769
+ const packageName = typeof named === "string" ? named : "";
770
+ const resolved = (value, specifier) => {
771
+ if (typeof value !== "string")
772
+ return [];
773
+ const cleaned = value.replace(/^\.\//u, "");
774
+ const candidates = DECLARATION.test(cleaned) ? [cleaned] : [
775
+ cleaned.replace(/\.[cm]?js$/u, ".d.ts"),
776
+ cleaned.replace(/\.[cm]?js$/u, ".d.mts"),
777
+ cleaned.replace(/\.[cm]?js$/u, ".d.cts")
778
+ ];
779
+ return candidates.filter((candidate) => files.has(candidate)).map((resolvedPath) => ({ path: resolvedPath, specifier }));
780
+ };
781
+ const found = [
782
+ ...resolved(record.get("types"), packageName),
783
+ ...resolved(record.get("typings"), packageName),
784
+ ...exportEntries(record.get("exports"), packageName).flatMap((entry) => resolved(entry.value, entry.specifier))
757
785
  ];
758
- const entries = claimed.filter((value) => typeof value === "string").map((value) => value.replace(/^\.\//u, "")).flatMap((cleaned) => DECLARATION.test(cleaned) ? [cleaned] : [
759
- cleaned.replace(/\.[cm]?js$/u, ".d.ts"),
760
- cleaned.replace(/\.[cm]?js$/u, ".d.mts"),
761
- cleaned.replace(/\.[cm]?js$/u, ".d.cts")
762
- ]).filter((candidate) => files.has(candidate));
763
- const fallback = entries.length === 0 && files.has("dist/index.d.ts") ? ["dist/index.d.ts"] : [];
764
- return [...new Set([...entries, ...fallback])];
786
+ const fallback = found.length === 0 && files.has("dist/index.d.ts") ? [{ path: "dist/index.d.ts", specifier: packageName }] : [];
787
+ const seen = new Set;
788
+ return [...found, ...fallback].filter((entry) => {
789
+ const key = `${entry.specifier}\x00${entry.path}`;
790
+ if (seen.has(key))
791
+ return false;
792
+ seen.add(key);
793
+ return true;
794
+ });
765
795
  };
766
796
  var SHAPE = {
767
797
  members: "members",
@@ -816,23 +846,33 @@ var changeShape = (change2) => {
816
846
  };
817
847
  var diffSurface = (before, after) => {
818
848
  const removed = [];
849
+ const withdrawn = [];
819
850
  const changed = [];
820
- for (const [name, declaration] of before) {
851
+ for (const [name, was] of before) {
821
852
  const now = after.get(name);
822
853
  if (now === undefined)
823
854
  removed.push(name);
824
- else if (now !== declaration)
855
+ if (now === undefined)
856
+ continue;
857
+ const lost = was.entries.filter((entry) => !now.entries.includes(entry));
858
+ if (lost.length > 0)
859
+ withdrawn.push({ from: lost, name });
860
+ if (now.declaration !== was.declaration)
825
861
  changed.push({
826
- after: now,
827
- before: declaration,
862
+ after: now.declaration,
863
+ before: was.declaration,
828
864
  name,
829
- shape: changeShape({ after: now, before: declaration })
865
+ shape: changeShape({
866
+ after: now.declaration,
867
+ before: was.declaration
868
+ })
830
869
  });
831
870
  }
832
871
  return {
833
872
  added: [...after.keys()].filter((name) => !before.has(name)),
834
873
  changed,
835
- removed
874
+ removed,
875
+ withdrawn
836
876
  };
837
877
  };
838
878
  var notable = (diff) => diff.changed.filter((change2) => change2.shape === "parameters" || change2.shape === "members");
@@ -955,10 +995,11 @@ var describeReconciliation = (found) => {
955
995
  members: "changed the members of its type",
956
996
  parameters: "changed what it is called with",
957
997
  removed: "is no longer exported",
958
- types: "changed its declaration"
998
+ types: "changed its declaration",
999
+ withdrawn: "is no longer exported from"
959
1000
  };
960
1001
  for (const entry of found.unannounced)
961
- lines.push(`\`${entry.name}\` ${moved2[entry.kind]} and no entry says so`);
1002
+ lines.push(entry.kind === "withdrawn" ? `\`${entry.name}\` ${moved2.withdrawn} ${(entry.from ?? []).join(", ")} and no entry says so` : `\`${entry.name}\` ${moved2[entry.kind]} and no entry says so`);
962
1003
  for (const name of found.unknownSymbols)
963
1004
  lines.push(`an entry names \`${name}\`, which this package does not export`);
964
1005
  lines.push(...found.wrongMigrations);
@@ -969,6 +1010,7 @@ var reconcile = (input) => {
969
1010
  const mentioned = new Set(input.changes.flatMap((change2) => [...change2.symbols ?? []]));
970
1011
  const unannounced = [
971
1012
  ...input.diff.removed.filter((name) => !disruptive.has(name)).map((name) => ({ kind: "removed", name })),
1013
+ ...input.diff.withdrawn.filter((entry) => !disruptive.has(entry.name)).map((entry) => ({ from: entry.from, kind: "withdrawn", name: entry.name })),
972
1014
  ...input.diff.changed.filter((change2) => !mentioned.has(change2.name) && change2.shape !== "unknown").map((change2) => ({ kind: change2.shape, name: change2.name }))
973
1015
  ];
974
1016
  const unknownSymbols = [
@@ -993,6 +1035,8 @@ var MAX_ARCHIVE_BYTES = MAX_ARCHIVE_MEBIBYTES * MEBIBYTE2;
993
1035
  var MAX_DOWNLOAD_MEBIBYTES = 32;
994
1036
  var MAX_DOWNLOAD_BYTES = MAX_DOWNLOAD_MEBIBYTES * MEBIBYTE2;
995
1037
  var TIMEOUT_MS = 20000;
1038
+ var NOT_FOUND = 404;
1039
+ var NOTHING_PUBLISHED = { published: [], tarballs: {} };
996
1040
  var PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/u;
997
1041
  var MAX_NAME_LENGTH = 214;
998
1042
  var isPackageName = (name) => name.length <= MAX_NAME_LENGTH && PACKAGE_NAME.test(name);
@@ -1036,9 +1080,25 @@ var packageArchive = async (name, version, options = {}) => {
1036
1080
  return;
1037
1081
  }
1038
1082
  };
1083
+ var packuments = new Map;
1084
+ var SECONDS_PER_MINUTE = 60;
1085
+ var MILLISECONDS_PER_SECOND = 1000;
1086
+ var PACKUMENT_MINUTES = 5;
1087
+ var PACKUMENT_TTL_MS = PACKUMENT_MINUTES * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND;
1088
+ var forgetRegistry = () => packuments.clear();
1039
1089
  var packageVersions = async (name, options = {}) => {
1040
1090
  if (!isPackageName(name))
1041
1091
  return;
1092
+ const cacheable = options.fetch === undefined && options.registry === undefined;
1093
+ const known = cacheable ? packuments.get(name) : undefined;
1094
+ if (known !== undefined && Date.now() - known.asked < PACKUMENT_TTL_MS)
1095
+ return known.value;
1096
+ const value = askRegistry(name, options);
1097
+ if (cacheable)
1098
+ packuments.set(name, { asked: Date.now(), value });
1099
+ return value;
1100
+ };
1101
+ var askRegistry = async (name, options) => {
1042
1102
  const call = options.fetch ?? fetch;
1043
1103
  const url = `${options.registry ?? DEFAULT_REGISTRY}/${name.replace("/", "%2f")}`;
1044
1104
  try {
@@ -1047,9 +1107,9 @@ var packageVersions = async (name, options = {}) => {
1047
1107
  signal: AbortSignal.timeout(TIMEOUT_MS)
1048
1108
  });
1049
1109
  const response = abbreviated.ok ? abbreviated : await call(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });
1050
- if (!response.ok)
1051
- return;
1052
- return readPackument(await response.json());
1110
+ if (response.ok)
1111
+ return readPackument(await response.json());
1112
+ return response.status === NOT_FOUND ? NOTHING_PUBLISHED : undefined;
1053
1113
  } catch {
1054
1114
  return;
1055
1115
  }
@@ -1196,6 +1256,7 @@ export {
1196
1256
  describeReconciliation,
1197
1257
  diffSurface,
1198
1258
  disruptiveBetween,
1259
+ forgetRegistry,
1199
1260
  isDisruptive,
1200
1261
  isMechanical,
1201
1262
  isPackageName,
@@ -1228,5 +1289,5 @@ export {
1228
1289
  validateChange
1229
1290
  };
1230
1291
 
1231
- //# debugId=7DC9C4F3C075733D64756E2164756E21
1292
+ //# debugId=C07818292D22AD6164756E2164756E21
1232
1293
  //# sourceMappingURL=index.js.map