-
Notifications
You must be signed in to change notification settings - Fork 216
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
Transition DT packages to use package.json files
#769
Comments
I am very much in favor of the simple files array approach that just always includes d.ts files. One gotcha is that some packages have scripts that they use to generate code, so we will want to be able to ignore those somehow. Maybe like tsconfig mismatches, error check in the mergebot if someone adds something else? |
I think scripts should only be Some notes on unused files based on Teams notes.
The only real value that OTHER_FILES is serving in this case is making a note that the files in it are not included in test coverage. It’s not clear to me why this wouldn’t have just been encoded in tsconfig’s
Specifically, the thing we’re missing is considering other entrypoints besides index.d.ts. We should be looking at package.json |
Note that declaration file extensions can be:
The last one is neglected from DT-tools and some of our Teams conversations, so we should make sure not to forget it. |
The main exception to this rule so far is the nested
Which is to say that two packages are weirdly broken, but all 9000 other packages match this rule! |
Awful script: // @ts-check
import { AllPackages, getDefinitelyTyped, parseDefinitions } from "@definitelytyped/definitions-parser";
import { glob } from "glob";
import assert from "node:assert";
import * as os from "node:os";
import path from "node:path";
const options = { definitelyTypedPath: ".", progress: false, parseInParallel: true };
const dt = await getDefinitelyTyped(options, console);
await parseDefinitions(dt, { nProcesses: os.cpus().length, definitelyTypedPath: "." }, console);
const allPackages = await AllPackages.read(dt);
const typings = allPackages.allTypings();
const patterns = [
"**/*.d.ts",
"**/*.d.mts",
"**/*.d.cts",
"**/*.d.*.ts",
];
await Promise.all(typings.map(async (data) => {
const dir = path.join("types", data.subDirectoryPath);
const resolvedDir = path.resolve(dir);
const globFiles = (await glob(patterns, {
cwd: dir,
nodir: true,
ignore: {
childrenIgnored: (p) => {
if (p.name === "node_modules") return true;
const fullpath = p.fullpath();
if (fullpath === resolvedDir) return false;
if (
data.isLatest
&& /^v[0-9]+(?:\.[0-9]+)?$/.test(p.name)
&& fullpath === path.join(resolvedDir, p.name)
) {
return true;
}
return false;
},
},
})).sort();
const expected = data.files.slice().sort();
try {
assert.deepStrictEqual(globFiles, expected);
} catch (e) {
console.error(`Mismatch in ${dir}`);
console.error("dt-tools says", expected);
console.error("but glob is ", globFiles);
}
})); |
Just to make sure I did it right, I changed the glob to also include |
There's still a chance somebody would want to ship something besides README.md or .d.ts files, but I think it's low given that it hasn't happened in the last five years.
|
Those two are probably already "working" by nature of the publisher placing files at those paths and then |
As for the files, right now, it's the case that all files that we include are explicitly just those four globs, then npm implicitly adds We can still keep the detection and |
I don’t think “unused” has been a particularly well-defined concept here, historically. Any .d.ts file in a package that doesn’t have package.json Even without |
Here are my notes from our discussion that roughly correspond to work items:
|
In trying to implement this, it was a lot easier to just directly check per package what the intended files array should be, and not any of the parent stuff, so my WIP branch does that instead which is clearer anyhow as it can directly assert equality to a specific expected list. |
It turns out that "files": [
"**/*.d.{ts,cts,mts,*.ts}",
"!v15",
"!v16",
"!v17"
], But npm7, npm8, pnpm, and all versions of yarn did not ignore things. Both The best I've gotten is to write *
!**/*.d.{ts,cts,mts,*.ts}
/v15/
/v16/
/v17/ This makes all package managers happy except yarn1, yarn3, and yarn4. Really, this just affects people randomly running |
I guess yarn implements this as an include/exclude list, so the order doesn't matter at all. https://github.com/yarnpkg/berry/blob/ab2e84588b1eacb2ec60a751f12b168415224a19/packages/plugin-pack/sources/packUtils.ts#L204 |
Yeah, my script didn't take into account packages which didn't contain any files; yarn ends up with empty packages because the patterns exclude all files and further patterns do not override things. *
!**/*.d.ts
!**/*.d.cts
!**/*.d.mts
!**/*.d.*.ts
/v15/
/v16/
/v17/ |
Hm, additionally, patterns like |
Filed yarnpkg/berry#5872. |
new work on DT=new bugs filed on package managers |
This will make it much easier and faster to determine what packages have been changed since last successful publish, since that’s done via a content hash of all published files, but “all published files” is currently dynamically determined by following imports and triple-slash references from
index.d.ts
, which requires parsing TypeScript SourceFiles and performing module resolution.There are two ways forward here:
files
to determine what to publish, but during CI, use the same module resolution andOTHER_FILES.txt
logic to ensure thatfiles
is consistent with the result there. Critically, we need to ensure thatfiles
does not omit anything that gets referenced byindex.d.ts
or any other package entrypoint.files
includes all declaration files, README, LICENSE, nested package.jsons, and nothing else. (We have not yet checked to see if any packages violate this rule as they are now.) This would be simpler and cheaper. We would only have to move theDefinitions must use global references to other packages, not parent ("../xxx") references
check, as that’s currently issued as we collect referenced files (module-info.ts
). We would also lose the unused file check, and I’m not sure how important that is, but if we want to keep it, we would want to move that into dtslint. (Note that all the module resolution already happens as part of the multiplets.createProgram
calls that happen in dtslint. In the future, we should also include all files mentioned by package.json"exports"
in these program root files.)I’m in favor of (2) for simplicity and consistency. Either way, adding
files
will change the content hash of every package and cause every package to be republished. A few observations about this:paths
, so we should remove that from the hash inputs. We also discussed stringifying the package.json object instead of including its file contents, so future formatting changes to package.json files wouldn’t cause a repo-wide republish.files
, and using it as the source of truth if present. Then, we could automate the change to DT as a series of PRs that can be merged slowly, as we did with formatting.The text was updated successfully, but these errors were encountered: