Skip to content

Commit

Permalink
chore/refactor: rewrite create.cjs in typescript (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW authored Sep 10, 2023
1 parent b36e3b4 commit b9a7bcf
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 208 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
{
"files": [
"bump.config.ts",
"create.ts",
"*.d.ts",
"packages/**/*.ts",
"packages/**/*.tsx"
Expand Down
133 changes: 71 additions & 62 deletions create.cjs → create.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
// @ts-check
'use strict';

const fsPromises = require('fs/promises');
const path = require('path');
const ezspawn = require('@jsdevtools/ez-spawn');
const { PathScurry } = require('path-scurry');
const colors = require('picocolors');
const { dequal } = require('dequal');

const currentPackageJson = require('./package.json');

const { fileExists, compareAndWriteFile } = require('@nolyfill/internal');
import fsPromises from 'fs/promises';
import path from 'path';
import ezspawn from '@jsdevtools/ez-spawn';
import { PathScurry } from 'path-scurry';
import colors from 'picocolors';
import { dequal } from 'dequal';
import { fileExists, compareAndWriteFile } from '@nolyfill/internal';
import type { PackageJson } from 'type-fest';

/**
* @typedef {Object} VirtualPackage
* @prop {string} path
* @prop {Record<string, string>} files
* @prop {import('type-fest').PackageJson} packageJson
* The package.json inside the project has a non-nullable "version" field,
* and a known "pnpm.overrides".
*
* PackageJson type can not be extend since it is a union type.
*/
type CurrentPackageJson = PackageJson & {
version: string,
pnpm: {
overrides: Record<string, string>
} & Record<string, unknown>
};

const autoGeneratedPackagesList = /** @type {const} */ ([
const currentPackageJsonPromise: Promise<CurrentPackageJson> = fsPromises.readFile('./package.json', { encoding: 'utf-8' })
.then(t => JSON.parse(t) as CurrentPackageJson);

interface VirtualPackage {
path: string,
files: Record<string, string>,
packageJson: PackageJson
}

const autoGeneratedPackagesList = [
['array-includes', 'Array.prototype.includes', false],
['array.prototype.findlastindex', `Array.prototype.findLastIndex || function (callback, thisArg) {
for (let i = this.length - 1; i >= 0; i--) {
Expand Down Expand Up @@ -171,9 +183,9 @@ const autoGeneratedPackagesList = /** @type {const} */ ([
}
}));
}`, true, {}, '>=12.4.0', 'Promise']
]);
] as const;

const singleFilePackagesList = /** @type {const} */ ([
const singleFilePackagesList = [
['has-property-descriptors', `const hasPropertyDescriptors = () => true;
hasPropertyDescriptors.hasArrayLengthDefineBug = () => false;
module.exports = hasPropertyDescriptors;`],
Expand Down Expand Up @@ -515,20 +527,20 @@ const assert = (O, slot) => {
}
};
module.exports = Object.freeze({ has, get, set, assert });`]
]);
] as const;

const manualPackagesList = /** @type {const} */ ([
const manualPackagesList = [
'function-bind', // function-bind's main entry point is not uncurried, and doesn't follow es-shim API
'has-tostringtag', // two entries (index.js, shams.js)
'has-symbols', // two entries (index.js, shams.js)
'es-iterator-helpers', // use rollup prebundle approach
'globalthis' // globalthis package's entrypoint is a function, not the implementation
]);
] as const;

const nonNolyfillPackagesList = /** @type {const} */ ([
const nonNolyfillPackagesList = [
'nolyfill',
'@nolyfill/shared'
]);
] as const;

(async () => {
const allPackagesList = [
Expand All @@ -537,24 +549,26 @@ const nonNolyfillPackagesList = /** @type {const} */ ([
...singleFilePackagesList.map(pkg => pkg[0])
].sort();

const currentPackageJson = await currentPackageJsonPromise;

const newPackageJson = {
...currentPackageJson,
overrides: allPackagesList
.reduce((acc, packageName) => {
acc[packageName] = `npm:@nolyfill/${packageName}@latest`;
return acc;
}, /** @type {Record<typeof allPackagesList[number], string>} */({})),
.reduce<Record<string, string>>((acc, packageName) => {
acc[packageName] = `npm:@nolyfill/${packageName}@latest`;
return acc;
}, {}),
pnpm: {
...currentPackageJson.pnpm,
overrides: allPackagesList
.reduce((acc, packageName) => {
acc[packageName] = `workspace:@nolyfill/${packageName}@*`;
return acc;
}, /** @type {Record<typeof allPackagesList[number], string>} */({}))
.reduce<Record<string, string>>((acc, packageName) => {
acc[packageName] = `workspace:@nolyfill/${packageName}@*`;
return acc;
}, {})
}
};

const cliAllPackagesTs = `/* Generated by create.cjs */
const cliAllPackagesTs = `/* Generated by create.ts */
/* eslint-disable */
export const allPackages = ${JSON.stringify(allPackagesList, null, 2)};\n`;

Expand All @@ -579,16 +593,15 @@ export const allPackages = ${JSON.stringify(allPackagesList, null, 2)};\n`;
await ezspawn.async('pnpm', ['i']);
})();

/**
* @param {string} packageName
* @param {string} packageImplementation
* @param {boolean} isStatic
* @param {Record<string, string>} [extraDependencies]
* @param {string} [minimumNodeVersion]
* @param {string | null} [bindTo]
*/
async function createEsShimLikePackage(packageName, packageImplementation, isStatic, extraDependencies = {}, minimumNodeVersion = '>=12.4.0', bindTo = null) {
const pkg = /** @type {VirtualPackage} */ {
async function createEsShimLikePackage(
packageName: string,
packageImplementation: string,
isStatic: boolean,
extraDependencies: Record<string, string> = {},
minimumNodeVersion = '>=12.4.0',
bindTo: string | null = null
) {
const pkg: VirtualPackage = {
path: path.join(__dirname, 'packages/generated', packageName),
files: {
'implementation.js': `'use strict';\nmodule.exports = ${packageImplementation};\n`,
Expand All @@ -611,7 +624,7 @@ async function createEsShimLikePackage(packageName, packageImplementation, isSta
},
packageJson: {
name: `@nolyfill/${packageName}`,
version: currentPackageJson.version,
version: (await currentPackageJsonPromise).version,
repository: {
type: 'git',
url: 'https://github.com/SukkaW/nolyfill',
Expand All @@ -634,14 +647,15 @@ async function createEsShimLikePackage(packageName, packageImplementation, isSta
return writePackage(pkg);
}

/**
* @param {string} packageName
* @param {string} implementation
* @param {Record<string, string>} [extraDependencies]
* @param {string} [minimumNodeVersion]
*/
async function createSingleFilePackage(packageName, implementation, extraDependencies = {}, minimumNodeVersion = '>=12.4.0') {
const pkg = /** @type {VirtualPackage} */ {
async function createSingleFilePackage(
packageName: string,
implementation: string,
extraDependencies: Record<string, string> = {},
minimumNodeVersion = '>=12.4.0'
) {
const currentPackageJson = await currentPackageJsonPromise;

const pkg:VirtualPackage = {
path: path.join(__dirname, 'packages/generated', packageName),
files: {
'index.js': `'use strict';\n${implementation}\n`
Expand Down Expand Up @@ -684,21 +698,16 @@ function generateDownloadStats() {
}

const ignoredFilesInPackages = new Set(['dist', 'node_modules', 'package.json']);
/**
* @param {VirtualPackage} pkg
*/
async function writePackage(pkg) {
async function writePackage(pkg: VirtualPackage) {
await fsPromises.mkdir(pkg.path, { recursive: true });
let hasChanged = false;

const promises = [];

/** @type {Set<string>} */
const existingFileFullpaths = new Set();
const promises: Array<Promise<void>> = [];
const existingFileFullpaths = new Set<string>();

const ps = new PathScurry(pkg.path);
for await (const file of ps) {
if (file.name[0] === '.' || ignoredFilesInPackages.has(file.name)) {
if (file.name.startsWith('.') || ignoredFilesInPackages.has(file.name)) {
continue;
}

Expand Down Expand Up @@ -750,7 +759,7 @@ async function writePackage(pkg) {

// if the package has changed, bump the version
if (hasChanged) {
pkg.packageJson.version = bumpVersion(pkg.packageJson.version || currentPackageJson.version);
pkg.packageJson.version = bumpVersion(pkg.packageJson.version || (await currentPackageJsonPromise).version);
await fsPromises.writeFile(
packageJsonPath,
`${JSON.stringify(pkg.packageJson, null, 2)}\n`,
Expand All @@ -762,7 +771,7 @@ async function writePackage(pkg) {
}
}

function bumpVersion(version) {
function bumpVersion(version: string) {
// TODO: use semver
const [major, minor, patch] = version.split('.');
return `${major}.${minor}.${+patch + 1}`;
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
"lint": "eslint .",
"build": "turbo run build",
"build:analyze": "ANALYZE=true turbo run build",
"codegen": "node create.cjs",
"codegen": "node -r @swc-node/register create.ts",
"prerelease": "turbo run build",
"release": "bumpp --all --commit=\"release: %s\" --tag=\"%s\""
},
"devDependencies": {
"@jsdevtools/ez-spawn": "^3.0.4",
"@nolyfill/internal": "workspace:*",
"@swc-node/register": "^1.6.7",
"@swc/core": "^1.3.83",
"@types/node": "^20.5.3",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/manual/es-iterator-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"@rollup/plugin-commonjs": "^25.0.4",
"@rollup/plugin-node-resolve": "^15.2.0",
"@rollup/plugin-replace": "^5.0.2",
"@swc/core": "^1.3.76",
"@swc/core": "^1.3.83",
"ljharb-es-iterator-helpers": "npm:es-iterator-helpers@^1.0.14",
"resolve-pkg": "^2.0.0",
"rollup": "^3.28.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/tools/cli/src/all-packages.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Generated by create.cjs */
/* Generated by create.ts */
/* eslint-disable */
export const allPackages = [
"array-buffer-byte-length",
Expand Down
Loading

0 comments on commit b9a7bcf

Please sign in to comment.