Skip to content

Commit 5128444

Browse files
committed
Add the ability to upload to @types/x
1 parent aad7832 commit 5128444

File tree

8 files changed

+291
-0
lines changed

8 files changed

+291
-0
lines changed

.github/workflows/deploy.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Deploy to npm
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
workflow_dispatch:
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v2
16+
- uses: actions/setup-node@v1
17+
with:
18+
node-version: "15.x"
19+
registry-url: "https://registry.npmjs.org"
20+
21+
- run: npm install
22+
- run: npm run build
23+
- run: npm test
24+
25+
- name: Create packages for .d.ts files
26+
run: node deploy/createTypesPackages.mjs
27+
28+
# Deploy anything which differs from the npm version of a tsconfig
29+
- name: 'Deploy built packages to NPM'
30+
run: node deploy/deployChangedPackages.mjs
31+
env:
32+
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
33+

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,4 @@ inputfiles/browser.webidl.json
286286
package-lock.json
287287
yarn.lock
288288
TypeScript
289+
deploy/generated

deploy/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Deploys
2+
3+
We want to generate @types/xyz

deploy/createTypesPackages.mjs

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// @ts-check
2+
3+
// node deploy/createTypesPackages.mjs
4+
5+
// prettier-ignore
6+
const packages = [
7+
{
8+
name: "@types/web",
9+
description: "Types for the DOM, and other web technologies in browsers",
10+
files: [
11+
{ from: "../generated/dom.generated.d.ts", to: "index.d.ts" }
12+
],
13+
},
14+
];
15+
16+
// Note: You can add 'version: "1.0.0"' to a package above
17+
// to set the major or minor, otherwise it will always bump
18+
// the patch.
19+
20+
import { join, dirname } from "path";
21+
import fs from "fs";
22+
import { fileURLToPath } from "url";
23+
import pkg from "prettier";
24+
const { format } = pkg;
25+
import { execSync } from "child_process";
26+
27+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
28+
// @ts-ignore
29+
const __filename = fileURLToPath(import.meta.url);
30+
const __dirname = dirname(__filename);
31+
32+
const go = async () => {
33+
const gitSha = execSync("git rev-parse HEAD").toString().trim().slice(0, 7);
34+
35+
const generatedDir = join(__dirname, "generated");
36+
const templateDir = join(__dirname, "template");
37+
38+
for (const pkg of packages) {
39+
const folderName = pkg.name.replace("@", "").replace("/", "-");
40+
const packagePath = join(generatedDir, folderName);
41+
42+
if (fs.existsSync(packagePath)) fs.rmSync(packagePath, { recursive: true });
43+
fs.mkdirSync(packagePath, { recursive: true });
44+
45+
// Migrate in the template files
46+
for (const templateFile of fs.readdirSync(templateDir)) {
47+
if (templateFile.startsWith(".")) continue;
48+
49+
const templatedFile = join(templateDir, templateFile);
50+
fs.copyFileSync(templatedFile, join(packagePath, templateFile));
51+
}
52+
53+
// Add the reference files in the config above
54+
pkg.files.forEach((fileRef) => {
55+
fs.copyFileSync(
56+
join(__filename, "..", fileRef.from),
57+
join(packagePath, fileRef.to)
58+
);
59+
});
60+
61+
// Setup the files
62+
await updatePackageJSON(packagePath, pkg, gitSha);
63+
64+
console.log("Built:", pkg.name);
65+
}
66+
};
67+
68+
go();
69+
70+
async function updatePackageJSON(packagePath, pkg, gitSha) {
71+
const pkgJSONPath = join(packagePath, "package.json");
72+
const packageText = fs.readFileSync(pkgJSONPath, "utf8");
73+
const packageJSON = JSON.parse(packageText);
74+
packageJSON.name = pkg.name;
75+
packageJSON.description = pkg.description;
76+
77+
// Bump the last version of the number from npm,
78+
// or use the _version in tsconfig if it's higher,
79+
// or default to 0.0.1
80+
let version = pkg.version || "0.0.1";
81+
try {
82+
const npmResponse = await fetch(
83+
`https://registry.npmjs.org/${packageJSON.name}`
84+
);
85+
const npmPackage = await npmResponse.json();
86+
87+
const semverMarkers = npmPackage["dist-tags"].latest.split(".");
88+
const bumpedVersion = `${semverMarkers[0]}.${semverMarkers[1]}.${
89+
Number(semverMarkers[2]) + 1
90+
}`;
91+
92+
if (isBumpedVersionHigher(version, bumpedVersion)) {
93+
version = bumpedVersion;
94+
}
95+
} catch (error) {
96+
// NOOP, this is for the first deploy, which will set it to 0.0.1
97+
}
98+
99+
packageJSON.version = version;
100+
packageJSON.domLibGeneratorSha = gitSha;
101+
102+
fs.writeFileSync(
103+
pkgJSONPath,
104+
format(JSON.stringify(packageJSON), { filepath: pkgJSONPath })
105+
);
106+
}
107+
108+
/**
109+
* @param packageJSONVersion {string}
110+
* @param bumpedVersion {string}
111+
*/
112+
function isBumpedVersionHigher(packageJSONVersion, bumpedVersion) {
113+
const semverMarkersPackageJSON = packageJSONVersion.split(".");
114+
const semverMarkersBumped = bumpedVersion.split(".");
115+
for (let i = 0; i < 3; i++) {
116+
if (Number(semverMarkersPackageJSON[i]) > Number(semverMarkersBumped[i])) {
117+
return false;
118+
}
119+
}
120+
121+
return true;
122+
}

deploy/deployChangedPackages.mjs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// @ts-check
2+
3+
// node deploy/deployChangedPackages.mjs
4+
// Builds on the results of createTypesPackages.mjs and deploys the
5+
// ones which have changed.
6+
7+
import * as fs from "fs";
8+
import { join, dirname } from "path";
9+
import { fileURLToPath } from "url";
10+
import fetch from "node-fetch";
11+
import { spawnSync } from "child_process";
12+
13+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
14+
// @ts-ignore
15+
const __filename = fileURLToPath(import.meta.url);
16+
const __dirname = dirname(__filename);
17+
18+
const go = async () => {
19+
const uploaded = [];
20+
21+
// Loop through generated packages, deploying versions for anything which has different
22+
// .d.ts files from the version available on npm.
23+
const generatedDir = join(__dirname, "generated");
24+
for (const dirName of fs.readdirSync(generatedDir)) {
25+
const localPackageJSONPath = join(generatedDir, dirName, "package.json");
26+
const newTSConfig = fs.readFileSync(localPackageJSONPath, "utf-8");
27+
const pkgJSON = JSON.parse(newTSConfig);
28+
29+
const dtsFiles = fs
30+
.readdirSync(join(generatedDir, dirName))
31+
.filter((f) => f.endsWith(".d.ts"));
32+
33+
// Look through each .d.ts file included in a package to
34+
// determine if anything has changed
35+
let upload = false;
36+
for (const file of dtsFiles) {
37+
const generatedDTSPath = join(generatedDir, dirName, file);
38+
const generatedDTSContent = fs.readFileSync(generatedDTSPath, "utf8");
39+
try {
40+
const unpkgURL = `https://unpkg.com/${pkgJSON.name}/${file}`;
41+
const npmDTSReq = await fetch(unpkgURL);
42+
const npmDTSText = await npmDTSReq.text();
43+
upload = upload || npmDTSText !== generatedDTSContent;
44+
} catch (error) {
45+
// Not here, definitely needs to be uploaded
46+
upload = true;
47+
}
48+
}
49+
50+
// Publish via npm
51+
if (upload) {
52+
if (process.env.NODE_AUTH_TOKEN) {
53+
const publish = spawnSync("npm", ["publish", "--access", "public"], {
54+
cwd: join("packages", dirName),
55+
});
56+
57+
if (publish.status) {
58+
console.log(publish.stdout?.toString());
59+
console.log(publish.stderr?.toString());
60+
process.exit(publish.status);
61+
} else {
62+
console.log(publish.stdout?.toString());
63+
}
64+
}
65+
66+
uploaded.push(dirName);
67+
}
68+
}
69+
70+
// Warn if we did a dry run.
71+
if (!process.env.NODE_AUTH_TOKEN) {
72+
console.log(
73+
"Did a dry run because process.env.NODE_AUTH_TOKEN is not set."
74+
);
75+
}
76+
77+
if (uploaded.length) {
78+
console.log("Uploaded: ", uploaded.join(", "));
79+
} else {
80+
console.log("No uploads");
81+
}
82+
};
83+
84+
go();

deploy/template/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Microsoft Corporation.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE

deploy/template/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Installation
2+
> `npm install --save {{name}}`
3+
4+
# Summary
5+
{{description}}
6+
7+
8+
### Additional Details
9+
* Last updated: {{date}}
10+
* Dependencies: none
11+
* Global values: none
12+

deploy/template/package.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "@types/xyz",
3+
"version": "0.0.x",
4+
"description": "TypeScript definitions for xyz",
5+
"license": "MIT",
6+
"contributors": [],
7+
"main": "",
8+
"types": "index.d.ts",
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/microsoft/TypeScript-DOM-Lib-Generator.git"
12+
},
13+
"scripts": {},
14+
"dependencies": {}
15+
}

0 commit comments

Comments
 (0)