Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PNPM workspaces #663

Merged
merged 71 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b144b97
remove baseUrl/typeRoots
sandersn Mar 28, 2023
689ccfc
WIP dtslint checks
sandersn Mar 30, 2023
85f0532
check version in package.json
sandersn Mar 31, 2023
2dbbcee
update to ts@next to match DT
sandersn Mar 31, 2023
683cbf2
Switch from no-outside-dependencies to import/no-extraneous-dependencies
sandersn Mar 31, 2023
2a62b4b
Fix used-files calculation and improve error output
sandersn Mar 31, 2023
9ffae5f
allow all @types deps
sandersn Mar 31, 2023
55bde30
Mostly done switching to package.json dep/devDeps
sandersn Apr 3, 2023
b19ebf4
Restore code for finding global values in source
sandersn Apr 3, 2023
3b866d1
definitions-parser tests pass
sandersn Apr 3, 2023
c30e50a
*now* definitions-parser tests all pass
sandersn Apr 3, 2023
ffc9fc4
Make generate-packages tests pass
sandersn Apr 3, 2023
da605a2
npm i -> pnpm i (compiles but hasn't run yet)
sandersn Apr 10, 2023
3d5cd40
Delete installDependencies entirely
sandersn Apr 10, 2023
a336a4e
Remove pathMapping check in definition-parser
sandersn Apr 10, 2023
ecac2cc
slice multiple prefixes from resolved filenames
sandersn Apr 10, 2023
39d5fe7
add debug entrypoint for dtslint-runner
sandersn Apr 13, 2023
72c0633
Switch from index.d.ts header to package.json
sandersn Apr 14, 2023
2c80d98
Require either contributor url XOR githubUsername
sandersn Apr 17, 2023
05fcf43
Switch to reporting errors at end, not throwing one at a time
sandersn Apr 17, 2023
dfa99bd
1. Remove npm consistency checks in dtslint-runner. They are unused.
sandersn Apr 17, 2023
7bca052
Switch to more semver
sandersn Apr 19, 2023
1749d27
Package publication works now.
sandersn May 12, 2023
fbbc16d
Merge branch 'master' into pnpm-workspaces
andrewbranch Sep 27, 2023
1747765
Fix merge conflict mistakes
andrewbranch Sep 27, 2023
c0890ef
Merge branch 'master' into pnpm-workspaces
sandersn Oct 2, 2023
0e51163
Test fixes
sandersn Oct 2, 2023
069c892
1. Add two new external dependencies
sandersn Oct 2, 2023
957cb23
dprint
sandersn Oct 2, 2023
8a19bd0
fix lint
sandersn Oct 2, 2023
3626e27
Fix version of packages after parsing
sandersn Oct 2, 2023
b302acc
Minor fixes
sandersn Oct 3, 2023
246e90d
Merge branch 'master' into pnpm-workspaces
andrewbranch Oct 3, 2023
ce65d47
Merge branch 'master' into pnpm-workspaces
andrewbranch Oct 3, 2023
a93d80e
realpath when enumerating files
andrewbranch Oct 3, 2023
f0903be
Rename name-related fields (#752)
andrewbranch Oct 5, 2023
7cf05ac
Include nonNpm in published package.json
andrewbranch Oct 5, 2023
8a2d200
Pnpm workspaces: fix dtslint-runner incremental (#753)
sandersn Oct 9, 2023
669100b
getAffectedPackages:array of errors, don't throw
sandersn Oct 9, 2023
6c3f181
fix lint
sandersn Oct 9, 2023
1c95ea2
Cleanup and TODOs
sandersn Oct 10, 2023
fc9aa97
Move more things to header-parser
sandersn Oct 10, 2023
a80c7dd
Parse with semver
sandersn Oct 10, 2023
ea10c0d
require devDeps to have self-ref w/workspace:.
sandersn Oct 10, 2023
67ad027
Move semver deps
sandersn Oct 10, 2023
f22f195
Forbid references to old /v* packages
sandersn Oct 10, 2023
249031c
make definitions-parser error handling more like header-parser
sandersn Oct 10, 2023
cef6149
new validation for tsconfig "paths"
sandersn Oct 10, 2023
d5f2a9d
format files
sandersn Oct 10, 2023
cda4775
Remove lint + a couple of TODOs
sandersn Oct 11, 2023
e5a2fb2
lint rule to forbid old header
sandersn Oct 11, 2023
a99ce6c
new lint: forbid devDep imports in .d.ts
sandersn Oct 11, 2023
7d58195
Allow self-reference in no-import-of-dev-dependencies
sandersn Oct 12, 2023
53402d2
forbid pinning on-DT @types/ packages
sandersn Oct 12, 2023
2b3ad3b
update READMEs
sandersn Oct 13, 2023
12b8ddc
make dtslint example files more generic
sandersn Oct 13, 2023
beb0355
Edits from self-review of PR
sandersn Oct 16, 2023
9266a75
npmNaming: report all errors always
sandersn Oct 16, 2023
1095384
dtslint-runner --clone SHA runs pnpm install once again
sandersn Oct 16, 2023
4aba26b
fix direction of clone check
sandersn Oct 16, 2023
102c3f3
Remove globals, make praser not crash on empty directories, remove de…
andrewbranch Oct 16, 2023
945114b
Remove obsolete test
andrewbranch Oct 16, 2023
b3509c5
Finish removing globals stuff
andrewbranch Oct 16, 2023
86a0736
Package.json: change properties and patch version
sandersn Oct 16, 2023
577b7da
address PR comments
sandersn Oct 16, 2023
2bfab35
Update dts-critic message to reference package.json instead of header…
andrewbranch Oct 17, 2023
2904537
dts-critic correctly passes typesVersions to header-parser
sandersn Oct 17, 2023
f1c69db
allow 0.0 versions to mismatch npm again
sandersn Oct 17, 2023
b4e40d1
get-affected-packages: check for dependents by package name
sandersn Oct 17, 2023
1e7bb28
dtslint-runner: Simplify getAffectedPackagesFromDiff
sandersn Oct 17, 2023
4a24663
Add changeset for shipping
sandersn Oct 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,47 @@
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"name": "dtslint-runner local all",
"program": "${workspaceFolder}/packages/dtslint-runner/dist/index.js",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
"skipFiles": [
"<node_internals>/**"
],
"args": [
"--path", "../DefinitelyTyped", "--selection", "all", "--localTypeScriptPath", "../../ts/built/local",
],
"type": "node"
},
{
"name": "jest",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"args": [ "definitions-parser"],
"type": "node"
},
{
"name": "dts-critic test",
"program": "${workspaceFolder}/packages/dts-critic/dist/index.js",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"args": [ "--dts", "packages/dts-critic/testsource/tslib/index.d.ts", ],
"type": "node"
},
{
"name": "dtslint aframe",
"program": "${workspaceFolder}/packages/dtslint/dist/index.js",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"args": [ "../DefinitelyTyped/types/aframe", ],

"type": "node"
},
]
}
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
A monorepo for formerly disparate DefinitelyTyped-related tools:

- [definitions-parser](packages/definitions-parser): the part of [microsoft/types-publisher](https://github.com/microsoft/types-publisher) that reads DefinitelyTyped repository data
- [dtslint](packages/dtslint): [microsoft/dtslint](https://github.com/microsoft/dtslint)
- [dtslint-runner](packages/dtslint-runner): [DefinitelyTyped/dtslint-runner](https://github.com/DefinitelyTyped/dtslint-runner)
- [dts-critic](packages/dts-critic): [DefinitelyTyped/dts-critic](https://github.com/DefinitelyTyped/dts-critic)
- [header-parser](packages/header-parser): [microsoft/definitelytyped-header-parser](https://github.com/microsoft/definitelytyped-header-parser)
- [dtslint](packages/dtslint): [microsoft/dtslint](https://github.com/microsoft/dtslint), make sure a package is correct for DT
- [dtslint-runner](packages/dtslint-runner): [DefinitelyTyped/dtslint-runner](https://github.com/DefinitelyTyped/dtslint-runner), test all packages, or all changed packages, on DT with dtslint
- [eslint-plugin](packages/eslint-plugin): provides DT-specific lint rules (except for the few remaining tslint rules, still in dtslint)
- [dts-critic](packages/dts-critic): [DefinitelyTyped/dts-critic](https://github.com/DefinitelyTyped/dts-critic), issue errors when a types packages mismatches its original Javascript package.
- [header-parser](packages/header-parser): [microsoft/definitelytyped-header-parser](https://github.com/microsoft/definitelytyped-header-parser), check and extract DT-related info from package.json
- [publisher](packages/publisher): the rest of [microsoft/types-publisher](https://github.com/microsoft/types-publisher)
- [retag](packages/retag): [DefinitelyTyped/dt-retag](https://github.com/DefinitelyTyped/dt-retag)
- [retag](packages/retag): [DefinitelyTyped/dt-retag](https://github.com/DefinitelyTyped/dt-retag), script to add ATA tags to `@types` packages. Run weekly.
- [typescript-versions](packages/typescript-versions): the part of [definitelytyped-header-parser](https://github.com/microsoft/definitelytyped-header-parser) that tracked which TypeScript versions are published to npm and supported on DefinitelyTyped
- [utils](packages/utils): shared utilities, mostly extracted from [microsoft/types-publisher](https://github.com/microsoft/types-publisher)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"eslint": "^7.31.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsdoc": "^30.7.8",
"jest": "^29.5.0",
"prettier": "^2.6.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ bl
bookshelf
boxen
broadcast-channel
broccoli-node-api
broccoli-plugin
bson
buffer
Expand Down Expand Up @@ -724,6 +725,7 @@ log4js
logform
loglevel
logrocket
long
lottie-web
magic-string
markdownlint
Expand Down
169 changes: 71 additions & 98 deletions packages/definitions-parser/src/get-affected-packages.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,82 @@
import { mapDefined, mapIterable, sort } from "@definitelytyped/utils";
import {
TypingsData,
AllPackages,
PackageId,
PackageBase,
getMangledNameForScopedPackage,
formatDependencyVersion,
} from "./packages";

export interface Affected {
readonly changedPackages: readonly TypingsData[];
readonly dependentPackages: readonly TypingsData[];
allPackages: AllPackages;
import { assertDefined, execAndThrowErrors, mapDefined, withoutStart } from "@definitelytyped/utils";
import { sourceBranch, sourceRemote } from "./lib/settings";
import { AllPackages, PackageId, formatTypingVersion, getDependencyFromFile } from "./packages";
import { resolve } from "path";
import { satisfies } from "semver";
export interface PreparePackagesResult {
readonly packageNames: Set<string>;
readonly dependents: Set<string>;
}

/** Gets all packages that have changed on this branch, plus all packages affected by the change. */
export function getAffectedPackages(allPackages: AllPackages, changedPackageIds: PackageId[]): Affected {
const resolved = changedPackageIds.map((id) => allPackages.tryResolve(id));
// If a package doesn't exist, that's because it was deleted.
const changed = mapDefined(resolved, (id) => allPackages.tryGetTypingsData(id));
const dependent = mapIterable(collectDependers(resolved, getReverseDependencies(allPackages, resolved)), (p) =>
allPackages.getTypingsData(p)
);
return { changedPackages: changed, dependentPackages: sortPackages(dependent), allPackages };
}

/** Every package name in the original list, plus their dependencies (incl. dependencies' dependencies). */
export function allDependencies(allPackages: AllPackages, packages: Iterable<TypingsData>): TypingsData[] {
return sortPackages(transitiveClosure(packages, (pkg) => allPackages.allDependencyTypings(pkg)));
}

/** Collect all packages that depend on changed packages, and all that depend on those, etc. */
function collectDependers(
changedPackages: PackageId[],
reverseDependencies: Map<PackageId, Set<PackageId>>
): Set<PackageId> {
const dependers = transitiveClosure(changedPackages, (pkg) => reverseDependencies.get(pkg) || []);
// Don't include the original changed packages, just their dependers
for (const original of changedPackages) {
dependers.delete(original);
}
return dependers;
}

function sortPackages(packages: Iterable<TypingsData>): TypingsData[] {
return sort<TypingsData>(packages, PackageBase.compare); // tslint:disable-line no-unbound-method
}

function transitiveClosure<T>(initialItems: Iterable<T>, getRelatedItems: (item: T) => Iterable<T>): Set<T> {
const all = new Set<T>();
const workList: T[] = [];

function add(item: T): void {
if (!all.has(item)) {
all.add(item);
workList.push(item);
export async function getAffectedPackages(
allPackages: AllPackages,
deletions: PackageId[],
definitelyTypedPath: string
): Promise<PreparePackagesResult> {
const allDependents = [];
const filters = [`--filter '...[${sourceRemote}/${sourceBranch}]'`];
for (const d of deletions) {
for (const dep of allPackages.allTypings()) {
for (const [name, version] of dep.allPackageJsonDependencies()) {
if (
"@types/" + d.typesDirectoryName === name &&
(d.version === "*" || satisfies(formatTypingVersion(d.version), version))
) {
filters.push(`--filter '...${dep.name}'`);
break;
}
}
}
}

for (const item of initialItems) {
add(item);
}

while (workList.length) {
const item = workList.pop()!;
for (const newItem of getRelatedItems(item)) {
add(newItem);
}
const changedPackageNames = await execAndThrowErrors(
`pnpm ls -r --depth -1 --parseable --filter '[${sourceRemote}/${sourceBranch}]'`,
definitelyTypedPath
sandersn marked this conversation as resolved.
Show resolved Hide resolved
);
// Chunk into 100-package chunks because of CMD.COM's command-line length limit
for (let i = 0; i < filters.length; i += 100) {
allDependents.push(
await execAndThrowErrors(
`pnpm ls -r --depth -1 --parseable ${filters.slice(i, i + 100).join(" ")}`,
definitelyTypedPath
)
);
}

return all;
return getAffectedPackagesWorker(allPackages, changedPackageNames, allDependents, definitelyTypedPath);
}

/** Generate a map from a package to packages that depend on it. */
function getReverseDependencies(
/** This function is exported for testing, since it's determined entirely by its inputs. */
export function getAffectedPackagesWorker(
allPackages: AllPackages,
changedPackages: PackageId[]
): Map<PackageId, Set<PackageId>> {
const map = new Map<string, [PackageId, Set<PackageId>]>();
for (const changed of changedPackages) {
map.set(packageIdToKey(changed), [changed, new Set()]);
}
for (const typing of allPackages.allTypings()) {
if (!map.has(packageIdToKey(typing.id))) {
map.set(packageIdToKey(typing.id), [typing.id, new Set()]);
}
}
for (const typing of allPackages.allTypings()) {
for (const [name, version] of Object.entries(typing.dependencies)) {
const dependencies = map.get(packageIdToKey(allPackages.tryResolve({ name, version })));
if (dependencies) {
dependencies[1].add(typing.id);
}
}
for (const dependencyName of typing.testDependencies) {
const version = typing.pathMappings[dependencyName] || "*";
const dependencies = map.get(packageIdToKey(allPackages.tryResolve({ name: dependencyName, version })));
if (dependencies) {
dependencies[1].add(typing.id);
}
}
}
return new Map(map.values());
changedOutput: string,
dependentOutputs: string[],
definitelyTypedPath: string
): PreparePackagesResult {
const dt = resolve(definitelyTypedPath);
const changedDirs = mapDefined(changedOutput.split("\n"), getDirectoryName(dt));
const dependentDirs = mapDefined(dependentOutputs.join("\n").split("\n"), getDirectoryName(dt));
const packageNames = new Set(
changedDirs.map(
(c) =>
assertDefined(
allPackages.tryGetTypingsData(assertDefined(getDependencyFromFile(c + "/index.d.ts"), "bad path " + c))
).subDirectoryPath
)
);
const dependents = new Set(
dependentDirs
.map(
(d) =>
assertDefined(
allPackages.tryGetTypingsData(assertDefined(getDependencyFromFile(d + "/index.d.ts"), "bad path " + d)),
d + " package not found"
).subDirectoryPath
)
.filter((d) => !packageNames.has(d))
);
return { packageNames, dependents };
}

function packageIdToKey(pkg: PackageId): string {
return getMangledNameForScopedPackage(pkg.name) + "/v" + formatDependencyVersion(pkg.version);
function getDirectoryName(dt: string): (line: string) => string | undefined {
return (line) =>
line && line !== dt ? assertDefined(withoutStart(line, dt + "/"), line + " is missing prefix " + dt) : undefined;
}
Loading
Loading