@alchemy.run/pkg 2.0.0-beta.80 → 2.0.0-beta.82
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/Manifest.d.ts.map +1 -1
- package/dist/Manifest.js.map +1 -1
- package/dist/Protocol.d.ts +1 -1
- package/dist/Protocol.d.ts.map +1 -1
- package/dist/Protocol.js +3 -12
- package/dist/Protocol.js.map +1 -1
- package/dist/Registry/Bindings.d.ts.map +1 -1
- package/dist/Registry/Bindings.js.map +1 -1
- package/dist/Registry/GitHub.d.ts +2 -2
- package/dist/Registry/GitHub.d.ts.map +1 -1
- package/dist/Registry/GitHub.js +10 -37
- package/dist/Registry/GitHub.js.map +1 -1
- package/dist/Registry/Handler.d.ts +1 -1
- package/dist/Registry/Handler.d.ts.map +1 -1
- package/dist/Registry/Handler.js +25 -33
- package/dist/Registry/Handler.js.map +1 -1
- package/dist/Registry/KVCache.d.ts.map +1 -1
- package/dist/Registry/KVCache.js +1 -1
- package/dist/Registry/KVCache.js.map +1 -1
- package/dist/Registry/Sweep.d.ts.map +1 -1
- package/dist/Registry/Sweep.js +3 -8
- package/dist/Registry/Sweep.js.map +1 -1
- package/dist/Registry/Tags.d.ts.map +1 -1
- package/dist/Registry/Tags.js +1 -1
- package/dist/Registry/Tags.js.map +1 -1
- package/dist/Registry.d.ts +23 -1
- package/dist/Registry.d.ts.map +1 -1
- package/dist/Registry.js +1 -1
- package/dist/Registry.js.map +1 -1
- package/dist/cli/bin.d.ts +1 -1
- package/dist/cli/bin.d.ts.map +1 -1
- package/dist/cli/bin.js +6 -10
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/pack.d.ts +11 -0
- package/dist/cli/pack.d.ts.map +1 -1
- package/dist/cli/pack.js +97 -24
- package/dist/cli/pack.js.map +1 -1
- package/dist/cli/publish.d.ts.map +1 -1
- package/dist/cli/publish.js +2 -2
- package/dist/cli/publish.js.map +1 -1
- package/package.json +26 -25
- package/src/Manifest.ts +1 -3
- package/src/Protocol.ts +12 -28
- package/src/Registry/Bindings.ts +1 -4
- package/src/Registry/GitHub.ts +25 -84
- package/src/Registry/Handler.ts +44 -100
- package/src/Registry/KVCache.ts +6 -17
- package/src/Registry/Sweep.ts +13 -26
- package/src/Registry/Tags.ts +8 -16
- package/src/Registry.ts +5 -15
- package/src/cli/bin.ts +9 -19
- package/src/cli/pack.ts +126 -74
- package/src/cli/publish.ts +11 -23
package/src/cli/pack.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { gunzipSync, gzipSync } from "node:zlib";
|
|
2
|
+
import { exec } from "alchemy/Util/exec";
|
|
3
|
+
import { sha256 } from "alchemy/Util/sha256";
|
|
1
4
|
import * as Config from "effect/Config";
|
|
2
5
|
import * as Console from "effect/Console";
|
|
3
6
|
import * as Data from "effect/Data";
|
|
@@ -5,14 +8,11 @@ import * as Effect from "effect/Effect";
|
|
|
5
8
|
import * as FileSystem from "effect/FileSystem";
|
|
6
9
|
import * as Option from "effect/Option";
|
|
7
10
|
import * as Path from "effect/Path";
|
|
11
|
+
import * as ChildProcess from "effect/process/ChildProcess";
|
|
8
12
|
import * as Schema from "effect/Schema";
|
|
9
13
|
import * as SchemaIssue from "effect/SchemaIssue";
|
|
10
14
|
import * as SchemaTransformation from "effect/SchemaTransformation";
|
|
11
|
-
import * as ChildProcess from "effect/process/ChildProcess";
|
|
12
|
-
import { exec } from "alchemy/Util/exec";
|
|
13
|
-
import { sha256 } from "alchemy/Util/sha256";
|
|
14
15
|
import { packTar, unpackTar, type TarHeader } from "modern-tar";
|
|
15
|
-
import { gunzipSync, gzipSync } from "node:zlib";
|
|
16
16
|
import {
|
|
17
17
|
GroupName,
|
|
18
18
|
MANIFEST_FILE,
|
|
@@ -48,8 +48,7 @@ export const Group = Schema.String.pipe(
|
|
|
48
48
|
.split(",")
|
|
49
49
|
.map((attribute) => attribute.trim())
|
|
50
50
|
.filter((attribute) => attribute.length > 0);
|
|
51
|
-
return match &&
|
|
52
|
-
attributes.every((attribute) => attribute === "Collapsed")
|
|
51
|
+
return match && attributes.every((attribute) => attribute === "Collapsed")
|
|
53
52
|
? Effect.succeed({
|
|
54
53
|
name: match[1]!,
|
|
55
54
|
pattern: match[3]!,
|
|
@@ -64,9 +63,7 @@ export const Group = Schema.String.pipe(
|
|
|
64
63
|
);
|
|
65
64
|
},
|
|
66
65
|
encode: (group) =>
|
|
67
|
-
Effect.succeed(
|
|
68
|
-
`${group.name}${group.collapsed ? "[Collapsed]" : ""}=${group.pattern}`,
|
|
69
|
-
),
|
|
66
|
+
Effect.succeed(`${group.name}${group.collapsed ? "[Collapsed]" : ""}=${group.pattern}`),
|
|
70
67
|
}),
|
|
71
68
|
),
|
|
72
69
|
);
|
|
@@ -86,9 +83,7 @@ export const DEPENDENCY_SECTIONS = [
|
|
|
86
83
|
"optionalDependencies",
|
|
87
84
|
] as const;
|
|
88
85
|
|
|
89
|
-
const DependencyMap = Schema.optionalKey(
|
|
90
|
-
Schema.Record(Schema.String, Schema.String),
|
|
91
|
-
);
|
|
86
|
+
const DependencyMap = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
|
|
92
87
|
|
|
93
88
|
export const DependencySections = Schema.Struct({
|
|
94
89
|
dependencies: DependencyMap,
|
|
@@ -167,8 +162,7 @@ export const selectPackages = (
|
|
|
167
162
|
changedFiles.some((file) =>
|
|
168
163
|
[...REBUILD_ALL_PATHS, ...rebuildAllPaths].some((pattern) =>
|
|
169
164
|
pattern.endsWith("/**")
|
|
170
|
-
? file === pattern.slice(0, -3) ||
|
|
171
|
-
file.startsWith(pattern.slice(0, -2))
|
|
165
|
+
? file === pattern.slice(0, -3) || file.startsWith(pattern.slice(0, -2))
|
|
172
166
|
: file === pattern,
|
|
173
167
|
),
|
|
174
168
|
)
|
|
@@ -180,9 +174,7 @@ export const selectPackages = (
|
|
|
180
174
|
.filter((pkg) =>
|
|
181
175
|
changedFiles.some(
|
|
182
176
|
(file) =>
|
|
183
|
-
file === pkg.dir ||
|
|
184
|
-
file.startsWith(`${pkg.dir}/`) ||
|
|
185
|
-
pkg.dir.startsWith(`${file}/`),
|
|
177
|
+
file === pkg.dir || file.startsWith(`${pkg.dir}/`) || pkg.dir.startsWith(`${file}/`),
|
|
186
178
|
),
|
|
187
179
|
)
|
|
188
180
|
.map((pkg) => pkg.name),
|
|
@@ -218,9 +210,7 @@ export const expandBraces = (pattern: string): string[] => {
|
|
|
218
210
|
.split(",")
|
|
219
211
|
.map((alternative) => alternative.trim())
|
|
220
212
|
.filter((alternative) => alternative.length > 0)
|
|
221
|
-
.flatMap((alternative) =>
|
|
222
|
-
expandBraces(`${match[1]}${alternative}${match[3]}`),
|
|
223
|
-
);
|
|
213
|
+
.flatMap((alternative) => expandBraces(`${match[1]}${alternative}${match[3]}`));
|
|
224
214
|
};
|
|
225
215
|
|
|
226
216
|
/**
|
|
@@ -236,10 +226,7 @@ const expand = Effect.fn("expandGlob")(function* (cwd: string, glob: string) {
|
|
|
236
226
|
return [...new Set(results)];
|
|
237
227
|
});
|
|
238
228
|
|
|
239
|
-
const expandPattern = Effect.fn("expandPattern")(function* (
|
|
240
|
-
cwd: string,
|
|
241
|
-
pattern: string,
|
|
242
|
-
) {
|
|
229
|
+
const expandPattern = Effect.fn("expandPattern")(function* (cwd: string, pattern: string) {
|
|
243
230
|
const fs = yield* FileSystem.FileSystem;
|
|
244
231
|
const path = yield* Path.Path;
|
|
245
232
|
if (pattern.includes("**")) {
|
|
@@ -312,6 +299,91 @@ export const discover = Effect.fn("discoverPackages")(function* (
|
|
|
312
299
|
return [...found.values()];
|
|
313
300
|
});
|
|
314
301
|
|
|
302
|
+
/** Display group of workspace dependencies packed without being listed by `--group`. */
|
|
303
|
+
export const TRANSITIVE_GROUP: Group = {
|
|
304
|
+
name: "Transitive Dependencies",
|
|
305
|
+
pattern: "",
|
|
306
|
+
collapsed: true,
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/** Sections a consumer installs, so a workspace dependency in one has to be published too. */
|
|
310
|
+
const INSTALLED_SECTIONS = ["dependencies", "peerDependencies", "optionalDependencies"] as const;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Add every `workspace:` dependency the discovered packages install,
|
|
314
|
+
* transitively, so a listed package never links to a version that was
|
|
315
|
+
* not published alongside it. Each dependency is resolved the way Node
|
|
316
|
+
* would, through the `node_modules` link the package manager created,
|
|
317
|
+
* walking up no further than `root`. Added packages join
|
|
318
|
+
* {@link TRANSITIVE_GROUP}.
|
|
319
|
+
*/
|
|
320
|
+
export const discoverWorkspaceDependencies = Effect.fn("discoverWorkspaceDependencies")(function* (
|
|
321
|
+
cwd: string,
|
|
322
|
+
root: string,
|
|
323
|
+
packages: ReadonlyArray<WorkspacePackage>,
|
|
324
|
+
) {
|
|
325
|
+
const fs = yield* FileSystem.FileSystem;
|
|
326
|
+
const path = yield* Path.Path;
|
|
327
|
+
const decode = Schema.decodeUnknownEffect(
|
|
328
|
+
Schema.fromJsonString(Schema.Struct({ ...PackageJson.fields, ...DependencySections.fields })),
|
|
329
|
+
);
|
|
330
|
+
// Links resolve to real paths, so compare everything by real path.
|
|
331
|
+
const realCwd = yield* fs.realPath(cwd);
|
|
332
|
+
const realRoot = yield* fs.realPath(root);
|
|
333
|
+
const found = new Map(packages.map((pkg) => [pkg.name, pkg]));
|
|
334
|
+
const realDirs = new Map<string, string>();
|
|
335
|
+
for (const pkg of packages) realDirs.set(pkg.name, yield* fs.realPath(pkg.absDir));
|
|
336
|
+
const added: WorkspacePackage[] = [];
|
|
337
|
+
|
|
338
|
+
const resolve = Effect.fn(function* (from: string, name: string) {
|
|
339
|
+
let dir = from;
|
|
340
|
+
while (true) {
|
|
341
|
+
const link = path.join(dir, "node_modules", name);
|
|
342
|
+
if (yield* fs.exists(link)) return yield* fs.realPath(link);
|
|
343
|
+
const relative = path.relative(realRoot, dir);
|
|
344
|
+
if (relative === "" || relative.startsWith("..")) break;
|
|
345
|
+
dir = path.dirname(dir);
|
|
346
|
+
}
|
|
347
|
+
return yield* new WorkspaceError({
|
|
348
|
+
message: `Cannot resolve workspace dependency ${name} from ${from}: install dependencies before packing`,
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const pending = [...packages];
|
|
353
|
+
for (const dependent of pending) {
|
|
354
|
+
const manifest = yield* decode(
|
|
355
|
+
yield* fs.readFileString(path.join(dependent.absDir, "package.json")),
|
|
356
|
+
);
|
|
357
|
+
const names = INSTALLED_SECTIONS.flatMap((section) =>
|
|
358
|
+
Object.entries(manifest[section] ?? {})
|
|
359
|
+
.filter(([, spec]) => spec.startsWith("workspace:"))
|
|
360
|
+
.map(([name]) => name),
|
|
361
|
+
);
|
|
362
|
+
for (const name of [...new Set(names)].sort()) {
|
|
363
|
+
if (found.has(name)) continue;
|
|
364
|
+
const absDir = yield* resolve(realDirs.get(dependent.name)!, name);
|
|
365
|
+
const dependency = yield* decode(yield* fs.readFileString(path.join(absDir, "package.json")));
|
|
366
|
+
if (dependency.private) {
|
|
367
|
+
return yield* new WorkspaceError({
|
|
368
|
+
message: `${dependent.name} depends on private workspace package ${name}, which cannot be published`,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
const pkg: WorkspacePackage = {
|
|
372
|
+
name,
|
|
373
|
+
version: dependency.version ?? "0.0.0",
|
|
374
|
+
dir: path.relative(realCwd, absDir).split(path.sep).join("/"),
|
|
375
|
+
absDir,
|
|
376
|
+
group: TRANSITIVE_GROUP.name,
|
|
377
|
+
};
|
|
378
|
+
found.set(name, pkg);
|
|
379
|
+
realDirs.set(name, absDir);
|
|
380
|
+
added.push(pkg);
|
|
381
|
+
pending.push(pkg);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return added;
|
|
385
|
+
});
|
|
386
|
+
|
|
315
387
|
export class GitError extends Data.TaggedError("GitError")<{
|
|
316
388
|
readonly args: ReadonlyArray<string>;
|
|
317
389
|
readonly cwd: string;
|
|
@@ -324,10 +396,7 @@ export class GitError extends Data.TaggedError("GitError")<{
|
|
|
324
396
|
}
|
|
325
397
|
|
|
326
398
|
/** Run `git` in `cwd` and return trimmed stdout. */
|
|
327
|
-
export const git = Effect.fn("git")(function* (
|
|
328
|
-
cwd: string,
|
|
329
|
-
args: ReadonlyArray<string>,
|
|
330
|
-
) {
|
|
399
|
+
export const git = Effect.fn("git")(function* (cwd: string, args: ReadonlyArray<string>) {
|
|
331
400
|
const { exitCode, stdout, stderr } = yield* exec(
|
|
332
401
|
ChildProcess.make("git", [...args], { cwd, shell: false }),
|
|
333
402
|
).pipe(Effect.scoped);
|
|
@@ -338,8 +407,7 @@ export const git = Effect.fn("git")(function* (
|
|
|
338
407
|
});
|
|
339
408
|
|
|
340
409
|
/** Absolute path of the repository (or submodule) that owns `cwd`. */
|
|
341
|
-
export const toplevel = (cwd: string) =>
|
|
342
|
-
git(cwd, ["rev-parse", "--show-toplevel"]);
|
|
410
|
+
export const toplevel = (cwd: string) => git(cwd, ["rev-parse", "--show-toplevel"]);
|
|
343
411
|
|
|
344
412
|
/** Full HEAD SHA of the repository that owns `cwd`. */
|
|
345
413
|
const gitHead = (cwd: string) => git(cwd, ["rev-parse", "HEAD"]);
|
|
@@ -349,24 +417,17 @@ export class PackError extends Data.TaggedError("PackError")<{
|
|
|
349
417
|
readonly message: string;
|
|
350
418
|
}> {}
|
|
351
419
|
|
|
352
|
-
const PnpmPackOutput = Schema.fromJsonString(
|
|
353
|
-
Schema.Struct({ filename: Schema.String }),
|
|
354
|
-
);
|
|
420
|
+
const PnpmPackOutput = Schema.fromJsonString(Schema.Struct({ filename: Schema.String }));
|
|
355
421
|
|
|
356
422
|
/**
|
|
357
423
|
* Rewrite every dependency on a package in `links` to that package's
|
|
358
424
|
* tarball URL. Returns the rewritten manifest text and the rewrites made.
|
|
359
425
|
*/
|
|
360
|
-
export const rewriteDependencies = (
|
|
361
|
-
manifestText: string,
|
|
362
|
-
links: ReadonlyMap<string, string>,
|
|
363
|
-
) =>
|
|
426
|
+
export const rewriteDependencies = (manifestText: string, links: ReadonlyMap<string, string>) =>
|
|
364
427
|
Effect.gen(function* () {
|
|
365
428
|
const manifest = yield* Schema.decodeUnknownEffect(
|
|
366
429
|
Schema.fromJsonString(
|
|
367
|
-
Schema.StructWithRest(DependencySections, [
|
|
368
|
-
Schema.Record(Schema.String, Schema.Unknown),
|
|
369
|
-
]),
|
|
430
|
+
Schema.StructWithRest(DependencySections, [Schema.Record(Schema.String, Schema.Unknown)]),
|
|
370
431
|
),
|
|
371
432
|
)(manifestText);
|
|
372
433
|
// Preserve source key order after validation: it contributes to the tarball hash.
|
|
@@ -454,16 +515,12 @@ export const packPackage = Effect.fn("packPackage")(function* (options: {
|
|
|
454
515
|
|
|
455
516
|
let rewrites: PackedTarball["rewrites"] = [];
|
|
456
517
|
const normalized: Array<{ header: TarHeader; data: Uint8Array }> = [];
|
|
457
|
-
for (const entry of entries.sort((a, b) =>
|
|
458
|
-
a.header.name.localeCompare(b.header.name),
|
|
459
|
-
)) {
|
|
518
|
+
for (const entry of entries.sort((a, b) => a.header.name.localeCompare(b.header.name))) {
|
|
460
519
|
let data = entry.data ?? new Uint8Array();
|
|
461
520
|
if (entry.header.name === "package/package.json") {
|
|
462
521
|
const text = yield* Effect.sync(() => new TextDecoder().decode(data));
|
|
463
522
|
const result = yield* rewriteDependencies(text, options.links).pipe(
|
|
464
|
-
Effect.mapError(
|
|
465
|
-
(e) => new PackError({ dir: options.absDir, message: String(e) }),
|
|
466
|
-
),
|
|
523
|
+
Effect.mapError((e) => new PackError({ dir: options.absDir, message: String(e) })),
|
|
467
524
|
);
|
|
468
525
|
rewrites = result.rewrites;
|
|
469
526
|
data = yield* Effect.sync(() => new TextEncoder().encode(result.text));
|
|
@@ -502,10 +559,7 @@ const PullRequestEvent = Schema.fromJsonString(
|
|
|
502
559
|
const pullRequest = Effect.gen(function* () {
|
|
503
560
|
const event = yield* Config.option(Config.String("GITHUB_EVENT_NAME"));
|
|
504
561
|
const eventPath = yield* Config.option(Config.String("GITHUB_EVENT_PATH"));
|
|
505
|
-
if (
|
|
506
|
-
Option.getOrUndefined(event) !== "pull_request" ||
|
|
507
|
-
Option.isNone(eventPath)
|
|
508
|
-
) {
|
|
562
|
+
if (Option.getOrUndefined(event) !== "pull_request" || Option.isNone(eventPath)) {
|
|
509
563
|
return undefined;
|
|
510
564
|
}
|
|
511
565
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -530,8 +584,7 @@ export interface PackOptions {
|
|
|
530
584
|
* replaced by `+`, a character package names cannot contain, so `@a/b-c`
|
|
531
585
|
* and `@a-b/c` get distinct files.
|
|
532
586
|
*/
|
|
533
|
-
export const tarballFile = (name: string) =>
|
|
534
|
-
`${name.replace(/^@/, "").replace("/", "+")}.tgz`;
|
|
587
|
+
export const tarballFile = (name: string) => `${name.replace(/^@/, "").replace("/", "+")}.tgz`;
|
|
535
588
|
|
|
536
589
|
/**
|
|
537
590
|
* Pack every discovered package into `out` with a manifest describing each
|
|
@@ -553,6 +606,13 @@ export const pack = Effect.fn("pack")(function* (options: PackOptions) {
|
|
|
553
606
|
});
|
|
554
607
|
}
|
|
555
608
|
let packages = yield* discover(options.cwd, options.groups);
|
|
609
|
+
const implied = yield* discoverWorkspaceDependencies(options.cwd, root, packages);
|
|
610
|
+
if (implied.length > 0) {
|
|
611
|
+
yield* Console.log(
|
|
612
|
+
`Including ${implied.length} workspace dependenc${implied.length === 1 ? "y" : "ies"} not listed by --group: ${implied.map((pkg) => pkg.name).join(", ")}`,
|
|
613
|
+
);
|
|
614
|
+
packages = [...packages, ...implied];
|
|
615
|
+
}
|
|
556
616
|
|
|
557
617
|
// Dependencies between packed packages are rewritten to the dependency's
|
|
558
618
|
// immutable tarball URL, so a package is packed only after everything it
|
|
@@ -562,17 +622,13 @@ export const pack = Effect.fn("pack")(function* (options: PackOptions) {
|
|
|
562
622
|
for (const pkg of packages) {
|
|
563
623
|
const manifest = yield* fs
|
|
564
624
|
.readFileString(path.join(pkg.absDir, "package.json"))
|
|
565
|
-
.pipe(
|
|
566
|
-
Effect.flatMap(
|
|
567
|
-
Schema.decodeUnknownEffect(Schema.fromJsonString(DependencySections)),
|
|
568
|
-
),
|
|
569
|
-
);
|
|
625
|
+
.pipe(Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(DependencySections))));
|
|
570
626
|
dependencies.set(
|
|
571
627
|
pkg.name,
|
|
572
628
|
new Set(
|
|
573
|
-
DEPENDENCY_SECTIONS.flatMap((section) =>
|
|
574
|
-
|
|
575
|
-
)
|
|
629
|
+
DEPENDENCY_SECTIONS.flatMap((section) => Object.keys(manifest[section] ?? {})).filter(
|
|
630
|
+
(name) => name !== pkg.name && byName.has(name),
|
|
631
|
+
),
|
|
576
632
|
),
|
|
577
633
|
);
|
|
578
634
|
}
|
|
@@ -614,11 +670,7 @@ export const pack = Effect.fn("pack")(function* (options: PackOptions) {
|
|
|
614
670
|
// subdirectory of the workspace: `--out .` would otherwise delete it.
|
|
615
671
|
const outDir = path.resolve(options.cwd, options.out);
|
|
616
672
|
const relative = path.relative(options.cwd, outDir);
|
|
617
|
-
if (
|
|
618
|
-
relative === "" ||
|
|
619
|
-
relative.startsWith("..") ||
|
|
620
|
-
path.isAbsolute(relative)
|
|
621
|
-
) {
|
|
673
|
+
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
622
674
|
return yield* new WorkspaceError({
|
|
623
675
|
message: `--out must be a subdirectory of ${options.cwd}, got ${outDir}`,
|
|
624
676
|
});
|
|
@@ -657,23 +709,23 @@ export const pack = Effect.fn("pack")(function* (options: PackOptions) {
|
|
|
657
709
|
{ concurrency: 4 },
|
|
658
710
|
);
|
|
659
711
|
for (const entry of packedLevel) {
|
|
660
|
-
links.set(
|
|
661
|
-
entry.name,
|
|
662
|
-
tarballUrl(options.registry, entry.name, entry.sha256),
|
|
663
|
-
);
|
|
712
|
+
links.set(entry.name, tarballUrl(options.registry, entry.name, entry.sha256));
|
|
664
713
|
packedByName.set(entry.name, entry);
|
|
665
714
|
}
|
|
666
715
|
}
|
|
667
716
|
// Packing ran in dependency order; the manifest keeps the listed order.
|
|
668
717
|
const entries = packages.map((pkg) => packedByName.get(pkg.name)!);
|
|
669
718
|
|
|
670
|
-
// One entry per distinct group name, in the order the groups were given
|
|
719
|
+
// One entry per distinct group name, in the order the groups were given,
|
|
720
|
+
// then the transitive group when it has members.
|
|
671
721
|
const groups = [
|
|
672
722
|
...new Map(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
723
|
+
[
|
|
724
|
+
...options.groups,
|
|
725
|
+
...(entries.some((entry) => entry.group === TRANSITIVE_GROUP.name)
|
|
726
|
+
? [TRANSITIVE_GROUP]
|
|
727
|
+
: []),
|
|
728
|
+
].map((group) => [group.name, { name: group.name, collapsed: group.collapsed }]),
|
|
677
729
|
).values(),
|
|
678
730
|
];
|
|
679
731
|
const manifest: Manifest = {
|
package/src/cli/publish.ts
CHANGED
|
@@ -3,9 +3,9 @@ import * as Console from "effect/Console";
|
|
|
3
3
|
import * as Data from "effect/Data";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as FileSystem from "effect/FileSystem";
|
|
6
|
+
import * as HttpApiClient from "effect/http-api/HttpApiClient";
|
|
6
7
|
import * as Path from "effect/Path";
|
|
7
8
|
import * as Schema from "effect/Schema";
|
|
8
|
-
import * as HttpApiClient from "effect/http-api/HttpApiClient";
|
|
9
9
|
import { MANIFEST_FILE, ManifestJson, type Manifest } from "../Manifest.ts";
|
|
10
10
|
import { PkgApi, type TarballRef } from "../Protocol.ts";
|
|
11
11
|
|
|
@@ -25,9 +25,7 @@ export interface PublishOptions {
|
|
|
25
25
|
const currentRun = Effect.gen(function* () {
|
|
26
26
|
const repo = yield* Config.String("GITHUB_REPOSITORY");
|
|
27
27
|
const runId = yield* Config.Int("GITHUB_RUN_ID");
|
|
28
|
-
const attempt = yield* Config.Int("GITHUB_RUN_ATTEMPT").pipe(
|
|
29
|
-
Config.withDefault(1),
|
|
30
|
-
);
|
|
28
|
+
const attempt = yield* Config.Int("GITHUB_RUN_ATTEMPT").pipe(Config.withDefault(1));
|
|
31
29
|
return { repo, runId, attempt };
|
|
32
30
|
}).pipe(
|
|
33
31
|
Effect.mapError(
|
|
@@ -39,11 +37,10 @@ const currentRun = Effect.gen(function* () {
|
|
|
39
37
|
);
|
|
40
38
|
|
|
41
39
|
/** Render a registry or transport failure as a `PublishError`. */
|
|
42
|
-
const failed =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
40
|
+
const failed = (what: string) => (e: { readonly _tag: string; readonly message?: string }) =>
|
|
41
|
+
new PublishError({
|
|
42
|
+
message: `${what}: ${e.message ? `${e._tag}: ${e.message}` : e._tag}`,
|
|
43
|
+
});
|
|
47
44
|
|
|
48
45
|
/**
|
|
49
46
|
* Publish a `pkg pack` directory from the current GitHub Actions job. The
|
|
@@ -52,9 +49,7 @@ const failed =
|
|
|
52
49
|
* through GitHub, then either reports the tarballs it lacks, which are
|
|
53
50
|
* uploaded before trying again, or writes the tags.
|
|
54
51
|
*/
|
|
55
|
-
export const publish = Effect.fn("publish")(function* (
|
|
56
|
-
options: PublishOptions,
|
|
57
|
-
) {
|
|
52
|
+
export const publish = Effect.fn("publish")(function* (options: PublishOptions) {
|
|
58
53
|
const fs = yield* FileSystem.FileSystem;
|
|
59
54
|
const path = yield* Path.Path;
|
|
60
55
|
const registry = options.registry.replace(/\/+$/, "");
|
|
@@ -63,8 +58,7 @@ export const publish = Effect.fn("publish")(function* (
|
|
|
63
58
|
|
|
64
59
|
const dir = path.resolve(options.cwd, options.dir);
|
|
65
60
|
const manifestText = yield* fs.readFileString(path.join(dir, MANIFEST_FILE));
|
|
66
|
-
const manifest =
|
|
67
|
-
yield* Schema.decodeUnknownEffect(ManifestJson)(manifestText);
|
|
61
|
+
const manifest = yield* Schema.decodeUnknownEffect(ManifestJson)(manifestText);
|
|
68
62
|
if (manifest.registry !== registry) {
|
|
69
63
|
return yield* new PublishError({
|
|
70
64
|
message: `artifact was packed for ${manifest.registry}, not ${registry}`,
|
|
@@ -96,9 +90,7 @@ export const publish = Effect.fn("publish")(function* (
|
|
|
96
90
|
).pipe(
|
|
97
91
|
Effect.andThen(
|
|
98
92
|
Effect.forEach(
|
|
99
|
-
manifest.packages.filter((pkg) =>
|
|
100
|
-
wanted.has(`${pkg.name}@${pkg.sha256}`),
|
|
101
|
-
),
|
|
93
|
+
manifest.packages.filter((pkg) => wanted.has(`${pkg.name}@${pkg.sha256}`)),
|
|
102
94
|
upload,
|
|
103
95
|
{ concurrency: 4, discard: true },
|
|
104
96
|
),
|
|
@@ -112,9 +104,7 @@ export const publish = Effect.fn("publish")(function* (
|
|
|
112
104
|
const published = yield* attempt.pipe(
|
|
113
105
|
// The first answer is usually the tarballs to upload; publish once more
|
|
114
106
|
// after uploading them.
|
|
115
|
-
Effect.catchTag("MissingTarballs", (e) =>
|
|
116
|
-
Effect.andThen(uploadMissing(e.missing), attempt),
|
|
117
|
-
),
|
|
107
|
+
Effect.catchTag("MissingTarballs", (e) => Effect.andThen(uploadMissing(e.missing), attempt)),
|
|
118
108
|
Effect.catchTag(
|
|
119
109
|
"MissingTarballs",
|
|
120
110
|
(e) =>
|
|
@@ -122,9 +112,7 @@ export const publish = Effect.fn("publish")(function* (
|
|
|
122
112
|
message: `registry still reports missing tarballs after upload: ${e.missing.map((ref) => ref.name).join(", ")}`,
|
|
123
113
|
}),
|
|
124
114
|
),
|
|
125
|
-
Effect.mapError((e) =>
|
|
126
|
-
e._tag === "PublishError" ? e : failed("publish")(e),
|
|
127
|
-
),
|
|
115
|
+
Effect.mapError((e) => (e._tag === "PublishError" ? e : failed("publish")(e))),
|
|
128
116
|
);
|
|
129
117
|
|
|
130
118
|
for (const pkg of published.packages) {
|