Skip to content

feat: Build with rollup and lint #3

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

Merged
merged 5 commits into from
Oct 2, 2024
Merged
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
8 changes: 7 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: 'Build & Test'
on: [push, pull_request]
on:
push:
branches:
- main
pull_request:

jobs:
build:
Expand All @@ -12,6 +16,8 @@ jobs:
node-version-file: 'package.json'
- name: Install
run: yarn install
- name: Lint
run: yarn lint
- name: Build
run: yarn build
- name: Run Unit Tests
Expand Down
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"printWidth": 120,
"proseWrap": "always",
"singleQuote": true,
"trailingComma": "all"
}
34 changes: 19 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,44 @@
"license": "MIT",
"exports": {
"rollup": {
"require": "./dist/rollup.js",
"import": "./dist/rollup.mjs"
"require": "./dist/cjs/rollup.js",
"import": "./dist/esm/rollup.mjs"
},
"webpack": {
"require": "./dist/webpack.js",
"import": "./dist/webpack.mjs"
"require": "./dist/cjs/webpack.js",
"import": "./dist/esm/webpack.mjs"
},
"esbuild": {
"require": "./dist/esbuild.js",
"import": "./dist/esbuild.mjs"
"require": "./dist/cjs/esbuild.js",
"import": "./dist/esm/esbuild.mjs"
},
"vite": {
"require": "./dist/vite.js",
"import": "./dist/vite.mjs"
"require": "./dist/cjs/vite.js",
"import": "./dist/esm/vite.mjs"
},
"rspack": {
"require": "./dist/rspack.js",
"import": "./dist/rspack.mjs"
"require": "./dist/cjs/rspack.js",
"import": "./dist/esm/rspack.mjs"
},
"rolldown": {
"require": "./dist/rolldown.js",
"import": "./dist/rolldown.mjs"
"require": "./dist/cjs/rolldown.js",
"import": "./dist/esm/rolldown.mjs"
}
},
"scripts": {
"build": "pkgroll --clean-dist --target=es2018 --target=node14 --sourcemap",
"test": "vitest run ./test/**/*.test.ts"
"build": "rollup --config rollup.config.mjs",
"test": "vitest run ./test/**/*.test.ts",
"lint": "prettier --check \"{src,test}/**/*.{ts,js}\"",
"fix": "prettier --write \"{src,test}/**/*.{ts,js}\""
},
"devDependencies": {
"@rollup/plugin-typescript": "^12.1.0",
"@rspack/cli": "^1.0.8",
"@rspack/core": "^1.0.8",
"@sentry-internal/typescript": "^8.32.0",
"@types/node": "14",
"esbuild": "^0.24.0",
"pkgroll": "^2.5.0",
"prettier": "^3.3.3",
"rolldown": "^0.13.2",
"rollup": "^4.22.5",
"typescript": "^5.6.2",
Expand Down
34 changes: 34 additions & 0 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { builtinModules } from 'node:module';
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
import typescript from '@rollup/plugin-typescript';

const pkgJson = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json')));
const external = [...builtinModules, ...Object.keys(pkgJson.dependencies || {})];

// a simple plugin that adds a package.json file with type: module
const modulePackageJson = {
name: 'package-json-module-type',
generateBundle() {
this.emitFile({ type: 'asset', fileName: 'package.json', source: '{"type": "module"}' });
},
};

function transpileNode(format, input, outDir) {
return {
input,
output: {
sourcemap: true,
strict: false,
format,
dir: outDir,
preserveModules: true,
},
plugins: [typescript({ outDir, tsconfig: './tsconfig.json' }), format === 'esm' ? modulePackageJson : {}],
external,
};
}

const inputs = ['src/esbuild.ts', 'src/rolldown.ts', 'src/rollup.ts', 'src/rspack.ts', 'src/vite.ts', 'src/webpack.ts'];

export default [transpileNode('cjs', inputs, 'dist/cjs'), transpileNode('esm', inputs, 'dist/esm')];
25 changes: 10 additions & 15 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
import * as crypto from "crypto";
import * as crypto from 'crypto';

export const DEFAULT_EXTENSIONS = [".js", ".mjs", ".cjs"];
export const DEFAULT_EXTENSIONS = ['.js', '.mjs', '.cjs'];

export function stringToUUID(str: string): string {
const md5sum = crypto.createHash("md5");
const md5sum = crypto.createHash('md5');
md5sum.update(str);

Check failure

Code scanning / CodeQL

Use of a broken or weak cryptographic algorithm High

A broken or weak cryptographic algorithm
depends on
sensitive data from a call to stringToUUID
.
const md5Hash = md5sum.digest("hex");
const md5Hash = md5sum.digest('hex');

// Position 16 is fixed to either 8, 9, a, or b in the uuid v4 spec (10xx in binary)
// RFC 4122 section 4.4
const v4variant = ["8", "9", "a", "b"][
md5Hash.substring(16, 17).charCodeAt(0) % 4
] as string;
const v4variant = ['8', '9', 'a', 'b'][md5Hash.substring(16, 17).charCodeAt(0) % 4] as string;

return (
md5Hash.substring(0, 8) +
"-" +
'-' +
md5Hash.substring(8, 12) +
"-4" +
'-4' +
md5Hash.substring(13, 16) +
"-" +
'-' +
v4variant +
md5Hash.substring(17, 20) +
"-" +
'-' +
md5Hash.substring(20)
).toLowerCase();
}

export function addDebugIdToSource(input: string, debugId: string): string {
return input.replace(
/\s*(?:\/\/# debugId=.+)?\s*(\/\/# sourceMappingURL=.+)?\s*$/,
`\n//# debugId=${debugId}\n$1`
);
return input.replace(/\s*(?:\/\/# debugId=.+)?\s*(\/\/# sourceMappingURL=.+)?\s*$/, `\n//# debugId=${debugId}\n$1`);
}

export function addDebugIdToSourcemap(input: string, debugId: string): string {
Expand Down
28 changes: 9 additions & 19 deletions src/esbuild.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
import type { PluginBuild } from "esbuild";
import {
addDebugIdToSource,
DEFAULT_EXTENSIONS,
stringToUUID,
addDebugIdToSourcemap,
} from "./common";
import { readFile, writeFile } from "fs/promises";
import * as path from "path";
import type { PluginBuild } from 'esbuild';
import { addDebugIdToSource, DEFAULT_EXTENSIONS, stringToUUID, addDebugIdToSourcemap } from './common';
import { readFile, writeFile } from 'fs/promises';
import * as path from 'path';

export default {
name: "esbuild-plugin-debug-ids",
name: 'esbuild-plugin-debug-ids',
setup({ onEnd, initialOptions }: PluginBuild) {
if (
initialOptions.bundle !== true ||
initialOptions.sourcemap === undefined
) {
if (initialOptions.bundle !== true || initialOptions.sourcemap === undefined) {
return;
}

initialOptions.metafile = true;

onEnd(async (result) => {
const assets = Object.keys(result.metafile?.outputs || {});
const assetsWithCorrectExt = assets.filter((file) =>
DEFAULT_EXTENSIONS.some((ext) => file.endsWith(ext))
);
const assetsWithCorrectExt = assets.filter((file) => DEFAULT_EXTENSIONS.some((ext) => file.endsWith(ext)));

if (assetsWithCorrectExt.length === 0) {
return;
Expand All @@ -39,13 +29,13 @@ export default {
}

const sourcePath = path.join(process.cwd(), key);
const source = await readFile(sourcePath, { encoding: "utf-8" });
const source = await readFile(sourcePath, { encoding: 'utf-8' });
const debugId = stringToUUID(source);
const updatedSource = addDebugIdToSource(source, debugId);
await writeFile(sourcePath, updatedSource);

const sourcemapPath = path.join(process.cwd(), sourcemapKey);
const sourcemap = await readFile(sourcemapPath, { encoding: "utf-8" });
const sourcemap = await readFile(sourcemapPath, { encoding: 'utf-8' });
const updatedSourcemap = addDebugIdToSourcemap(sourcemap, debugId);
await writeFile(sourcemapPath, updatedSourcemap);
});
Expand Down
2 changes: 1 addition & 1 deletion src/rolldown.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import rollupPlugin from "./rollup";
import rollupPlugin from './rollup';

export default rollupPlugin;
59 changes: 27 additions & 32 deletions src/rollup.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { OutputAsset, OutputChunk, Plugin } from "rollup";
import {
addDebugIdToSourcemap,
addDebugIdToSource,
stringToUUID,
DEFAULT_EXTENSIONS,
} from "./common";
import { OutputAsset, OutputChunk, Plugin } from 'rollup';
import { addDebugIdToSourcemap, addDebugIdToSource, stringToUUID, DEFAULT_EXTENSIONS } from './common';
import { TextDecoder } from 'util';

function getString(input: string | Uint8Array): string {
if (typeof input === 'string') {
return input;
}

return new TextDecoder().decode(input);
}

export default function debugIds(): Plugin {
return {
name: "rollup-plugin-debug-ids",
generateBundle: function (
_,
bundle: { [fileName: string]: OutputAsset | OutputChunk }
) {
name: 'rollup-plugin-debug-ids',
generateBundle: function (_, bundle: { [fileName: string]: OutputAsset | OutputChunk }) {
for (const [key, value] of Object.entries(bundle)) {
// We only add debugId where there is a linked sourcemap file
if (!("sourcemapFileName" in value) || !value.sourcemapFileName) {
if (!('sourcemapFileName' in value) || !value.sourcemapFileName) {
continue;
}

Expand All @@ -26,32 +27,26 @@ export default function debugIds(): Plugin {

// Check we have a sourcemap in the output and it has source property
const sourceMapFile = bundle[value.sourcemapFileName];
if (!sourceMapFile || !("source" in sourceMapFile)) {
if (!sourceMapFile || !('source' in sourceMapFile)) {
continue;
}

const debugId = stringToUUID(value.code);
value.code = addDebugIdToSource(value.code, debugId);
sourceMapFile.source = addDebugIdToSourcemap(
sourceMapFile.source.toString(),
debugId
);
sourceMapFile.source = addDebugIdToSourcemap(sourceMapFile.source.toString(), debugId);

// vite has plugins that run after us which can modify the sourcemap so we
// vite has a plugin that runs after us which can modify the sourcemap so we
// proxy the sourceMapFile to re-add the debugId if the source gets set again
bundle[value.sourcemapFileName] = new Proxy(
bundle[value.sourcemapFileName],
{
set: function (target, prop, value) {
if (prop === "source") {
target[prop] = addDebugIdToSourcemap(value, debugId);
} else {
target[prop] = value;
}
return true;
},
}
);
bundle[value.sourcemapFileName] = new Proxy(bundle[value.sourcemapFileName] as OutputAsset, {
set: function <K extends keyof OutputAsset>(target: OutputAsset, prop: K, value: OutputAsset[K]) {
if (prop === 'source') {
(target as any)[prop] = addDebugIdToSourcemap(getString(value as string | Uint8Array), debugId);
} else {
target[prop] = value;
}
return true;
},
}) as OutputAsset;
}
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/rspack.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { DebugIdWebpackPlugin } from "./webpack";
import { DebugIdWebpackPlugin } from './webpack';

export class DebugIdRspackPlugin extends DebugIdWebpackPlugin {}
10 changes: 5 additions & 5 deletions src/vite.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import rollupPlugin from "./rollup";
import { Plugin } from "vite";
import rollupPlugin from './rollup';
import { Plugin } from 'vite';

export default function debugIds(): Plugin {
return {
...rollupPlugin(),
name: "vite-plugin-debug-ids",
apply: "build",
enforce: "post",
name: 'vite-plugin-debug-ids',
apply: 'build',
enforce: 'post',
};
}
29 changes: 9 additions & 20 deletions src/webpack.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import type { Compiler } from "webpack";
import {
DEFAULT_EXTENSIONS,
addDebugIdToSource,
stringToUUID,
addDebugIdToSourcemap,
} from "./common";
import type { Compiler } from 'webpack';
import { DEFAULT_EXTENSIONS, addDebugIdToSource, stringToUUID, addDebugIdToSourcemap } from './common';

const PLUGIN_NAME = "DebugIdWebpackPlugin";
const PLUGIN_NAME = 'DebugIdWebpackPlugin';

export class DebugIdWebpackPlugin {
apply(compiler: Compiler) {
Expand All @@ -28,8 +23,8 @@ export class DebugIdWebpackPlugin {
stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE,
},
() => {
const assetsWithCorrectExt = Object.keys(compilation.assets).filter(
(file) => DEFAULT_EXTENSIONS.some((ext) => file.endsWith(ext))
const assetsWithCorrectExt = Object.keys(compilation.assets).filter((file) =>
DEFAULT_EXTENSIONS.some((ext) => file.endsWith(ext)),
);

for (const key of assetsWithCorrectExt) {
Expand All @@ -42,7 +37,7 @@ export class DebugIdWebpackPlugin {

if (Array.isArray(sourceAsset.info.related.sourceMap)) {
throw new Error(
"Oh dear, we cannot handle arrays of source maps yet! Please open an issue with an example."
'DebugIdWebpackPlugin: Oh dear, we cannot handle arrays of source maps yet! Please open an issue with an example.',
);
}

Expand All @@ -59,17 +54,11 @@ export class DebugIdWebpackPlugin {

compilation.updateAsset(key, new RawSource(updatedSource));

const updatedSourcemap = addDebugIdToSourcemap(
sourcemapAsset.source.source().toString(),
debugId
);
const updatedSourcemap = addDebugIdToSourcemap(sourcemapAsset.source.source().toString(), debugId);

compilation.updateAsset(
sourcemapKey,
new RawSource(updatedSourcemap)
);
compilation.updateAsset(sourcemapKey, new RawSource(updatedSourcemap));
}
}
},
);
});
}
Expand Down
Loading