Files
wehub-resource-sync da10c3c2c3
Publish Any Commit / build (22) (push) Failing after 1s
Build Extension / build (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:20:35 +08:00

247 lines
7.2 KiB
TypeScript

import * as fs from "node:fs";
import fsPromise from "node:fs/promises";
import path from "node:path";
import { TsconfigPathsPlugin } from "@esbuild-plugins/tsconfig-paths";
import { init, parse } from "es-module-lexer";
import { defineConfig } from "tsup";
import { workerPlugin } from "./worker-plugin";
const DIST_PATH = "./dist";
const USE_CLIENT_DIRECTIVE = `'use client';\n`;
const addDirectivesToChunkFiles = async (readPath: string): Promise<void> => {
try {
if (!fs.existsSync(readPath)) return;
const files = await fsPromise.readdir(readPath);
for (const file of files) {
if (file.endsWith(".mjs") || file.endsWith(".js")) {
const filePath = path.join(readPath, file);
const data = await fsPromise.readFile(filePath, "utf8");
if (data.startsWith(USE_CLIENT_DIRECTIVE)) continue;
await fsPromise.writeFile(filePath, `${USE_CLIENT_DIRECTIVE}${data}`, "utf8");
}
}
} catch (err) {
// oxlint-disable-next-line no-console
console.error("Error:", err);
}
};
const banner = `/**
* Copyright 2025 Aiden Bai, Million Software, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the “Software”), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/`;
void (async () => {
await init;
if (fs.existsSync(DIST_PATH)) {
fs.rmSync(DIST_PATH, { recursive: true });
}
fs.mkdirSync(DIST_PATH, { recursive: true });
const code = fs.readFileSync("./src/core/index.ts", "utf8");
const [_, allExports] = parse(code);
const names: Array<string> = [];
for (const exportItem of allExports) {
names.push(exportItem.n);
}
const createFn = (name: string) => `export let ${name}=()=>{}`;
const createVar = (name: string) => `export let ${name}=undefined`;
let script = "";
for (const name of names) {
if (name[0].toLowerCase() === name[0]) {
script += `${createFn(name)}\n`;
continue;
}
script += `${createVar(name)}\n`;
}
setTimeout(() => {
for (const ext of ["js", "mjs", "global.js"]) {
fs.writeFileSync(`./dist/rsc-shim.${ext}`, script);
}
}, 500);
})();
export default defineConfig([
{
entry: ["./src/auto.ts", "./src/install-hook.ts"],
outDir: DIST_PATH,
banner: {
js: banner,
},
splitting: false,
clean: false,
sourcemap: false,
format: ["iife"],
// Target ES2019 (no `?.`, no `??`) so older babel-loader configs without
// `@babel/preset-env` for optional chaining can still parse the bundle
// (#287, #336).
target: "es2019",
platform: "browser",
treeshake: true,
dts: true,
minify: process.env.NODE_ENV === "production" ? "terser" : false,
env: {
NODE_ENV: process.env.NODE_ENV ?? "development",
},
external: [
"react",
"react-dom",
"next",
"next/navigation",
"react-router",
"react-router-dom",
"@remix-run/react",
],
esbuildPlugins: [workerPlugin],
loader: {
".css": "text",
".worker.js": "text",
},
},
{
entry: [
"./src/index.ts",
"./src/install-hook.ts",
"./src/core/all-environments.ts",
"./src/lite/index.ts",
],
banner: {
js: banner,
},
outDir: DIST_PATH,
splitting: false,
clean: false,
sourcemap: false,
format: ["cjs", "esm"],
target: "es2019",
platform: "browser",
// FIXME: tree shaking removes use client directive
// Info: vercel analytics does the same thing- https://github.com/vercel/analytics/blob/main/packages/web/tsup.config.js
treeshake: false,
dts: true,
watch: process.env.NODE_ENV === "development",
async onSuccess() {
await addDirectivesToChunkFiles(DIST_PATH);
await addDirectivesToChunkFiles(path.join(DIST_PATH, "lite"));
await addDirectivesToChunkFiles(path.join(DIST_PATH, "core"));
},
minify: false,
env: {
NODE_ENV: process.env.NODE_ENV ?? "development",
NPM_PACKAGE_VERSION: JSON.parse(
fs.readFileSync(path.join(__dirname, "../scan", "package.json"), "utf8"),
).version,
},
external: [
"react",
"react-dom",
"next",
"next/navigation",
"react-router",
"react-router-dom",
"@remix-run/react",
"preact",
"@preact/signals",
],
loader: {
".css": "text",
},
esbuildPlugins: [
workerPlugin,
TsconfigPathsPlugin({
tsconfig: path.resolve(__dirname, "./tsconfig.json"),
}),
],
},
{
entry: ["./src/cli.mts"],
outDir: DIST_PATH,
banner: {
js: banner,
},
splitting: false,
clean: false,
sourcemap: false,
format: ["cjs"],
target: "esnext",
platform: "node",
minify: false,
env: {
NODE_ENV: process.env.NODE_ENV ?? "development",
NPM_PACKAGE_VERSION: JSON.parse(
fs.readFileSync(path.join(__dirname, "../scan", "package.json"), "utf8"),
).version,
},
watch: process.env.NODE_ENV === "development",
},
{
entry: [
"./src/react-component-name/index.ts",
"./src/react-component-name/vite.ts",
"./src/react-component-name/webpack.ts",
"./src/react-component-name/esbuild.ts",
"./src/react-component-name/rspack.ts",
"./src/react-component-name/rolldown.ts",
"./src/react-component-name/rollup.ts",
"./src/react-component-name/astro.ts",
"./src/react-component-name/loader.ts",
],
outDir: `${DIST_PATH}/react-component-name`,
splitting: false,
sourcemap: false,
clean: false,
format: ["cjs", "esm"],
target: "esnext",
external: [
"unplugin",
"estree-walker",
"@rollup/pluginutils",
"@babel/types",
"@babel/parser",
"@babel/traverse",
"@babel/generator",
"@babel/core",
"rollup",
"webpack",
"esbuild",
"rspack",
"vite",
],
dts: true,
minify: false,
treeshake: true,
env: {
NODE_ENV: process.env.NODE_ENV || "development",
},
outExtension: ({ format }) => ({
js: format === "esm" ? ".mjs" : ".js",
}),
esbuildOptions: (options, context) => {
options.mainFields = ["module", "main"];
options.conditions = ["import", "require", "node", "default"];
options.format = context.format === "esm" ? "esm" : "cjs";
options.preserveSymlinks = true;
},
},
]);