Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
f5293423738cc9d1d07e5bf87ae7a1b4cffff12f # https://github.com/tsconfig/bases/commit/f529342
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL'd

4 changes: 2 additions & 2 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
uses: actions/checkout@v3

- name: Set-up Deno
uses: denoland/setup-deno@v1
uses: denoland/setup-deno@v2
with:
deno-version: v1.x
deno-version: v2.x

# Build all the packages
- name: Create packages for TSConfig JSONs
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ jobs:
registry-url: https://registry.npmjs.org

- name: Set-up Deno
uses: denoland/setup-deno@v1
uses: denoland/setup-deno@v2
with:
deno-version: v1.x
deno-version: v2.x

# Build all the packages
- name: Create packages for TSConfig JSONs
Expand Down
16 changes: 16 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"tasks": {
"build": "deno run -RWN ./scripts/create-npm-packages.ts"
},
"imports": {
"@std/collections": "jsr:@std/collections@^1.1.2",
"@std/io": "jsr:@std/io@^0.225.2",
"@std/path": "jsr:@std/path@^1.1.1",
"@std/semver": "jsr:@std/semver@^1.0.5",
"@std/streams": "jsr:@std/streams@^1.0.10",
"strip-json-comments": "npm:strip-json-comments@^5.0.3"
},
"fmt": {
"include": ["deno.json", "scripts/"]
}
}
63 changes: 63 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

137 changes: 81 additions & 56 deletions scripts/create-npm-packages.ts
Original file line number Diff line number Diff line change
@@ -1,103 +1,128 @@
import * as path from "https://deno.land/std/path/mod.ts";
import stripJsonComments from "https://esm.sh/strip-json-comments";
import * as path from "jsr:@std/path";
import stripJsonComments from "npm:strip-json-comments";

for await (const tsconfigEntry of Deno.readDir("bases")) {
if (!tsconfigEntry.isFile) continue
const tsconfigFilePath = path.join("bases", tsconfigEntry.name)
const name = path.basename(tsconfigEntry.name).replace(".json", "")
if (!tsconfigEntry.isFile) continue;

const tsconfigFilePath = path.join("bases", tsconfigEntry.name);
const name = path.basename(tsconfigEntry.name).replace(".json", "");

// Make the folder
const packagePath = path.join("packages", name)
Deno.mkdirSync(packagePath, { recursive: true })
const packagePath = path.join("packages", name);
Deno.mkdirSync(packagePath, { recursive: true });

// Copy over the template files
const templateDir = "./template"
const templateDir = "./template";
for await (const templateFile of Deno.readDir(templateDir)) {
if (!templateFile.isFile) continue
const templatedFile = path.join(templateDir, templateFile.name)
Deno.copyFileSync(templatedFile, path.join(packagePath, templateFile.name))
if (!templateFile.isFile) continue;
const templatedFile = path.join(templateDir, templateFile.name);
Deno.copyFileSync(templatedFile, path.join(packagePath, templateFile.name));
}

// Copy the create a tsconfig.json from the base json
const newPackageTSConfigPath = path.join(packagePath, "tsconfig.json")
Deno.copyFileSync(tsconfigFilePath, newPackageTSConfigPath)
const tsconfigText = await Deno.readTextFile(newPackageTSConfigPath)
const tsconfigJSON = JSON.parse(stripJsonComments(tsconfigText))
const newPackageTSConfigPath = path.join(packagePath, "tsconfig.json");
Deno.copyFileSync(tsconfigFilePath, newPackageTSConfigPath);

const tsconfigText = await Deno.readTextFile(newPackageTSConfigPath);
const tsconfigJSON = JSON.parse(stripJsonComments(tsconfigText));

// Drop `display` field in tsconfig.json for npm package
await Deno.writeTextFile(newPackageTSConfigPath, tsconfigText.replace(/\s*"display.*/,''))
// Drop `display` field in tsconfig.json for npm package
await Deno.writeTextFile(
newPackageTSConfigPath,
tsconfigText.replace(/\s*"display.*/, ""),
);

// Edit the package.json
const packageText = await Deno.readTextFile(path.join(packagePath, "package.json"))
const packageJSON = JSON.parse(packageText)
packageJSON.name = `@tsconfig/${name}`
packageJSON.description = `A base TSConfig for working with ${tsconfigJSON.display}.`
packageJSON.keywords = ["tsconfig", name]
const packageText = await Deno.readTextFile(
path.join(packagePath, "package.json"),
);
const packageJSON = JSON.parse(packageText);
packageJSON.name = `@tsconfig/${name}`;
packageJSON.description =
`A base TSConfig for working with ${tsconfigJSON.display}.`;
packageJSON.keywords = ["tsconfig", name];

// Do some string replacements in the other templated files
const replaceTextIn = ["README.md"]
const replaceTextIn = ["README.md"];
for (const filenameToEdit of replaceTextIn) {
const fileToEdit = path.join(packagePath, filenameToEdit)

const defaultTitle = `A base TSConfig for working with ${tsconfigJSON.display}`
const title = name !== "recommended" ? defaultTitle : "The recommended base for a TSConfig"
const fileToEdit = path.join(packagePath, filenameToEdit);

let packageText = await Deno.readTextFile(fileToEdit)
const defaultTitle =
`A base TSConfig for working with ${tsconfigJSON.display}`;
const title = name !== "recommended"
? defaultTitle
: "The recommended base for a TSConfig";

let packageText = await Deno.readTextFile(fileToEdit);
packageText = packageText.replace(/\[filename\]/g, name)
.replace(/\[display_title\]/g, title)
.replace(/\[tsconfig\]/g, Deno.readTextFileSync(newPackageTSConfigPath))
.replace(/\[display_title\]/g, title)
.replace(/\[tsconfig\]/g, Deno.readTextFileSync(newPackageTSConfigPath));

// Inject readme-extra if any
try {
const readmeExtra = (await Deno.readTextFile(path.join("readme-extras", `${name}.md`))).trim()

if (readmeExtra)
packageText = packageText.replace(/\[readme-extra\]/g, `\n${readmeExtra}\n`)
const readmeExtra =
(await Deno.readTextFile(path.join("readme-extras", `${name}.md`)))
.trim();

if (readmeExtra) {
packageText = packageText.replace(
/\[readme-extra\]/g,
`\n${readmeExtra}\n`,
);
}
} catch (error) {
// NOOP, there is no extra readme
// NOOP, there is no extra readme
// console.log(error)
}

// Remove readme-extra placeholders if any
packageText = packageText.replace(/\[readme-extra\]/g, '')
packageText = packageText.replace(/\[readme-extra\]/g, "");

await Deno.writeTextFile(fileToEdit, packageText)
};
await Deno.writeTextFile(fileToEdit, packageText);
}

// Bump the last version of the number from npm,
// or use the _version in tsconfig if it's higher,
// or default to 1.0.0
let version = tsconfigJSON._version || "1.0.0"
let version = tsconfigJSON._version || "1.0.0";
try {
const npmResponse = await fetch(`https://registry.npmjs.org/${packageJSON.name}`)
const npmPackage = await npmResponse.json()
const npmResponse = await fetch(
`https://registry.npmjs.org/${packageJSON.name}`,
);
const npmPackage = await npmResponse.json();

const semverMarkers = npmPackage["dist-tags"].latest.split(".");
const bumpedVersion = `${semverMarkers[0]}.${semverMarkers[1]}.${Number(semverMarkers[2]) + 1}`;
const bumpedVersion = `${semverMarkers[0]}.${semverMarkers[1]}.${
Number(semverMarkers[2]) + 1
}`;
if (isBumpedVersionHigher(version, bumpedVersion)) {
version = bumpedVersion;
}
} catch (error) {
// NOOP, this is for the first deploy
// NOOP, this is for the first deploy
// console.log(error)
}

packageJSON.version = version
await Deno.writeTextFile(path.join(packagePath, "package.json"), JSON.stringify(packageJSON, null, " "))

packageJSON.version = version;
await Deno.writeTextFile(
path.join(packagePath, "package.json"),
JSON.stringify(packageJSON, null, " "),
);

console.log("Built:", tsconfigEntry.name);
}

function isBumpedVersionHigher (packageJSONVersion: string, bumpedVersion: string) {
const semverMarkersPackageJSON = packageJSONVersion.split('.')
const semverMarkersBumped = bumpedVersion.split('.')
function isBumpedVersionHigher(
packageJSONVersion: string,
bumpedVersion: string,
) {
const semverMarkersPackageJSON = packageJSONVersion.split(".");
const semverMarkersBumped = bumpedVersion.split(".");
for (let i = 0; i < 3; i++) {
if (Number(semverMarkersPackageJSON[i]) > Number(semverMarkersBumped[i])) {
return false
return false;
}
}

return true
return true;
}
36 changes: 24 additions & 12 deletions scripts/deploy-changed-npm-packages.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import * as path from "https://deno.land/std@0.164.0/path/mod.ts";
import * as bufio from "https://deno.land/std@0.164.0/io/buffer.ts";
import * as path from "jsr:@std/path";
import { TextLineStream } from "jsr:@std/streams";

// Loop through generated packages, deploying versions for anything which has a different tsconfig
const uploaded = []
const uploaded = [];

for (const dirEntry of Deno.readDirSync("packages")) {
const localTsconfigPath = path.join("packages", dirEntry.name, "tsconfig.json");
const localTsconfigPath = path.join(
"packages",
dirEntry.name,
"tsconfig.json",
);
const newTSConfig = Deno.readTextFileSync(localTsconfigPath);

let upload = false;
try {
const unpkgURL = `https://unpkg.com/@tsconfig/${dirEntry.name}/tsconfig.json`;
const unpkgURL =
`https://unpkg.com/@tsconfig/${dirEntry.name}/tsconfig.json`;
const currentJSONReq = await fetch(unpkgURL);
const currentJSONTxt = await currentJSONReq.text();
upload = currentJSONTxt !== newTSConfig;
Expand All @@ -20,23 +25,30 @@ for (const dirEntry of Deno.readDirSync("packages")) {
}

if (upload) {
const process = Deno.run({
cmd: ["npm", "publish", "--provenance", "--access", "public"],
const process = new Deno.Command("npm", {
args: ["publish", "--provenance", "--access", "public"],
stdout: "piped",
cwd: path.join("packages", dirEntry.name),
env: { NODE_AUTH_TOKEN: Deno.env.get("NODE_AUTH_TOKEN")! },
});
}).spawn();

for await (const line of bufio.readLines(process.stdout!)) {
for await (const line of readLines(process.stdout!)) {
console.warn(line);
}

uploaded.push(dirEntry.name)
uploaded.push(dirEntry.name);
}
}

if (uploaded.length) {
console.log("Uploaded: ", uploaded.join(", "))
console.log("Uploaded: ", uploaded.join(", "));
} else {
console.log("No uploads")
console.log("No uploads");
}

function readLines(stream: ReadableStream) {
// https://github.com/denoland/deno/discussions/23495
return stream.pipeThrough(new TextDecoderStream()).pipeThrough(
new TextLineStream(),
);
}
Loading