From fa6b99fcba9460c5c4a10d8e5e3581172bce8da5 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 03:21:54 +0000 Subject: [PATCH 1/2] Update from copier (2026-04-10T03:21:54) Signed-off-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .copier-answers.yaml | 2 +- js/build.mjs | 82 +++++++++--------------------------------- js/package.json | 5 ++- js/tools/bundle.mjs | 59 ++++++++++++++++++++++++++++++ js/tools/css.mjs | 52 +++++++++++++++++++++++++++ js/tools/externals.mjs | 18 ++++++++++ js/tools/getarg.mjs | 2 +- js/tools/html.mjs | 0 8 files changed, 149 insertions(+), 71 deletions(-) create mode 100644 js/tools/bundle.mjs create mode 100644 js/tools/css.mjs create mode 100644 js/tools/externals.mjs create mode 100644 js/tools/html.mjs diff --git a/.copier-answers.yaml b/.copier-answers.yaml index f472638..3b639ce 100644 --- a/.copier-answers.yaml +++ b/.copier-answers.yaml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 9b579a3 +_commit: 9498b78 _src_path: https://github.com/python-project-templates/base.git add_docs: true add_extension: cppjswasm diff --git a/js/build.mjs b/js/build.mjs index 4877fa3..551bf34 100644 --- a/js/build.mjs +++ b/js/build.mjs @@ -1,92 +1,42 @@ -import { NodeModulesExternal } from "@finos/perspective-esbuild-plugin/external.js"; -import { build } from "@finos/perspective-esbuild-plugin/build.js"; -import { transform } from "lightningcss"; +import { bundle } from "./tools/bundle.mjs"; +import { bundle_css } from "./tools/css.mjs"; +import { node_modules_external } from "./tools/externals.mjs"; import { getarg } from "./tools/getarg.mjs"; + +import { transform } from "lightningcss"; import fs from "fs"; import cpy from "cpy"; -const DEBUG = getarg("--debug"); - -const COMMON_DEFINE = { - global: "window", - "process.env.DEBUG": `${DEBUG}`, -}; - -const BUILD = [ +const BUNDLES = [ { - define: COMMON_DEFINE, entryPoints: ["src/ts/index.ts"], - plugins: [NodeModulesExternal()], - format: "esm", - loader: { - ".css": "text", - ".html": "text", - }, + plugins: [node_modules_external()], outfile: "dist/esm/index.js", }, { - define: COMMON_DEFINE, entryPoints: ["src/ts/index.ts"], - plugins: [], - format: "esm", - loader: { - ".css": "text", - ".html": "text", - }, outfile: "dist/cdn/index.js", }, ]; -async function compile_css() { - const process_path = (path) => { - const outpath = path.replace("src/css", "dist/css"); - fs.mkdirSync(outpath, { recursive: true }); - - fs.readdirSync(path, { withFileTypes: true }).forEach((entry) => { - const input = `${path}/${entry.name}`; - const output = `${outpath}/${entry.name}`; - - if (entry.isDirectory()) { - process_path(input); - } else if (entry.isFile() && entry.name.endsWith(".css")) { - const source = fs.readFileSync(input); - const { code } = transform({ - filename: entry.name, - code: source, - minify: !DEBUG, - sourceMap: false, - }); - fs.writeFileSync(output, code); - } - }); - }; +async function build() { + // Bundle css + await bundle_css(); - process_path("src/css"); -} - -async function copy_html() { + // Copy HTML fs.mkdirSync("dist/html", { recursive: true }); cpy("src/html/*", "dist/html"); - // also copy to top level cpy("src/html/*", "dist/"); -} -async function copy_img() { + // Copy images fs.mkdirSync("dist/img", { recursive: true }); cpy("src/img/*", "dist/img"); -} -async function copy_to_python() { + await Promise.all(BUNDLES.map(bundle)).catch(() => process.exit(1)); + + // Copy from dist to python fs.mkdirSync("../python_template_cppjswasm/extension", { recursive: true }); cpy("dist/**/*", "../python_template_cppjswasm/extension"); } -async function build_all() { - await compile_css(); - await copy_html(); - await copy_img(); - await Promise.all(BUILD.map(build)).catch(() => process.exit(1)); - await copy_to_python(); -} - -build_all(); +build(); diff --git a/js/package.json b/js/package.json index 8c1a4ca..f6420a4 100644 --- a/js/package.json +++ b/js/package.json @@ -48,10 +48,9 @@ }, "dependencies": {}, "devDependencies": { - "@finos/perspective-esbuild-plugin": "^3.2.1", - "@playwright/test": "^1.59.0", + "@playwright/test": "^1.59.1", "cpy": "^13.2.1", - "esbuild": "^0.27.2", + "esbuild": "^0.27.3", "lightningcss": "^1.29.3", "http-server": "^14.1.1", "nodemon": "^3.1.10", diff --git a/js/tools/bundle.mjs b/js/tools/bundle.mjs new file mode 100644 index 0000000..b417871 --- /dev/null +++ b/js/tools/bundle.mjs @@ -0,0 +1,59 @@ +import { getarg } from "./getarg.mjs"; +import esbuild from "esbuild"; + +const DEBUG = getarg("--debug"); + +const CUTOFF_PERCENT = 0.02; + +const COMMON_DEFINE = { + global: "window", + "process.env.DEBUG": `${DEBUG}`, +}; + +const COMMON_LOADER = { + ".css": "text", + ".html": "text", + ".jsx": "jsx", + ".png": "file", + ".ttf": "file", + ".wasm": "file", +}; + +const DEFAULT_BUILD = { + target: ["es2022"], + bundle: true, + format: "esm", + minify: DEBUG, + sourcemap: true, + metafile: true, + entryNames: "[name]", + chunkNames: "[name]", + assetNames: "[name]", + define: COMMON_DEFINE, + loader: COMMON_LOADER, + plugins: [], +}; + +export const bundle = async (config) => { + const result = await esbuild.build({ + ...DEFAULT_BUILD, + ...config, + }); + + if (result.metafile) { + for (const output of Object.keys(result.metafile.outputs)) { + const { inputs, bytes } = result.metafile.outputs[output]; + for (const input of Object.keys(inputs)) { + if (inputs[input].bytesInOutput / bytes < CUTOFF_PERCENT) { + delete inputs[input]; + } + } + } + + const text = await esbuild.analyzeMetafile(result.metafile, { + color: true, + }); + + console.log(text); + } +}; diff --git a/js/tools/css.mjs b/js/tools/css.mjs new file mode 100644 index 0000000..4ac3594 --- /dev/null +++ b/js/tools/css.mjs @@ -0,0 +1,52 @@ +import { getarg } from "./getarg.mjs"; + +import { bundleAsync } from "lightningcss"; +import fs from "fs"; +import path from "path"; + +const DEBUG = getarg("--debug"); + +const DEFAULT_RESOLVER = { + resolve(specifier, originatingFile) { + if (/^https?:\/\//.test(specifier)) { + return specifier; + } + + if (specifier.startsWith("perspective-viewer-")) { + const viewerCssDir = path.resolve( + "node_modules/@perspective-dev/viewer/dist/css", + ); + const normalized = specifier.replace(/^perspective-viewer-/, ""); + const normalizedPath = path.join(viewerCssDir, normalized); + if (fs.existsSync(normalizedPath)) { + return normalizedPath; + } + return path.join(viewerCssDir, specifier); + } + return path.resolve(path.dirname(originatingFile), specifier); + }, +}; + +const bundle_one = async (file, resolver) => { + const { code } = await bundleAsync({ + filename: path.resolve(file), + minify: !DEBUG, + sourceMap: false, + resolver: resolver || DEFAULT_RESOLVER, + }); + const outName = path.basename(file); + fs.mkdirSync("./dist", { recursive: true }); + fs.writeFileSync(path.join("./dist", outName), code); +}; + +export const bundle_css = async (root = "src/css/index.css", resolver = null) => { + const resolved = path.resolve(root); + if (fs.statSync(resolved).isDirectory()) { + const files = fs.readdirSync(resolved).filter((f) => f.endsWith(".css")); + for (const file of files) { + await bundle_one(path.join(root, file), resolver); + } + } else { + await bundle_one(root, resolver); + } +} diff --git a/js/tools/externals.mjs b/js/tools/externals.mjs new file mode 100644 index 0000000..0ee4835 --- /dev/null +++ b/js/tools/externals.mjs @@ -0,0 +1,18 @@ +export const node_modules_external = (whitelist) => { + function setup(build) { + build.onResolve({ filter: /^[A-Za-z0-9\@]/ }, (args) => { + if (!whitelist || !args.path.startsWith(whitelist)) { + return { + path: args.path, + external: true, + namespace: "skip-node-modules", + }; + } + }); + } + + return { + name: "node_modules_external", + setup, + }; +}; diff --git a/js/tools/getarg.mjs b/js/tools/getarg.mjs index 30793a7..9cfe88c 100644 --- a/js/tools/getarg.mjs +++ b/js/tools/getarg.mjs @@ -20,4 +20,4 @@ export const getarg = (flag, ...args) => { }) .join(" "); } - }; \ No newline at end of file + }; diff --git a/js/tools/html.mjs b/js/tools/html.mjs new file mode 100644 index 0000000..e69de29 From 6b3b4e80eb3164f61ee46b425d0e41569a9cae57 Mon Sep 17 00:00:00 2001 From: Tim Paine <3105306+timkpaine@users.noreply.github.com> Date: Thu, 9 Apr 2026 23:27:22 -0400 Subject: [PATCH 2/2] update lockfile --- js/pnpm-lock.yaml | 111 +--------------------------------------------- 1 file changed, 2 insertions(+), 109 deletions(-) diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index f4bf28d..aa803af 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -8,17 +8,14 @@ importers: .: devDependencies: - '@finos/perspective-esbuild-plugin': - specifier: ^3.2.1 - version: 3.2.1 '@playwright/test': - specifier: ^1.59.0 + specifier: ^1.59.1 version: 1.59.1 cpy: specifier: ^13.2.1 version: 13.2.1 esbuild: - specifier: ^0.27.2 + specifier: ^0.27.3 version: 0.27.3 http-server: specifier: ^14.1.1 @@ -197,9 +194,6 @@ packages: cpu: [x64] os: [win32] - '@finos/perspective-esbuild-plugin@3.2.1': - resolution: {integrity: sha512-6EqacFm5rGA0EtzD2p9RuxtVLEci9AEC4NPiOCpqFdgxxX8Msv8LlL7Ml3opxyaEeKpndVsLFdOD5U+PNaaa+A==} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -294,10 +288,6 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -430,10 +420,6 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -780,38 +766,12 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - nodemon@3.1.11: resolution: {integrity: sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==} engines: {node: '>=10'} @@ -1083,11 +1043,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1096,9 +1051,6 @@ packages: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -1141,17 +1093,11 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -1172,9 +1118,6 @@ packages: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - snapshots: '@esbuild/aix-ppc64@0.27.3': @@ -1255,13 +1198,6 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@finos/perspective-esbuild-plugin@3.2.1': - dependencies: - node-fetch: 2.7.0 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1373,8 +1309,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chownr@2.0.0: {} - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -1594,10 +1528,6 @@ snapshots: dependencies: is-callable: 1.2.7 - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - fsevents@2.3.2: optional: true @@ -1937,27 +1867,10 @@ snapshots: minimist@1.2.8: {} - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - - minipass@5.0.0: {} - - minizlib@2.1.2: - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - - mkdirp@1.0.4: {} - ms@2.1.3: {} nice-try@1.0.5: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - nodemon@3.1.11: dependencies: chokidar: 3.6.0 @@ -2269,23 +2182,12 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tar@6.2.1: - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 touch@3.1.1: {} - tr46@0.0.3: {} - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -2343,17 +2245,10 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - webidl-conversions@3.0.1: {} - whatwg-encoding@2.0.0: dependencies: iconv-lite: 0.6.3 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -2398,5 +2293,3 @@ snapshots: which@1.3.1: dependencies: isexe: 2.0.0 - - yallist@4.0.0: {}