@packall/core 0.0.1 → 0.2.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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/archive-6sqTn1C4.js +274 -0
- package/dist/archive-6sqTn1C4.js.map +1 -0
- package/dist/archive.d.ts +64 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/{Bundle.d.ts → bundle.d.ts} +56 -38
- 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} +9 -8
- 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 +46 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2121 -1060
- 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 +80 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/layout.d.ts +87 -0
- package/dist/layout.d.ts.map +1 -0
- 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/node/archiver.d.ts +5 -0
- package/dist/node/archiver.d.ts.map +1 -0
- package/dist/node/index.d.ts +13 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +55 -0
- package/dist/node/index.js.map +1 -0
- package/dist/{Options.d.ts → options.d.ts} +12 -30
- package/dist/options.d.ts.map +1 -0
- package/dist/{Platform.d.ts → platform.d.ts} +14 -19
- 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 +13 -11
- package/src/archive.ts +95 -0
- package/src/bundle.ts +736 -0
- package/src/dependency-range.ts +121 -0
- package/src/download.ts +155 -0
- 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 +300 -0
- package/src/index.ts +146 -35
- package/src/input-file.ts +324 -0
- package/src/integrity.ts +165 -0
- package/src/layout.ts +137 -0
- package/src/locked-resolve.ts +471 -0
- package/src/lockfile/bun.ts +214 -0
- package/src/lockfile/detect.ts +80 -0
- package/src/lockfile/json.ts +131 -0
- package/src/lockfile/names.ts +20 -0
- package/src/lockfile/npm.ts +328 -0
- package/src/lockfile/parse.ts +56 -0
- package/src/lockfile/pnpm.ts +230 -0
- package/src/lockfile/tree-builder.ts +166 -0
- package/src/lockfile/types.ts +74 -0
- package/src/manifest.ts +129 -0
- package/src/node/archiver.ts +85 -0
- package/src/node/index.ts +13 -0
- package/src/options.ts +103 -0
- package/src/platform.ts +178 -0
- package/src/progress.ts +105 -0
- package/src/registry.ts +116 -0
- package/src/resolve.ts +560 -0
- package/src/schemas/lenient.ts +130 -0
- package/src/schemas/package-json.ts +28 -0
- package/src/spec.ts +182 -0
- package/src/types/value-of.ts +8 -0
- package/src/utils/is-record.ts +8 -0
- package/dist/Archive.d.ts +0 -32
- 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 +0 -48
- package/dist/Integrity.d.ts.map +0 -1
- package/dist/Layout.d.ts +0 -53
- package/dist/Layout.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/Archive.ts +0 -92
- package/src/Bundle.ts +0 -570
- package/src/DependencyRange.ts +0 -115
- package/src/Download.ts +0 -132
- package/src/Errors.ts +0 -216
- package/src/InputFile.ts +0 -229
- package/src/Integrity.ts +0 -122
- package/src/Layout.ts +0 -103
- package/src/Manifest.ts +0 -133
- package/src/Options.ts +0 -123
- package/src/Platform.ts +0 -182
- package/src/Progress.ts +0 -106
- package/src/Registry.ts +0 -121
- package/src/Resolve.ts +0 -528
- package/src/Spec.ts +0 -186
package/src/Spec.ts
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parsing and validation of package specs — the `lodash`, `react@18.2.0`,
|
|
3
|
-
* `@babel/core@^7`, `typescript@next` strings a user types.
|
|
4
|
-
*
|
|
5
|
-
* Deliberately dependency-light and synchronous: parsing must never touch the
|
|
6
|
-
* network, so `--dry-run` and argument validation stay instant.
|
|
7
|
-
*/
|
|
8
|
-
import semver from "semver"
|
|
9
|
-
import { InvalidSpecError } from "./Errors.js"
|
|
10
|
-
|
|
11
|
-
/** How a spec narrows down which version(s) of a package we want. */
|
|
12
|
-
export type Selector =
|
|
13
|
-
/** An exact, fully-qualified version: `react@18.2.0`. */
|
|
14
|
-
| { readonly _tag: "Exact"; readonly version: string }
|
|
15
|
-
/** A semver range: `react@^18`, `react@>=17 <19`, `react@*`. */
|
|
16
|
-
| { readonly _tag: "Range"; readonly range: string }
|
|
17
|
-
/** A dist-tag: `react@latest`, `typescript@next`. */
|
|
18
|
-
| { readonly _tag: "Tag"; readonly tag: string }
|
|
19
|
-
|
|
20
|
-
/** A parsed, validated package spec. */
|
|
21
|
-
export interface PackageSpec {
|
|
22
|
-
/** The npm package name, including scope. */
|
|
23
|
-
readonly name: string
|
|
24
|
-
/** What the user asked for after the `@`. */
|
|
25
|
-
readonly selector: Selector
|
|
26
|
-
/** The original string, kept verbatim for error messages and the manifest. */
|
|
27
|
-
readonly raw: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Renders a spec back into the canonical `name@selector` form. */
|
|
31
|
-
export const formatSpec = (spec: PackageSpec): string => {
|
|
32
|
-
switch (spec.selector._tag) {
|
|
33
|
-
case "Exact":
|
|
34
|
-
return `${spec.name}@${spec.selector.version}`
|
|
35
|
-
case "Range":
|
|
36
|
-
return `${spec.name}@${spec.selector.range}`
|
|
37
|
-
case "Tag":
|
|
38
|
-
return `${spec.name}@${spec.selector.tag}`
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Human-readable form of just the selector part. */
|
|
43
|
-
export const formatSelector = (selector: Selector): string => {
|
|
44
|
-
switch (selector._tag) {
|
|
45
|
-
case "Exact":
|
|
46
|
-
return selector.version
|
|
47
|
-
case "Range":
|
|
48
|
-
return selector.range
|
|
49
|
-
case "Tag":
|
|
50
|
-
return selector.tag
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const MAX_NAME_LENGTH = 214
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validates an npm package name against the rules the registry actually
|
|
58
|
-
* enforces. Returns `null` when valid, or the reason it is not.
|
|
59
|
-
*/
|
|
60
|
-
export const validatePackageName = (name: string): string | null => {
|
|
61
|
-
if (name.length === 0) return "name is empty"
|
|
62
|
-
if (name.length > MAX_NAME_LENGTH) {
|
|
63
|
-
return `name is longer than ${MAX_NAME_LENGTH} characters`
|
|
64
|
-
}
|
|
65
|
-
if (name.trim() !== name) return "name has leading or trailing whitespace"
|
|
66
|
-
if (name.startsWith(".")) return "name cannot start with a period"
|
|
67
|
-
if (name.startsWith("_")) return "name cannot start with an underscore"
|
|
68
|
-
if (name !== name.toLowerCase()) return "name cannot contain capital letters"
|
|
69
|
-
|
|
70
|
-
if (name.startsWith("@")) {
|
|
71
|
-
const slash = name.indexOf("/")
|
|
72
|
-
if (slash === -1) return "scoped name is missing the '/name' part"
|
|
73
|
-
const scope = name.slice(1, slash)
|
|
74
|
-
const rest = name.slice(slash + 1)
|
|
75
|
-
if (scope.length === 0) return "scope is empty"
|
|
76
|
-
if (rest.length === 0) return "name after the scope is empty"
|
|
77
|
-
if (rest.includes("/")) return "name contains more than one '/'"
|
|
78
|
-
if (!SEGMENT_RE.test(scope)) return `scope "${scope}" contains illegal characters`
|
|
79
|
-
if (!SEGMENT_RE.test(rest)) return `name "${rest}" contains illegal characters`
|
|
80
|
-
return null
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (name.includes("/")) return "unscoped name cannot contain '/'"
|
|
84
|
-
if (!SEGMENT_RE.test(name)) return "name contains illegal characters"
|
|
85
|
-
return null
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// The registry accepts URL-safe characters plus `-`, `.` and `_`.
|
|
89
|
-
const SEGMENT_RE = /^[a-z0-9\-._~]+$/
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Parses a single spec string.
|
|
93
|
-
*
|
|
94
|
-
* Splitting on `@` is the fiddly part: a scoped name *starts* with `@`, so we
|
|
95
|
-
* look for the last `@` that is not at index 0.
|
|
96
|
-
*/
|
|
97
|
-
export const parseSpec = (raw: string): PackageSpec => {
|
|
98
|
-
const input = raw.trim()
|
|
99
|
-
if (input.length === 0) {
|
|
100
|
-
throw new InvalidSpecError(raw, "spec is empty")
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const at = input.lastIndexOf("@")
|
|
104
|
-
const hasSelector = at > 0
|
|
105
|
-
const name = hasSelector ? input.slice(0, at) : input
|
|
106
|
-
const selectorText = hasSelector ? input.slice(at + 1) : ""
|
|
107
|
-
|
|
108
|
-
const nameProblem = validatePackageName(name)
|
|
109
|
-
if (nameProblem !== null) {
|
|
110
|
-
throw new InvalidSpecError(raw, nameProblem)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!hasSelector || selectorText.length === 0) {
|
|
114
|
-
return { name, selector: { _tag: "Tag", tag: "latest" }, raw: input }
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return { name, selector: parseSelector(raw, selectorText), raw: input }
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Classifies the part after the `@` as an exact version, a range, or a dist-tag. */
|
|
121
|
-
export const parseSelector = (raw: string, text: string): Selector => {
|
|
122
|
-
// `semver.valid` only accepts a complete `x.y.z`, which is exactly the
|
|
123
|
-
// "pin me to this one version" case.
|
|
124
|
-
const exact = semver.valid(text, { loose: false })
|
|
125
|
-
if (exact !== null) {
|
|
126
|
-
return { _tag: "Exact", version: exact }
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (semver.validRange(text, { loose: false }) !== null) {
|
|
130
|
-
return { _tag: "Range", range: text }
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Anything left has to be a dist-tag. Tags may not look like versions and
|
|
134
|
-
// may not contain characters that would break a registry URL.
|
|
135
|
-
if (!DIST_TAG_RE.test(text)) {
|
|
136
|
-
throw new InvalidSpecError(
|
|
137
|
-
raw,
|
|
138
|
-
`"${text}" is not a valid version, semver range, or dist-tag`
|
|
139
|
-
)
|
|
140
|
-
}
|
|
141
|
-
return { _tag: "Tag", tag: text }
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const DIST_TAG_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Parses many specs, collecting *every* failure rather than stopping at the
|
|
148
|
-
* first. Somebody bundling forty packages should be told about all four typos
|
|
149
|
-
* in one go, not made to re-run four times.
|
|
150
|
-
*/
|
|
151
|
-
export const parseSpecs = (
|
|
152
|
-
inputs: ReadonlyArray<string>
|
|
153
|
-
): { readonly specs: ReadonlyArray<PackageSpec>; readonly errors: ReadonlyArray<InvalidSpecError> } => {
|
|
154
|
-
const specs: Array<PackageSpec> = []
|
|
155
|
-
const errors: Array<InvalidSpecError> = []
|
|
156
|
-
for (const input of inputs) {
|
|
157
|
-
try {
|
|
158
|
-
specs.push(parseSpec(input))
|
|
159
|
-
} catch (error) {
|
|
160
|
-
if (error instanceof InvalidSpecError) {
|
|
161
|
-
errors.push(error)
|
|
162
|
-
} else {
|
|
163
|
-
throw error
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return { specs, errors }
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Collapses duplicate specs, keeping the first occurrence.
|
|
172
|
-
*
|
|
173
|
-
* `npmb react react@latest` is a plausible thing to type and should not
|
|
174
|
-
* download React twice.
|
|
175
|
-
*/
|
|
176
|
-
export const dedupeSpecs = (specs: ReadonlyArray<PackageSpec>): ReadonlyArray<PackageSpec> => {
|
|
177
|
-
const seen = new Set<string>()
|
|
178
|
-
const out: Array<PackageSpec> = []
|
|
179
|
-
for (const spec of specs) {
|
|
180
|
-
const key = formatSpec(spec)
|
|
181
|
-
if (seen.has(key)) continue
|
|
182
|
-
seen.add(key)
|
|
183
|
-
out.push(spec)
|
|
184
|
-
}
|
|
185
|
-
return out
|
|
186
|
-
}
|