@packall/core 0.3.3 → 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/dist/bundle.d.ts +7 -6
- package/dist/bundle.d.ts.map +1 -1
- package/dist/enums/artifact-kind.d.ts +6 -0
- package/dist/enums/artifact-kind.d.ts.map +1 -1
- package/dist/enums/layout.d.ts +6 -0
- package/dist/enums/layout.d.ts.map +1 -1
- package/dist/index.js +135 -28
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +48 -12
- package/dist/layout.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bundle.ts +140 -7
- package/src/enums/artifact-kind.ts +6 -0
- package/src/enums/layout.ts +6 -0
- package/src/layout.ts +83 -12
- package/src/manifest.ts +2 -2
package/dist/bundle.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export type BundleArtifact = {
|
|
|
38
38
|
readonly path: string;
|
|
39
39
|
readonly bytes: number;
|
|
40
40
|
readonly packageCount: number;
|
|
41
|
-
/** Which spec this artifact covers.
|
|
41
|
+
/** Which spec this artifact covers. Only `per-spec` sets it. */
|
|
42
42
|
readonly spec?: string | undefined;
|
|
43
43
|
readonly version?: string | undefined;
|
|
44
44
|
};
|
|
@@ -76,11 +76,12 @@ export type PlanSummary = {
|
|
|
76
76
|
/**
|
|
77
77
|
* The files a run will write, known before anything is downloaded.
|
|
78
78
|
*
|
|
79
|
-
* `dir`
|
|
80
|
-
*
|
|
81
|
-
* version
|
|
82
|
-
*
|
|
83
|
-
* the
|
|
79
|
+
* `dir` and `flat` are the odd ones: they merge a package tree into `outDir`
|
|
80
|
+
* rather than writing an archive. Either way a package's path is derived from
|
|
81
|
+
* its name and version, so the same package at the same version is the same
|
|
82
|
+
* bytes at the same path — an overlap is idempotent rather than destructive.
|
|
83
|
+
* Only the two summary files are genuinely replaced, and those are the ones
|
|
84
|
+
* worth guarding.
|
|
84
85
|
*/
|
|
85
86
|
export type PlannedOutput = {
|
|
86
87
|
readonly file: string;
|
package/dist/bundle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,12 @@ import type { ValueOf } from "../types/value-of.js";
|
|
|
3
3
|
export declare const ArtifactKind: {
|
|
4
4
|
readonly Archive: "archive";
|
|
5
5
|
readonly Directory: "directory";
|
|
6
|
+
/**
|
|
7
|
+
* A loose file that is not an archive — the manifest and the import guide,
|
|
8
|
+
* which `dir` and `flat` write beside the tarballs rather than sealing
|
|
9
|
+
* inside one.
|
|
10
|
+
*/
|
|
11
|
+
readonly File: "file";
|
|
6
12
|
};
|
|
7
13
|
export type ArtifactKind = ValueOf<typeof ArtifactKind>;
|
|
8
14
|
//# sourceMappingURL=artifact-kind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-kind.d.ts","sourceRoot":"","sources":["../../src/enums/artifact-kind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,uDAAuD;AACvD,eAAO,MAAM,YAAY;aACxB,OAAO,EAAE,SAAS;aAClB,SAAS,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"artifact-kind.d.ts","sourceRoot":"","sources":["../../src/enums/artifact-kind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,uDAAuD;AACvD,eAAO,MAAM,YAAY;aACxB,OAAO,EAAE,SAAS;aAClB,SAAS,EAAE,WAAW;IACtB;;;;OAIG;aACH,IAAI,EAAE,MAAM;CACH,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
package/dist/enums/layout.d.ts
CHANGED
|
@@ -17,6 +17,12 @@ export declare const Layout: {
|
|
|
17
17
|
* `jf rt upload` or rsync.
|
|
18
18
|
*/
|
|
19
19
|
readonly Dir: "dir";
|
|
20
|
+
/**
|
|
21
|
+
* Every tarball side by side in one directory — no archive, and no
|
|
22
|
+
* `name/-/` nesting. For tooling that globs `*.tgz` out of one directory
|
|
23
|
+
* rather than walking a registry tree.
|
|
24
|
+
*/
|
|
25
|
+
readonly Flat: "flat";
|
|
20
26
|
};
|
|
21
27
|
export type Layout = ValueOf<typeof Layout>;
|
|
22
28
|
export declare const Layouts: ReadonlyArray<Layout>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/enums/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,+CAA+C;AAC/C,eAAO,MAAM,MAAM;IAClB;;;;OAIG;aACH,OAAO,EAAE,UAAU;IACnB;;;OAGG;aACH,MAAM,EAAE,QAAQ;IAChB;;;OAGG;aACH,GAAG,EAAE,KAAK;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/enums/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,+CAA+C;AAC/C,eAAO,MAAM,MAAM;IAClB;;;;OAIG;aACH,OAAO,EAAE,UAAU;IACnB;;;OAGG;aACH,MAAM,EAAE,QAAQ;IAChB;;;OAGG;aACH,GAAG,EAAE,KAAK;IACV;;;;OAIG;aACH,IAAI,EAAE,MAAM;CACH,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,MAAM,CAAC,CAAC;AAE5C,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC,MAAM,CAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,8 @@ import * as Path from "effect/Path";
|
|
|
15
15
|
/** What a bundle run wrote to the output directory. */
|
|
16
16
|
const ArtifactKind = {
|
|
17
17
|
Archive: "archive",
|
|
18
|
-
Directory: "directory"
|
|
18
|
+
Directory: "directory",
|
|
19
|
+
File: "file"
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
//#endregion
|
|
@@ -56,7 +57,8 @@ const InputFileKind = {
|
|
|
56
57
|
const Layout = {
|
|
57
58
|
PerSpec: "per-spec",
|
|
58
59
|
Single: "single",
|
|
59
|
-
Dir: "dir"
|
|
60
|
+
Dir: "dir",
|
|
61
|
+
Flat: "flat"
|
|
60
62
|
};
|
|
61
63
|
const Layouts = Object.values(Layout);
|
|
62
64
|
|
|
@@ -660,22 +662,6 @@ const strengthByAlgorithm = {
|
|
|
660
662
|
|
|
661
663
|
//#endregion
|
|
662
664
|
//#region src/layout.ts
|
|
663
|
-
/**
|
|
664
|
-
* The on-disk shape of a bundle.
|
|
665
|
-
*
|
|
666
|
-
* Everything is laid out exactly the way a registry serves it:
|
|
667
|
-
*
|
|
668
|
-
* lodash/-/lodash-4.17.21.tgz
|
|
669
|
-
* @babel/core/-/core-7.24.0.tgz
|
|
670
|
-
*
|
|
671
|
-
* That is not an Artifactory convention — it is the path structure in every
|
|
672
|
-
* `dist.tarball` URL npm publishes. See `notes/requirements.md` § FR-12 for
|
|
673
|
-
* what that buys.
|
|
674
|
-
*
|
|
675
|
-
* The one shape worth noticing before editing anything here: a scoped
|
|
676
|
-
* package's file name drops the scope, so `@babel/core` becomes
|
|
677
|
-
* `core-7.24.0.tgz` under an `@babel/core/-/` directory.
|
|
678
|
-
*/
|
|
679
665
|
/** Splits `@scope/name` into its parts. `scope` is undefined when unscoped. */
|
|
680
666
|
const splitName = (name) => {
|
|
681
667
|
if (!name.startsWith("@")) return {
|
|
@@ -708,7 +694,7 @@ const MANIFEST_FILE = "bundle-manifest.json";
|
|
|
708
694
|
/** File name of the short import guide that ships inside every bundle. */
|
|
709
695
|
const README_FILE = "IMPORT.md";
|
|
710
696
|
/**
|
|
711
|
-
*
|
|
697
|
+
* A flat, collision-free file name for one `name@version`.
|
|
712
698
|
*
|
|
713
699
|
* It is the spec, with the one character a file name cannot hold taken out:
|
|
714
700
|
* `@types/react@19.2.18` becomes `@types-react@19.2.18.tgz`. So the name of the
|
|
@@ -738,18 +724,41 @@ const README_FILE = "IMPORT.md";
|
|
|
738
724
|
* has to cross-reference against a manifest.
|
|
739
725
|
*
|
|
740
726
|
* It does not make every collision impossible — `@a/b-c` and `@a-b/c` still
|
|
741
|
-
* meet — so
|
|
742
|
-
* scoped-against-unscoped one is `@babel/core` beside
|
|
743
|
-
* real migration somebody could be bundling.
|
|
727
|
+
* meet — so the run still checks before downloading anything. That pair is
|
|
728
|
+
* pathological; the scoped-against-unscoped one is `@babel/core` beside
|
|
729
|
+
* `babel-core`, which is a real migration somebody could be bundling.
|
|
744
730
|
*
|
|
745
731
|
* The leading `@` is safe here in a way it is not inside the archive: tar's
|
|
746
732
|
* splice convention applies to the *file list* it is given, which is what
|
|
747
|
-
* `archive.ts` guards with `./`.
|
|
733
|
+
* `archive.ts` guards with `./`. These are output paths, not entries.
|
|
748
734
|
*/
|
|
749
|
-
const
|
|
735
|
+
const flatName = (name, version) => {
|
|
750
736
|
const { scope, bare } = splitName(name);
|
|
751
737
|
return `${scope === void 0 ? bare : `${scope}-${bare}`}@${version}.tgz`;
|
|
752
738
|
};
|
|
739
|
+
/**
|
|
740
|
+
* Name of the archive produced for one root spec in `per-spec` layout.
|
|
741
|
+
*
|
|
742
|
+
* The same rule as {@link flatName}, which is where the reasoning lives — a
|
|
743
|
+
* per-spec archive and a `flat` package tarball are both "one file in a
|
|
744
|
+
* directory, named for what is in it", and there is no reason for a directory
|
|
745
|
+
* of bundles and a directory of packages to be read differently.
|
|
746
|
+
*/
|
|
747
|
+
const perSpecArchiveName = flatName;
|
|
748
|
+
/**
|
|
749
|
+
* The path of one package tarball within a bundle. The one place the two
|
|
750
|
+
* shapes are chosen between, so a manifest and the tree it describes cannot
|
|
751
|
+
* drift apart.
|
|
752
|
+
*
|
|
753
|
+
* `flat` keeps a file name and no directories, and uses {@link flatName}
|
|
754
|
+
* rather than the registry file name: with the directories gone that name is
|
|
755
|
+
* all there is to tell two packages apart, and the registry one drops the
|
|
756
|
+
* scope, which would put `@types/node` and `node` on the same file. The name
|
|
757
|
+
* is free to differ — `npm publish <tarball>` reads a package's name and
|
|
758
|
+
* version from the `package.json` inside it, not from what the file is
|
|
759
|
+
* called.
|
|
760
|
+
*/
|
|
761
|
+
const bundlePath = (layout, name, version) => layout === Layout.Flat ? flatName(name, version) : packagePath(name, version);
|
|
753
762
|
/** Name of the archive produced in `single` layout. */
|
|
754
763
|
const singleArchiveName = (base = "bundle") => `${base}.tgz`;
|
|
755
764
|
/**
|
|
@@ -757,8 +766,14 @@ const singleArchiveName = (base = "bundle") => `${base}.tgz`;
|
|
|
757
766
|
*
|
|
758
767
|
* Kept short and copy-pasteable on purpose: whoever opens this is mid-task on a
|
|
759
768
|
* restricted network and does not want prose.
|
|
769
|
+
*
|
|
770
|
+
* Layout-aware, because the instructions genuinely differ — a registry-layout
|
|
771
|
+
* tree uploads into Artifactory as it stands and a flat directory does not, and
|
|
772
|
+
* a guide that said otherwise would be discovered to be wrong by somebody who
|
|
773
|
+
* can no longer look anything up.
|
|
760
774
|
*/
|
|
761
|
-
const importGuide = (options) =>
|
|
775
|
+
const importGuide = (options) => options.layout === Layout.Flat ? flatGuide(options) : treeGuide(options);
|
|
776
|
+
const treeGuide = (options) => `# Importing this bundle
|
|
762
777
|
|
|
763
778
|
${options.packageCount} package tarball(s), laid out exactly as an npm registry serves them:
|
|
764
779
|
|
|
@@ -786,6 +801,32 @@ Publish each tarball individually:
|
|
|
786
801
|
|
|
787
802
|
node -e "const m=require('./bundle/${MANIFEST_FILE}');console.log(m.packages.length+' packages')"
|
|
788
803
|
|
|
804
|
+
Every entry in ${MANIFEST_FILE} carries the integrity string the source registry
|
|
805
|
+
advertised, and each tarball was checked against it at download time.
|
|
806
|
+
`;
|
|
807
|
+
const flatGuide = (options) => `# Importing this bundle
|
|
808
|
+
|
|
809
|
+
${options.packageCount} package tarball(s), side by side in this one directory:
|
|
810
|
+
|
|
811
|
+
<name>@<version>.tgz
|
|
812
|
+
@<scope>-<name>@<version>.tgz
|
|
813
|
+
|
|
814
|
+
Created ${options.createdAt} by packall ${options.toolVersion}.
|
|
815
|
+
See ${MANIFEST_FILE} for the full list with checksums.
|
|
816
|
+
|
|
817
|
+
## Publishing into a registry
|
|
818
|
+
|
|
819
|
+
\`npm publish\` reads each package's name and version from the \`package.json\`
|
|
820
|
+
inside its tarball, so neither the file names nor the order matter:
|
|
821
|
+
|
|
822
|
+
for f in *.tgz; do npm publish --registry <url> "$f"; done
|
|
823
|
+
|
|
824
|
+
For a tree that uploads into Artifactory as it stands, use --layout dir instead.
|
|
825
|
+
|
|
826
|
+
## Verifying before import
|
|
827
|
+
|
|
828
|
+
node -e "const m=require('./${MANIFEST_FILE}');console.log(m.packages.length+' packages')"
|
|
829
|
+
|
|
789
830
|
Every entry in ${MANIFEST_FILE} carries the integrity string the source registry
|
|
790
831
|
advertised, and each tarball was checked against it at download time.
|
|
791
832
|
`;
|
|
@@ -804,7 +845,7 @@ const buildManifest = (input) => {
|
|
|
804
845
|
return {
|
|
805
846
|
name: pkg.name,
|
|
806
847
|
version: pkg.version,
|
|
807
|
-
path:
|
|
848
|
+
path: bundlePath(input.options.layout, pkg.name, pkg.version),
|
|
808
849
|
tarball: pkg.manifest.dist.tarball,
|
|
809
850
|
integrity: pkg.manifest.dist.integrity,
|
|
810
851
|
shasum: pkg.manifest.dist.shasum,
|
|
@@ -2554,7 +2595,7 @@ const bundleResolved = (resolution, options) => Effect.gen(function* () {
|
|
|
2554
2595
|
* first second rather than after a twenty-minute transfer.
|
|
2555
2596
|
*/
|
|
2556
2597
|
const plannedOutputs = (resolution, options) => {
|
|
2557
|
-
if (options.layout === Layout.Dir) return [{ file: MANIFEST_FILE }, { file: README_FILE }];
|
|
2598
|
+
if (options.layout === Layout.Dir || options.layout === Layout.Flat) return [{ file: MANIFEST_FILE }, { file: README_FILE }];
|
|
2558
2599
|
if (options.layout === Layout.Single) return [{ file: singleArchiveName(options.archiveName ?? "bundle") }];
|
|
2559
2600
|
return perSpecTargets(resolution).map(({ root, version }) => ({
|
|
2560
2601
|
file: perSpecArchiveName(root.spec.name, version),
|
|
@@ -2609,6 +2650,7 @@ const emit$1 = (input, staging) => {
|
|
|
2609
2650
|
case Layout.Single: return emitSingle(input);
|
|
2610
2651
|
case Layout.Dir: return emitDirectory(input);
|
|
2611
2652
|
case Layout.PerSpec: return emitPerSpec(input, staging);
|
|
2653
|
+
case Layout.Flat: return emitFlat(input, staging);
|
|
2612
2654
|
}
|
|
2613
2655
|
};
|
|
2614
2656
|
/** One tarball containing the deduplicated union of every closure. */
|
|
@@ -2658,6 +2700,47 @@ const emitDirectory = (input) => Effect.gen(function* () {
|
|
|
2658
2700
|
}];
|
|
2659
2701
|
});
|
|
2660
2702
|
/**
|
|
2703
|
+
* The flat directory: every tarball side by side, no archive, no nesting.
|
|
2704
|
+
*
|
|
2705
|
+
* The tarballs are the untouched registry ones — only their names are ours,
|
|
2706
|
+
* and `bundlePath` says why.
|
|
2707
|
+
*/
|
|
2708
|
+
const emitFlat = (input, staging) => Effect.gen(function* () {
|
|
2709
|
+
const fs = yield* FileSystem.FileSystem;
|
|
2710
|
+
const path = yield* Path.Path;
|
|
2711
|
+
const flatDir = path.join(staging, "flat");
|
|
2712
|
+
yield* fs.makeDirectory(flatDir, { recursive: true });
|
|
2713
|
+
for (const pkg of input.resolution.packages) {
|
|
2714
|
+
const parts = packagePath(pkg.name, pkg.version).split("/");
|
|
2715
|
+
yield* linkOrCopy(path.join(input.packagesDir, ...parts), path.join(flatDir, flatName(pkg.name, pkg.version)));
|
|
2716
|
+
}
|
|
2717
|
+
yield* writeBundleMetadata({
|
|
2718
|
+
dir: flatDir,
|
|
2719
|
+
resolution: input.resolution,
|
|
2720
|
+
included: input.resolution.packages,
|
|
2721
|
+
options: input.options,
|
|
2722
|
+
registryInfo: input.registryInfo,
|
|
2723
|
+
sizes: input.report.sizes
|
|
2724
|
+
});
|
|
2725
|
+
yield* fs.copy(flatDir, input.options.outDir, { overwrite: true }).pipe(Effect.mapError((cause) => new OutputError(input.options.outDir, "could not write output tree", { cause })));
|
|
2726
|
+
const tarballs = input.resolution.packages.map((pkg) => ({
|
|
2727
|
+
kind: ArtifactKind.Archive,
|
|
2728
|
+
path: path.join(input.options.outDir, flatName(pkg.name, pkg.version)),
|
|
2729
|
+
bytes: input.report.sizes.get(`${pkg.name}@${pkg.version}`) ?? 0,
|
|
2730
|
+
packageCount: 1
|
|
2731
|
+
}));
|
|
2732
|
+
const summaries = yield* Effect.forEach([MANIFEST_FILE, README_FILE], (file) => Effect.gen(function* () {
|
|
2733
|
+
const info = yield* fs.stat(path.join(flatDir, file));
|
|
2734
|
+
return {
|
|
2735
|
+
kind: ArtifactKind.File,
|
|
2736
|
+
path: path.join(input.options.outDir, file),
|
|
2737
|
+
bytes: Number(info.size),
|
|
2738
|
+
packageCount: 0
|
|
2739
|
+
};
|
|
2740
|
+
}));
|
|
2741
|
+
return [...tarballs, ...summaries];
|
|
2742
|
+
});
|
|
2743
|
+
/**
|
|
2661
2744
|
* One tarball per resolved root *version*.
|
|
2662
2745
|
*
|
|
2663
2746
|
* Under `--all-versions react@^18` this produces `react-18.0.0.tgz`,
|
|
@@ -2743,7 +2826,8 @@ const writeBundleMetadata = (input) => Effect.gen(function* () {
|
|
|
2743
2826
|
yield* fs.writeFileString(path.join(input.dir, README_FILE), importGuide({
|
|
2744
2827
|
packageCount: input.included.length,
|
|
2745
2828
|
createdAt: createdAt.toISOString(),
|
|
2746
|
-
toolVersion: input.options.toolVersion
|
|
2829
|
+
toolVersion: input.options.toolVersion,
|
|
2830
|
+
layout: input.options.layout
|
|
2747
2831
|
}));
|
|
2748
2832
|
});
|
|
2749
2833
|
/** Sorted top-level entries of a directory, used as the tar entry list. */
|
|
@@ -2751,6 +2835,28 @@ const topLevelEntries = (dir) => Effect.gen(function* () {
|
|
|
2751
2835
|
return (yield* (yield* FileSystem.FileSystem).readDirectory(dir)).toSorted();
|
|
2752
2836
|
});
|
|
2753
2837
|
/**
|
|
2838
|
+
* `assertDistinctOutputs`, over package tarballs instead of archives.
|
|
2839
|
+
*
|
|
2840
|
+
* `flat` is the only layout with nothing but a file name to tell two packages
|
|
2841
|
+
* apart — everywhere else a tarball keeps its unique `name/-/` directory. What
|
|
2842
|
+
* is left to catch is the pathological pair, `@a/b-c` against `@a-b/c`; the
|
|
2843
|
+
* plausible one is impossible by construction, which is what `flatName` buys.
|
|
2844
|
+
*/
|
|
2845
|
+
const assertDistinctFlatNames = (resolution, options) => Effect.gen(function* () {
|
|
2846
|
+
if (options.layout !== Layout.Flat) return;
|
|
2847
|
+
const owners = /* @__PURE__ */ new Map();
|
|
2848
|
+
for (const pkg of resolution.packages) {
|
|
2849
|
+
const file = flatName(pkg.name, pkg.version);
|
|
2850
|
+
const claimed = owners.get(file);
|
|
2851
|
+
if (claimed === void 0) owners.set(file, [`${pkg.name}@${pkg.version}`]);
|
|
2852
|
+
else claimed.push(`${pkg.name}@${pkg.version}`);
|
|
2853
|
+
}
|
|
2854
|
+
const collisions = [...owners].filter(([, packages]) => packages.length > 1);
|
|
2855
|
+
if (collisions.length === 0) return;
|
|
2856
|
+
const described = collisions.map(([file, packages]) => `${packages.join(" and ")} would both be ${file}`).join("; ");
|
|
2857
|
+
return yield* Effect.fail(new OutputError(options.outDir, `two packages want the same file name — ${described}. \`flat\` layout has only the file name to tell them apart, and the \`/\` in a scope becomes a \`-\` to make one. Use --layout dir, which keeps each package in its own directory.`));
|
|
2858
|
+
});
|
|
2859
|
+
/**
|
|
2754
2860
|
* Two different packages must not want the same file name.
|
|
2755
2861
|
*
|
|
2756
2862
|
* Most of what this used to catch is now impossible: an archive is named for
|
|
@@ -2810,6 +2916,7 @@ const prepareOutputDir = (resolution, options) => Effect.gen(function* () {
|
|
|
2810
2916
|
const path = yield* Path.Path;
|
|
2811
2917
|
const outDir = options.outDir;
|
|
2812
2918
|
yield* assertDistinctOutputs(resolution, options);
|
|
2919
|
+
yield* assertDistinctFlatNames(resolution, options);
|
|
2813
2920
|
if (!options.force) {
|
|
2814
2921
|
const clashes = [];
|
|
2815
2922
|
for (const planned of plannedOutputs(resolution, options)) {
|