@packall/core 0.0.1 → 0.1.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/{Archive.d.ts → archive.d.ts} +5 -5
- package/dist/archive.d.ts.map +1 -0
- package/dist/{Bundle.d.ts → bundle.d.ts} +51 -36
- package/dist/bundle.d.ts.map +1 -0
- package/dist/{DependencyRange.d.ts → dependency-range.d.ts} +2 -2
- package/dist/dependency-range.d.ts.map +1 -0
- package/dist/{Download.d.ts → download.d.ts} +7 -7
- package/dist/download.d.ts.map +1 -0
- package/dist/enums/artifact-kind.d.ts +8 -0
- package/dist/enums/artifact-kind.d.ts.map +1 -0
- package/dist/enums/edge-kind.d.ts +29 -0
- package/dist/enums/edge-kind.d.ts.map +1 -0
- package/dist/enums/input-file-kind.d.ts +12 -0
- package/dist/enums/input-file-kind.d.ts.map +1 -0
- package/dist/enums/layout.d.ts +23 -0
- package/dist/enums/layout.d.ts.map +1 -0
- package/dist/enums/lockfile-format.d.ts +9 -0
- package/dist/enums/lockfile-format.d.ts.map +1 -0
- package/dist/enums/phase.d.ts +11 -0
- package/dist/enums/phase.d.ts.map +1 -0
- package/dist/{Errors.d.ts → errors.d.ts} +49 -7
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +44 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2416 -1180
- package/dist/index.js.map +1 -1
- package/dist/input-file.d.ts +77 -0
- package/dist/input-file.d.ts.map +1 -0
- package/dist/{Integrity.d.ts → integrity.d.ts} +3 -3
- package/dist/integrity.d.ts.map +1 -0
- package/dist/{Layout.d.ts → layout.d.ts} +1 -1
- package/dist/{Layout.d.ts.map → layout.d.ts.map} +1 -1
- package/dist/locked-resolve.d.ts +47 -0
- package/dist/locked-resolve.d.ts.map +1 -0
- package/dist/lockfile/bun.d.ts +3 -0
- package/dist/lockfile/bun.d.ts.map +1 -0
- package/dist/lockfile/detect.d.ts +31 -0
- package/dist/lockfile/detect.d.ts.map +1 -0
- package/dist/lockfile/json.d.ts +23 -0
- package/dist/lockfile/json.d.ts.map +1 -0
- package/dist/lockfile/names.d.ts +16 -0
- package/dist/lockfile/names.d.ts.map +1 -0
- package/dist/lockfile/npm.d.ts +3 -0
- package/dist/lockfile/npm.d.ts.map +1 -0
- package/dist/lockfile/parse.d.ts +23 -0
- package/dist/lockfile/parse.d.ts.map +1 -0
- package/dist/lockfile/pnpm.d.ts +20 -0
- package/dist/lockfile/pnpm.d.ts.map +1 -0
- package/dist/lockfile/tree-builder.d.ts +70 -0
- package/dist/lockfile/tree-builder.d.ts.map +1 -0
- package/dist/lockfile/types.d.ts +70 -0
- package/dist/lockfile/types.d.ts.map +1 -0
- package/dist/{Manifest.d.ts → manifest.d.ts} +7 -15
- package/dist/manifest.d.ts.map +1 -0
- package/dist/{Options.d.ts → options.d.ts} +9 -27
- package/dist/options.d.ts.map +1 -0
- package/dist/{Platform.d.ts → platform.d.ts} +9 -9
- package/dist/platform.d.ts.map +1 -0
- package/dist/{Progress.d.ts → progress.d.ts} +10 -9
- package/dist/progress.d.ts.map +1 -0
- package/dist/{Registry.d.ts → registry.d.ts} +42 -44
- package/dist/registry.d.ts.map +1 -0
- package/dist/{Resolve.d.ts → resolve.d.ts} +25 -26
- package/dist/resolve.d.ts.map +1 -0
- package/dist/schemas/lenient.d.ts +38 -0
- package/dist/schemas/lenient.d.ts.map +1 -0
- package/dist/schemas/package-json.d.ts +44 -0
- package/dist/schemas/package-json.d.ts.map +1 -0
- package/dist/{Spec.d.ts → spec.d.ts} +4 -4
- package/dist/spec.d.ts.map +1 -0
- package/dist/types/value-of.d.ts +9 -0
- package/dist/types/value-of.d.ts.map +1 -0
- package/dist/utils/is-record.d.ts +8 -0
- package/dist/utils/is-record.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/{Archive.ts → archive.ts} +92 -92
- package/src/{Bundle.ts → bundle.ts} +616 -570
- package/src/{DependencyRange.ts → dependency-range.ts} +115 -115
- package/src/{Download.ts → download.ts} +133 -132
- package/src/enums/artifact-kind.ts +9 -0
- package/src/enums/edge-kind.ts +32 -0
- package/src/enums/input-file-kind.ts +13 -0
- package/src/enums/layout.ts +25 -0
- package/src/enums/lockfile-format.ts +10 -0
- package/src/enums/phase.ts +12 -0
- package/src/{Errors.ts → errors.ts} +87 -5
- package/src/index.ts +133 -35
- package/src/{InputFile.ts → input-file.ts} +127 -44
- package/src/{Integrity.ts → integrity.ts} +121 -122
- package/src/locked-resolve.ts +461 -0
- package/src/lockfile/bun.ts +207 -0
- package/src/lockfile/detect.ts +80 -0
- package/src/lockfile/json.ts +132 -0
- package/src/lockfile/names.ts +20 -0
- package/src/lockfile/npm.ts +308 -0
- package/src/lockfile/parse.ts +56 -0
- package/src/lockfile/pnpm.ts +225 -0
- package/src/lockfile/tree-builder.ts +166 -0
- package/src/lockfile/types.ts +74 -0
- package/src/{Manifest.ts → manifest.ts} +133 -133
- package/src/{Options.ts → options.ts} +7 -27
- package/src/{Platform.ts → platform.ts} +23 -23
- package/src/{Progress.ts → progress.ts} +106 -106
- package/src/{Registry.ts → registry.ts} +115 -121
- package/src/{Resolve.ts → resolve.ts} +537 -528
- package/src/schemas/lenient.ts +123 -0
- package/src/schemas/package-json.ts +27 -0
- package/src/{Spec.ts → spec.ts} +11 -19
- package/src/types/value-of.ts +8 -0
- package/src/utils/is-record.ts +8 -0
- package/dist/Archive.d.ts.map +0 -1
- package/dist/Bundle.d.ts.map +0 -1
- package/dist/DependencyRange.d.ts.map +0 -1
- package/dist/Download.d.ts.map +0 -1
- package/dist/Errors.d.ts.map +0 -1
- package/dist/InputFile.d.ts +0 -46
- package/dist/InputFile.d.ts.map +0 -1
- package/dist/Integrity.d.ts.map +0 -1
- package/dist/Manifest.d.ts.map +0 -1
- package/dist/Options.d.ts.map +0 -1
- package/dist/Platform.d.ts.map +0 -1
- package/dist/Progress.d.ts.map +0 -1
- package/dist/Registry.d.ts.map +0 -1
- package/dist/Resolve.d.ts.map +0 -1
- package/dist/Spec.d.ts.map +0 -1
- /package/src/{Layout.ts → layout.ts} +0 -0
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Turning a staged directory tree into a gzipped tarball.
|
|
3
|
-
*
|
|
4
|
-
* Uses `node-tar`, the same library npm itself packs with. Writing a USTAR
|
|
5
|
-
* encoder by hand would be a fun afternoon and a bad idea: scoped package
|
|
6
|
-
* paths routinely exceed the 100-byte name field, so correctness depends on
|
|
7
|
-
* prefix-splitting and PAX headers that `tar` already gets right.
|
|
8
|
-
*/
|
|
9
|
-
import * as Effect from "effect/Effect"
|
|
10
|
-
import * as FileSystem from "effect/FileSystem"
|
|
11
|
-
import type { PlatformError } from "effect/PlatformError"
|
|
12
|
-
import { create } from "tar"
|
|
13
|
-
import { ArchiveError } from "./
|
|
14
|
-
import * as Progress from "./
|
|
15
|
-
|
|
16
|
-
/** A finished archive. */
|
|
17
|
-
export
|
|
18
|
-
readonly path: string
|
|
19
|
-
readonly bytes: number
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Packs `entries` (paths relative to `cwd`) into a gzipped tar at `outPath`.
|
|
24
|
-
*
|
|
25
|
-
* `portable` normalises uid/gid/mtime so the same inputs produce byte-identical
|
|
26
|
-
* output — which matters when a security team wants to diff two bundles or
|
|
27
|
-
* re-derive one from a manifest.
|
|
28
|
-
*/
|
|
29
|
-
export const createArchive = (options: {
|
|
30
|
-
readonly cwd: string
|
|
31
|
-
readonly entries: ReadonlyArray<string>
|
|
32
|
-
readonly outPath: string
|
|
33
|
-
readonly gzipLevel?: number | undefined
|
|
34
|
-
}): Effect.Effect<ArchiveResult, ArchiveError | PlatformError, FileSystem.FileSystem | Progress.Progress> =>
|
|
35
|
-
Effect.gen(function*() {
|
|
36
|
-
const fs = yield* FileSystem.FileSystem
|
|
37
|
-
|
|
38
|
-
yield* Progress.emit({
|
|
39
|
-
_tag: "ArchiveStarted",
|
|
40
|
-
path: options.outPath,
|
|
41
|
-
entryCount: options.entries.length
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
yield* Effect.tryPromise({
|
|
45
|
-
try: () =>
|
|
46
|
-
create(
|
|
47
|
-
{
|
|
48
|
-
gzip: options.gzipLevel === undefined ? true : { level: options.gzipLevel },
|
|
49
|
-
file: options.outPath,
|
|
50
|
-
cwd: options.cwd,
|
|
51
|
-
portable: true,
|
|
52
|
-
// Undo the `./` added below, so recorded entry names stay exactly
|
|
53
|
-
// the registry paths the manifest lists.
|
|
54
|
-
onWriteEntry: (entry) => {
|
|
55
|
-
entry.path = entry.path.replace(/^\.\//, "")
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
// Sorted so archive order is stable across runs and platforms.
|
|
59
|
-
|
|
60
|
-
),
|
|
61
|
-
catch: (cause) => new ArchiveError(options.outPath, describe(cause), { cause })
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
const info = yield* fs.stat(options.outPath)
|
|
65
|
-
const bytes = Number(info.size)
|
|
66
|
-
|
|
67
|
-
yield* Progress.emit({ _tag: "ArchiveCompleted", path: options.outPath, bytes })
|
|
68
|
-
|
|
69
|
-
return { path: options.outPath, bytes }
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Guards every entry against tar's `@` convention.
|
|
74
|
-
*
|
|
75
|
-
* In a tar file list, a leading `@` means "splice in the entries of this other
|
|
76
|
-
* archive" — a GNU convention `node-tar` implements by stripping the `@` and
|
|
77
|
-
* looking for what is left. Every scoped package is a top-level entry starting
|
|
78
|
-
* with `@`, so this hit the bundler in both possible ways:
|
|
79
|
-
*
|
|
80
|
-
* - `@oxc-project` became `oxc-project`, which does not exist, and the run died
|
|
81
|
-
* with an ENOENT naming a path that appears nowhere in the staging tree.
|
|
82
|
-
* - `@esbuild` became `esbuild`, which *does* exist — the unscoped package of
|
|
83
|
-
* the same name sitting right next to it. No error, and every scoped tarball
|
|
84
|
-
* silently missing from a bundle that reported success. That is the dangerous
|
|
85
|
-
* one: you would not find out until the install failed behind the firewall.
|
|
86
|
-
*
|
|
87
|
-
* `./@scope` is not subject to the convention and resolves identically.
|
|
88
|
-
*/
|
|
89
|
-
const dotSlash = (entry: string): string => (entry.startsWith("./") ? entry : `./${entry}`)
|
|
90
|
-
|
|
91
|
-
const describe = (cause: unknown): string =>
|
|
92
|
-
cause instanceof Error ? cause.message : String(cause)
|
|
1
|
+
/**
|
|
2
|
+
* Turning a staged directory tree into a gzipped tarball.
|
|
3
|
+
*
|
|
4
|
+
* Uses `node-tar`, the same library npm itself packs with. Writing a USTAR
|
|
5
|
+
* encoder by hand would be a fun afternoon and a bad idea: scoped package
|
|
6
|
+
* paths routinely exceed the 100-byte name field, so correctness depends on
|
|
7
|
+
* prefix-splitting and PAX headers that `tar` already gets right.
|
|
8
|
+
*/
|
|
9
|
+
import * as Effect from "effect/Effect"
|
|
10
|
+
import * as FileSystem from "effect/FileSystem"
|
|
11
|
+
import type { PlatformError } from "effect/PlatformError"
|
|
12
|
+
import { create } from "tar"
|
|
13
|
+
import { ArchiveError } from "./errors.js"
|
|
14
|
+
import * as Progress from "./progress.js"
|
|
15
|
+
|
|
16
|
+
/** A finished archive. */
|
|
17
|
+
export type ArchiveResult = {
|
|
18
|
+
readonly path: string
|
|
19
|
+
readonly bytes: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Packs `entries` (paths relative to `cwd`) into a gzipped tar at `outPath`.
|
|
24
|
+
*
|
|
25
|
+
* `portable` normalises uid/gid/mtime so the same inputs produce byte-identical
|
|
26
|
+
* output — which matters when a security team wants to diff two bundles or
|
|
27
|
+
* re-derive one from a manifest.
|
|
28
|
+
*/
|
|
29
|
+
export const createArchive = (options: {
|
|
30
|
+
readonly cwd: string
|
|
31
|
+
readonly entries: ReadonlyArray<string>
|
|
32
|
+
readonly outPath: string
|
|
33
|
+
readonly gzipLevel?: number | undefined
|
|
34
|
+
}): Effect.Effect<ArchiveResult, ArchiveError | PlatformError, FileSystem.FileSystem | Progress.Progress> =>
|
|
35
|
+
Effect.gen(function*() {
|
|
36
|
+
const fs = yield* FileSystem.FileSystem
|
|
37
|
+
|
|
38
|
+
yield* Progress.emit({
|
|
39
|
+
_tag: "ArchiveStarted",
|
|
40
|
+
path: options.outPath,
|
|
41
|
+
entryCount: options.entries.length
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
yield* Effect.tryPromise({
|
|
45
|
+
try: () =>
|
|
46
|
+
create(
|
|
47
|
+
{
|
|
48
|
+
gzip: options.gzipLevel === undefined ? true : { level: options.gzipLevel },
|
|
49
|
+
file: options.outPath,
|
|
50
|
+
cwd: options.cwd,
|
|
51
|
+
portable: true,
|
|
52
|
+
// Undo the `./` added below, so recorded entry names stay exactly
|
|
53
|
+
// the registry paths the manifest lists.
|
|
54
|
+
onWriteEntry: (entry) => {
|
|
55
|
+
entry.path = entry.path.replace(/^\.\//, "")
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
// Sorted so archive order is stable across runs and platforms.
|
|
59
|
+
options.entries.toSorted().map(dotSlash)
|
|
60
|
+
),
|
|
61
|
+
catch: (cause) => new ArchiveError(options.outPath, describe(cause), { cause })
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const info = yield* fs.stat(options.outPath)
|
|
65
|
+
const bytes = Number(info.size)
|
|
66
|
+
|
|
67
|
+
yield* Progress.emit({ _tag: "ArchiveCompleted", path: options.outPath, bytes })
|
|
68
|
+
|
|
69
|
+
return { path: options.outPath, bytes }
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Guards every entry against tar's `@` convention.
|
|
74
|
+
*
|
|
75
|
+
* In a tar file list, a leading `@` means "splice in the entries of this other
|
|
76
|
+
* archive" — a GNU convention `node-tar` implements by stripping the `@` and
|
|
77
|
+
* looking for what is left. Every scoped package is a top-level entry starting
|
|
78
|
+
* with `@`, so this hit the bundler in both possible ways:
|
|
79
|
+
*
|
|
80
|
+
* - `@oxc-project` became `oxc-project`, which does not exist, and the run died
|
|
81
|
+
* with an ENOENT naming a path that appears nowhere in the staging tree.
|
|
82
|
+
* - `@esbuild` became `esbuild`, which *does* exist — the unscoped package of
|
|
83
|
+
* the same name sitting right next to it. No error, and every scoped tarball
|
|
84
|
+
* silently missing from a bundle that reported success. That is the dangerous
|
|
85
|
+
* one: you would not find out until the install failed behind the firewall.
|
|
86
|
+
*
|
|
87
|
+
* `./@scope` is not subject to the convention and resolves identically.
|
|
88
|
+
*/
|
|
89
|
+
const dotSlash = (entry: string): string => (entry.startsWith("./") ? entry : `./${entry}`)
|
|
90
|
+
|
|
91
|
+
const describe = (cause: unknown): string =>
|
|
92
|
+
cause instanceof Error ? cause.message : String(cause)
|