Skip to content

Commit 3736a13

Browse files
Add support for pnpm (#219)
1 parent 4834ff7 commit 3736a13

23 files changed

+199
-24
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ yarn install
4343
scip-typescript index --yarn-workspaces
4444
```
4545

46+
### Index a TypeScript project using pnpm workspaces
47+
48+
Navigate to the project root, containing `package.json`.
49+
50+
```sh
51+
pnpm install
52+
53+
scip-typescript index --pnpm-workspaces
54+
```
55+
4656
### Indexing in CI
4757

4858
Add the following run steps to your CI pipeline:

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"build": "node ./node_modules/typescript/bin/tsc -b .",
1414
"test": "uvu -r ts-node/register --ignore dist",
1515
"update-snapshots": "uvu -r ts-node/register --ignore dist --update-snapshots",
16-
"prepare": "cd snapshots && yarn && cd input/multi-project && yarn"
16+
"prepare": "cd snapshots && yarn && cd input/multi-project && yarn && cd ../pnpm-workspaces && pnpm install"
1717
},
1818
"repository": {
1919
"type": "git",
@@ -54,6 +54,7 @@
5454
"eslint": "^7.32.0",
5555
"eslint-plugin-unicorn": "^21.0.0",
5656
"eslint-plugin-unused-imports": "^2.0.0",
57+
"pnpm": "7.20.0",
5758
"prettier": "2.8.1",
5859
"ts-node": "^10.7.0",
5960
"typescript-eslint": "0.0.1-alpha.0",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "pnpm-workspaces",
3+
"version": "1.0.0",
4+
"description": "Example TS/JS project",
5+
"main": "src/main.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"private": true,
12+
"packageManager": "[email protected]"
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "@example/a",
3+
"version": "1.0.0",
4+
"description": "Example TS/JS project",
5+
"main": "src/a.ts",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC"
11+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function a(): string {
2+
return ''
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"rootDir": ".",
5+
"baseUrl": ".",
6+
"outDir": "dist"
7+
},
8+
"include": ["src/*"]
9+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "@example/b",
3+
"version": "1.0.0",
4+
"description": "Example TS/JS project",
5+
"main": "src/b.ts",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"dependencies": {
12+
"@example/a": "1.0.0"
13+
}
14+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { a } from '@example/a'
2+
3+
export function b() {
4+
return a()
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"rootDir": ".",
5+
"baseUrl": "./src",
6+
"sourceRoot": "src",
7+
"outDir": "dist"
8+
},
9+
"include": ["src/*"],
10+
"references": [{ "path": "../a" }]
11+
}

snapshots/input/pnpm-workspaces/packages/b/tsconfig.tsbuildinfo

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

snapshots/input/pnpm-workspaces/pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
packages:
2+
- 'packages/*'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"extends": "@sourcegraph/tsconfig",
3+
"compilerOptions": {
4+
"target": "es2020",
5+
"module": "commonjs",
6+
"allowJs": false,
7+
"moduleResolution": "node",
8+
"esModuleInterop": true,
9+
"lib": ["esnext", "dom", "dom.iterable"],
10+
"sourceMap": true,
11+
"declaration": true,
12+
"declarationMap": true,
13+
"skipLibCheck": true,
14+
"skipDefaultLibCheck": true,
15+
"noErrorTruncation": true,
16+
"importHelpers": true,
17+
"resolveJsonModule": true,
18+
"composite": true,
19+
"outDir": "out",
20+
"rootDir": "."
21+
},
22+
"include": [],
23+
"exclude": ["out", "node_modules", "dist"]
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function a(): string {
2+
// definition @example/a 1.0.0 src/`a.ts`/
3+
//documentation ```ts\nmodule "a.ts"\n```
4+
// ^ definition @example/a 1.0.0 src/`a.ts`/a().
5+
// documentation ```ts\nfunction a(): string\n```
6+
return ''
7+
}
8+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { a } from '@example/a'
2+
// definition @example/b 1.0.0 src/`b.ts`/
3+
//documentation ```ts\nmodule "b.ts"\n```
4+
// ^ reference @example/a 1.0.0 src/`a.ts`/a().
5+
// ^^^^^^^^^^^^ reference @example/a 1.0.0 src/`a.ts`/
6+
7+
export function b() {
8+
// ^ definition @example/b 1.0.0 src/`b.ts`/b().
9+
// documentation ```ts\nfunction b(): string\n```
10+
return a()
11+
// ^ reference @example/a 1.0.0 src/`a.ts`/a().
12+
}
13+

snapshots/output/react/src/LoaderInput.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react'
22
// definition react-example 1.0.0 src/`LoaderInput.tsx`/
33
//documentation ```ts\nmodule "LoaderInput.tsx"\n```
4-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
5-
// ^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/
4+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
5+
// ^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/
66

77
/** Takes loading prop, input component as child */
88
interface Props {
@@ -15,15 +15,15 @@
1515
children: React.ReactNode
1616
// ^^^^^^^^ definition react-example 1.0.0 src/`LoaderInput.tsx`/Props#children.
1717
// documentation ```ts\n(property) children: ReactNode\n```
18-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
19-
// ^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/ReactNode#
18+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
19+
// ^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/ReactNode#
2020
}
2121

2222
export const LoaderInput: React.FunctionComponent<Props> = ({
2323
// ^^^^^^^^^^^ definition react-example 1.0.0 src/`LoaderInput.tsx`/LoaderInput.
2424
// documentation ```ts\nvar LoaderInput: FunctionComponent<Props>\n```
25-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
26-
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/FunctionComponent#
25+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
26+
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/FunctionComponent#
2727
// ^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#
2828
loading,
2929
// ^^^^^^^ definition local 3
@@ -36,23 +36,23 @@
3636
// ^^^^^^^^ reference local 7
3737
}) => (
3838
<div className="hello">
39-
// ^^^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#div.
40-
// ^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/HTMLAttributes#className.
39+
// ^^^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#div.
40+
// ^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/HTMLAttributes#className.
4141
{children}
4242
// ^^^^^^^^ reference local 4
4343
{loading && <p>spinner</p>}
4444
// ^^^^^^^ reference local 3
45-
// ^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#p.
46-
// ^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#p.
45+
// ^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#p.
46+
// ^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#p.
4747
</div>
48-
// ^^^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#div.
48+
// ^^^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#div.
4949
)
5050

5151
export const LoaderInput2: React.FunctionComponent<Props> = props => {
5252
// ^^^^^^^^^^^^ definition react-example 1.0.0 src/`LoaderInput.tsx`/LoaderInput2.
5353
// documentation ```ts\nvar LoaderInput2: FunctionComponent<Props>\n```
54-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
55-
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/FunctionComponent#
54+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
55+
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/FunctionComponent#
5656
// ^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#
5757
// ^^^^^ definition local 9
5858
// documentation ```ts\n(parameter) props: PropsWithChildren<Props>\n```
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react'
22
// definition react-example 1.0.0 src/`MyTSXElement.tsx`/
33
//documentation ```ts\nmodule "MyTSXElement.tsx"\n```
4-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
5-
// ^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/
4+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
5+
// ^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/
66

77
export interface MyProps {}
88
// ^^^^^^^ definition react-example 1.0.0 src/`MyTSXElement.tsx`/MyProps#
@@ -11,8 +11,8 @@
1111
export const MyTSXElement: React.FunctionComponent<MyProps> = ({}) => (<p></p>)
1212
// ^^^^^^^^^^^^ definition react-example 1.0.0 src/`MyTSXElement.tsx`/MyTSXElement.
1313
// documentation ```ts\nvar MyTSXElement: FunctionComponent<MyProps>\n```
14-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
15-
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/FunctionComponent#
14+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
15+
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/FunctionComponent#
1616
// ^^^^^^^ reference react-example 1.0.0 src/`MyTSXElement.tsx`/MyProps#
17-
// ^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#p.
18-
// ^ reference @types/react 17.0.0 `index.d.ts`/global/JSX/IntrinsicElements#p.
17+
// ^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#p.
18+
// ^ reference @types/react 17.0.52 `index.d.ts`/global/JSX/IntrinsicElements#p.

snapshots/output/react/src/UseMyTSXElement.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from "react";
22
// definition react-example 1.0.0 src/`UseMyTSXElement.tsx`/
33
//documentation ```ts\nmodule "UseMyTSXElement.tsx"\n```
4-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
5-
// ^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/
4+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
5+
// ^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/
66

77
import { MyProps, MyTSXElement } from "./MyTSXElement";
88
// ^^^^^^^ reference react-example 1.0.0 src/`MyTSXElement.tsx`/MyProps#
@@ -12,8 +12,8 @@
1212
export const _: React.FunctionComponent<MyProps> =
1313
// ^ definition react-example 1.0.0 src/`UseMyTSXElement.tsx`/_.
1414
// documentation ```ts\nvar _: FunctionComponent<MyProps>\n```
15-
// ^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/
16-
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.0 `index.d.ts`/React/FunctionComponent#
15+
// ^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/
16+
// ^^^^^^^^^^^^^^^^^ reference @types/react 17.0.52 `index.d.ts`/React/FunctionComponent#
1717
// ^^^^^^^ reference react-example 1.0.0 src/`MyTSXElement.tsx`/MyProps#
1818
({}) => (<MyTSXElement></MyTSXElement>)
1919
// ^^^^^^^^^^^^ reference react-example 1.0.0 src/`MyTSXElement.tsx`/MyTSXElement.

src/CommandLineOptions.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ checkIndexParser([], {
3232

3333
checkIndexParser(['--cwd', 'qux'], { cwd: 'qux' })
3434
checkIndexParser(['--yarn-workspaces'], { yarnWorkspaces: true })
35+
checkIndexParser(['--pnpm-workspaces'], { pnpmWorkspaces: true })
3536
checkIndexParser(['--infer-tsconfig'], { inferTsconfig: true })
3637
checkIndexParser(['--no-progress-bar'], { progressBar: false })
3738
checkIndexParser(['--progress-bar'], { progressBar: true })

src/CommandLineOptions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface MultiProjectOptions {
1212
progressBar: boolean
1313
yarnWorkspaces: boolean
1414
yarnBerryWorkspaces: boolean
15+
pnpmWorkspaces: boolean
1516
globalCaches: boolean
1617
cwd: string
1718
output: string
@@ -47,6 +48,7 @@ export function mainCommand(
4748
command
4849
.command('index')
4950
.option('--cwd <path>', 'the working directory', process.cwd())
51+
.option('--pnpm-workspaces', 'whether to index all pnpm workspaces', false)
5052
.option('--yarn-workspaces', 'whether to index all yarn workspaces', false)
5153
.option(
5254
'--yarn-berry-workspaces',

src/main.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ if (isUpdate && fs.existsSync(outputDirectory)) {
3131
}
3232
interface PackageJson {
3333
workspaces: string[]
34+
packageManager?: string
3435
}
3536
for (const snapshotDirectory of snapshotDirectories) {
3637
// Uncomment below if you want to skip certain tests for local development.
@@ -56,6 +57,7 @@ for (const snapshotDirectory of snapshotDirectories) {
5657
output,
5758
yarnWorkspaces: Boolean(packageJson.workspaces),
5859
yarnBerryWorkspaces: false,
60+
pnpmWorkspaces: Boolean(packageJson.packageManager?.includes('pnpm')),
5961
progressBar: false,
6062
indexedProjects: new Set(),
6163
globalCaches: true,

src/main.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env node
22
import * as child_process from 'child_process'
33
import * as fs from 'fs'
4+
import { EOL } from 'os'
45
import * as path from 'path'
56
import * as url from 'url'
67

@@ -33,6 +34,8 @@ export function indexCommand(
3334
projects.push(...listYarnWorkspaces(options.cwd, 'tryYarn1'))
3435
} else if (options.yarnBerryWorkspaces) {
3536
projects.push(...listYarnWorkspaces(options.cwd, 'yarn2Plus'))
37+
} else if (options.pnpmWorkspaces) {
38+
projects.push(...listPnpmWorkspaces(options.cwd))
3639
} else if (projects.length === 0) {
3740
projects.push(options.cwd)
3841
}
@@ -211,6 +214,28 @@ function defaultCompilerOptions(configFileName?: string): ts.CompilerOptions {
211214
return options
212215
}
213216

217+
function listPnpmWorkspaces(directory: string): string[] {
218+
/**
219+
* Returns the list of projects formatted as:
220+
* '/Users/user/sourcegraph/client/web:@sourcegraph/[email protected]:PRIVATE',
221+
*
222+
* See https://pnpm.io/id/cli/list#--depth-number
223+
*/
224+
const output = child_process.execSync(
225+
'pnpm ls -r --depth -1 --long --parseable',
226+
{
227+
cwd: directory,
228+
encoding: 'utf-8',
229+
maxBuffer: 1024 * 1024 * 5, // 5MB
230+
}
231+
)
232+
233+
return output
234+
.split(EOL)
235+
.filter(project => project.includes(':'))
236+
.map(project => project.split(':')[0])
237+
}
238+
214239
function listYarnWorkspaces(
215240
directory: string,
216241
yarnVersion: 'tryYarn1' | 'yarn2Plus'

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,11 @@ pluralize@^8.0.0:
22812281
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
22822282
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
22832283

2284+
2285+
version "7.20.0"
2286+
resolved "https://registry.yarnpkg.com/pnpm/-/pnpm-7.20.0.tgz#fa5c9d347852e9ce1e98abe7f6636c3a78f710bb"
2287+
integrity sha512-klGp+P0sxw1f6OYwJtl0PcoYiIHVhMZdh9e2B8maUmzOGmAj0NL9jKaKPfIX4kKfyQcWeADm46Z+4CKtabZqSw==
2288+
22842289
prelude-ls@^1.2.1:
22852290
version "1.2.1"
22862291
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"

0 commit comments

Comments
 (0)