Skip to content

Commit 1c0cfbe

Browse files
committed
augment parseNameAndVersion
1 parent 3d407bd commit 1c0cfbe

File tree

2 files changed

+156
-21
lines changed

2 files changed

+156
-21
lines changed

src/PackageDetails.test.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
getPackageDetailsFromPatchFilename,
33
getPatchDetailsFromCliString,
4+
parseNameAndVersion,
45
} from "./PackageDetails"
56

67
describe("getPackageDetailsFromPatchFilename", () => {
@@ -280,3 +281,93 @@ Object {
280281
)
281282
})
282283
})
284+
285+
describe("parseNameAndVersion", () => {
286+
it("works for good-looking names", () => {
287+
expect(parseNameAndVersion("lodash+2.3.4")).toMatchInlineSnapshot(`
288+
Object {
289+
"packageName": "lodash",
290+
"version": "2.3.4",
291+
}
292+
`)
293+
expect(parseNameAndVersion("patch-package+2.0.0-alpha.3"))
294+
.toMatchInlineSnapshot(`
295+
Object {
296+
"packageName": "patch-package",
297+
"version": "2.0.0-alpha.3",
298+
}
299+
`)
300+
})
301+
it("works for scoped package names", () => {
302+
expect(parseNameAndVersion("@react-spring+rafz+2.0.0-alpha.3"))
303+
.toMatchInlineSnapshot(`
304+
Object {
305+
"packageName": "@react-spring/rafz",
306+
"version": "2.0.0-alpha.3",
307+
}
308+
`)
309+
expect(parseNameAndVersion("@microsoft+api-extractor+2.2.3"))
310+
.toMatchInlineSnapshot(`
311+
Object {
312+
"packageName": "@microsoft/api-extractor",
313+
"version": "2.2.3",
314+
}
315+
`)
316+
})
317+
it("works for ordered patches", () => {
318+
expect(parseNameAndVersion("patch-package+2.0.0+01"))
319+
.toMatchInlineSnapshot(`
320+
Object {
321+
"packageName": "patch-package",
322+
"sequenceNumber": 1,
323+
"version": "2.0.0",
324+
}
325+
`)
326+
expect(parseNameAndVersion("@react-spring+rafz+2.0.0-alpha.3+23"))
327+
.toMatchInlineSnapshot(`
328+
Object {
329+
"packageName": "@react-spring/rafz",
330+
"sequenceNumber": 23,
331+
"version": "2.0.0-alpha.3",
332+
}
333+
`)
334+
expect(parseNameAndVersion("@microsoft+api-extractor+2.0.0+001"))
335+
.toMatchInlineSnapshot(`
336+
Object {
337+
"packageName": "@microsoft/api-extractor",
338+
"sequenceNumber": 1,
339+
"version": "2.0.0",
340+
}
341+
`)
342+
})
343+
344+
it("works for ordered patches with names", () => {
345+
expect(parseNameAndVersion("patch-package+2.0.0+021+FixImportantThing"))
346+
.toMatchInlineSnapshot(`
347+
Object {
348+
"packageName": "patch-package",
349+
"sequenceName": "FixImportantThing",
350+
"sequenceNumber": 21,
351+
"version": "2.0.0",
352+
}
353+
`)
354+
expect(parseNameAndVersion("@react-spring+rafz+2.0.0-alpha.3+000023+Foo"))
355+
.toMatchInlineSnapshot(`
356+
Object {
357+
"packageName": "@react-spring/rafz",
358+
"sequenceName": "Foo",
359+
"sequenceNumber": 23,
360+
"version": "2.0.0-alpha.3",
361+
}
362+
`)
363+
expect(parseNameAndVersion("@microsoft+api-extractor+2.0.0+001+Bar"))
364+
.toMatchInlineSnapshot(`
365+
Object {
366+
"packageName": "@microsoft/api-extractor",
367+
"sequenceName": "Bar",
368+
"sequenceNumber": 1,
369+
"version": "2.0.0",
370+
}
371+
`)
372+
})
373+
})

src/PackageDetails.ts

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,72 @@ export interface PatchedPackageDetails extends PackageDetails {
1515
isDevOnly: boolean
1616
}
1717

18-
function parseNameAndVersion(
19-
s: string,
18+
export function parseNameAndVersion(
19+
str: string,
2020
): {
21-
name: string
21+
packageName: string
2222
version?: string
23+
sequenceName?: string
24+
sequenceNumber?: number
2325
} | null {
24-
const parts = s.split("+")
25-
switch (parts.length) {
26+
const parts = str
27+
.split("+")
28+
.map((s) => s.trim())
29+
.filter(Boolean)
30+
if (parts.length === 0) {
31+
return null
32+
}
33+
if (parts.length === 1) {
34+
return { packageName: str }
35+
}
36+
const versionIndex = parts.findIndex((part) =>
37+
part.match(/^\d+\.\d+\.\d+.*$/),
38+
)
39+
if (versionIndex === -1) {
40+
const [scope, name] = parts
41+
return { packageName: `${scope}/${name}` }
42+
}
43+
const nameParts = parts.slice(0, versionIndex)
44+
let packageName
45+
switch (nameParts.length) {
46+
case 0:
47+
return null
48+
case 1:
49+
packageName = nameParts[0]
50+
break
51+
case 2:
52+
const [scope, name] = nameParts
53+
packageName = `${scope}/${name}`
54+
break
55+
default:
56+
return null
57+
}
58+
59+
const version = parts[versionIndex]
60+
const sequenceParts = parts.slice(versionIndex + 1)
61+
if (sequenceParts.length === 0) {
62+
return { packageName, version }
63+
}
64+
65+
// expect sequenceParts[0] to be a number, strip leading 0s
66+
const sequenceNumber = parseInt(sequenceParts[0].replace(/^0+/, ""), 10)
67+
if (isNaN(sequenceNumber)) {
68+
return null
69+
}
70+
switch (sequenceParts.length) {
2671
case 1: {
27-
return { name: parts[0] }
72+
return { packageName, version, sequenceNumber }
2873
}
2974
case 2: {
30-
const [nameOrScope, versionOrName] = parts
31-
if (versionOrName.match(/^\d+/)) {
32-
return {
33-
name: nameOrScope,
34-
version: versionOrName,
35-
}
75+
return {
76+
packageName,
77+
version,
78+
sequenceName: sequenceParts[1],
79+
sequenceNumber,
3680
}
37-
return { name: `${nameOrScope}/${versionOrName}` }
3881
}
39-
case 3: {
40-
const [scope, name, version] = parts
41-
return { name: `${scope}/${name}`, version }
82+
default: {
83+
return null
4284
}
4385
}
4486
return null
@@ -85,17 +127,19 @@ export function getPackageDetailsFromPatchFilename(
85127
}
86128

87129
return {
88-
name: lastPart.name,
130+
name: lastPart.packageName,
89131
version: lastPart.version,
90132
path: join(
91133
"node_modules",
92-
parts.map(({ name }) => name).join("/node_modules/"),
134+
parts.map(({ packageName: name }) => name).join("/node_modules/"),
93135
),
94136
patchFilename,
95-
pathSpecifier: parts.map(({ name }) => name).join("/"),
96-
humanReadablePathSpecifier: parts.map(({ name }) => name).join(" => "),
137+
pathSpecifier: parts.map(({ packageName: name }) => name).join("/"),
138+
humanReadablePathSpecifier: parts
139+
.map(({ packageName: name }) => name)
140+
.join(" => "),
97141
isNested: parts.length > 1,
98-
packageNames: parts.map(({ name }) => name),
142+
packageNames: parts.map(({ packageName: name }) => name),
99143
isDevOnly: patchFilename.endsWith(".dev.patch"),
100144
}
101145
}

0 commit comments

Comments
 (0)