@prosopo/config 3.3.1 → 3.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
 
2
- > @prosopo/config@3.3.1 build:cjs
2
+ > @prosopo/config@3.3.3 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-production}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
@@ -29,4 +29,4 @@ rendering chunks...
29
29
  dist/cjs/webpack/webpack.config.cjs 5.05 kB
30
30
  dist/cjs/dependencies.cjs 5.22 kB
31
31
  dist/cjs/vite/vite.frontend.config.cjs 7.39 kB
32
- ✓ built in 162ms
32
+ ✓ built in 205ms
@@ -1,11 +1,11 @@
1
1
 
2
- > @prosopo/config@3.3.1 build:tsc
2
+ > @prosopo/config@3.3.3 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 6:47:19 AM - Projects in this build:
5
+ 7:01:32 PM - Projects in this build:
6
6
  * tsconfig.json
7
7
 
8
- 6:47:19 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
8
+ 7:01:32 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
9
9
 
10
- 6:47:19 AM - Building project '/home/runner/work/captcha/captcha/dev/config/tsconfig.json'...
10
+ 7:01:32 PM - Building project '/home/runner/work/captcha/captcha/dev/config/tsconfig.json'...
11
11
 
@@ -1,9 +1,9 @@
1
1
 
2
- > @prosopo/config@3.3.1 build
2
+ > @prosopo/config@3.3.3 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/config@3.3.1 build:cross-env
6
+ > @prosopo/config@3.3.3 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
@@ -32,4 +32,4 @@ rendering chunks...
32
32
  dist/webpack/webpack.config.js 3.81 kB
33
33
  dist/dependencies.js 5.02 kB
34
34
  dist/vite/vite.frontend.config.js 7.27 kB
35
- ✓ built in 230ms
35
+ ✓ built in 245ms
@@ -1,4 +1,4 @@
1
1
 
2
- > @prosopo/config@3.3.1 typecheck
2
+ > @prosopo/config@3.3.3 typecheck
3
3
  > tsc --project tsconfig.types.json
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @prosopo/config
2
2
 
3
+ ## 3.3.3
4
+ ### Patch Changes
5
+
6
+ - e3c399d: chore(deps-dev): bump webpack-dev-server from 5.2.2 to 5.2.5 in /dev/config
7
+ - c523319: chore(deps-dev): bump webpack-dev-server from 5.2.2 to 5.2.5
8
+
9
+ ## 3.3.2
10
+ ### Patch Changes
11
+
12
+ - 7a97bba: chore(deps): bump esbuild from 0.25.9 to 0.28.1
13
+
3
14
  ## 3.3.1
4
15
  ### Patch Changes
5
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/config",
3
- "version": "3.3.1",
3
+ "version": "3.3.3",
4
4
  "description": "Prosopo config library",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "@rollup/plugin-typescript": "11.1.6",
23
23
  "@rollup/plugin-wasm": "6.2.2",
24
24
  "@vitejs/plugin-react": "5.1.0",
25
- "esbuild": "0.25.9",
25
+ "esbuild": "0.28.1",
26
26
  "fast-glob": "3.3.2",
27
27
  "html-webpack-plugin": "5.6.0",
28
28
  "mini-css-extract-plugin": "2.9.1",
@@ -67,11 +67,12 @@
67
67
  "vitest": "3.2.4",
68
68
  "webpack": "5.102.1",
69
69
  "webpack-cli": "5.1.4",
70
- "webpack-dev-server": "5.2.2"
70
+ "webpack-dev-server": "5.2.5"
71
71
  },
72
72
  "repository": {
73
73
  "type": "git",
74
- "url": "git+https://github.com/prosopo/captcha.git"
74
+ "url": "git+https://github.com/prosopo/captcha.git",
75
+ "directory": "dev/config"
75
76
  },
76
77
  "bugs": {
77
78
  "url": "https://github.com/prosopo/captcha/issues"
@@ -0,0 +1,246 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import child_process from "node:child_process";
16
+ import fs from "node:fs";
17
+ import path from "node:path";
18
+ import util from "node:util";
19
+ import type { ProjectReference } from "typescript";
20
+
21
+ const exec = util.promisify(child_process.exec);
22
+ const peerDepsRegex = /UNMET\sOPTIONAL\sDEPENDENCY\s+(@*[\w\-/.]+)@/;
23
+ const depsRegex = /\s+(@*[\w\-/.]+)@/;
24
+
25
+ const getTsconfigDir = (tsConfigPath: string): string =>
26
+ ".json" === path.extname(tsConfigPath)
27
+ ? path.dirname(tsConfigPath)
28
+ : tsConfigPath;
29
+
30
+ async function getPackageDir(packageName: string): Promise<string> {
31
+ let pkg = packageName;
32
+ if (packageName && !packageName.startsWith("@prosopo/")) {
33
+ pkg = `@prosopo/${packageName}`;
34
+ }
35
+ const pkgCommand = `npm list ${pkg} -ap`;
36
+ console.info(`Running command ${pkgCommand}`);
37
+ // get package directory
38
+ const { stdout: packageDir, stderr } = await exec(pkgCommand);
39
+ if (stderr) {
40
+ if (stderr.includes("ERR!")) {
41
+ throw new Error("CONFIG.INVALID_PACKAGE_DIR");
42
+ }
43
+ }
44
+ return packageDir.trim() || path.resolve();
45
+ }
46
+
47
+ /**
48
+ * Resolve the tsconfig path for a reference using the initial tsconfig path and the reference path. If the reference
49
+ * does not contain a tsconfig filename, `tsconfig.json` will be appended to the path.
50
+ * @param initialTsConfigPath
51
+ * @param reference
52
+ */
53
+ function getReferenceTsConfigPath(
54
+ initialTsConfigPath: string,
55
+ reference: ProjectReference,
56
+ ) {
57
+ // remove tsconfig.*.json from the path and get the path to the new directory via the reference path
58
+ let refTSConfigPath = path.resolve(
59
+ getTsconfigDir(initialTsConfigPath),
60
+ reference.path,
61
+ );
62
+ if (!refTSConfigPath.endsWith(".json")) {
63
+ refTSConfigPath = path.resolve(refTSConfigPath, "tsconfig.json");
64
+ }
65
+ return refTSConfigPath;
66
+ }
67
+
68
+ /**
69
+ * Get the tsconfig paths for a package
70
+ * @param tsConfigPath the tsconfig path to start with
71
+ * @param ignorePatterns the patterns to ignore
72
+ * @param tsConfigPaths the tsconfig paths to add to
73
+ * @param includeInitialTsConfig return the initial tsconfig path in the returned array
74
+ */
75
+ export function getTsConfigs(
76
+ tsConfigPath: string,
77
+ ignorePatterns: RegExp[] = [],
78
+ tsConfigPaths: string[] = [],
79
+ includeInitialTsConfig = true,
80
+ ): string[] {
81
+ let tsConfigs = [...tsConfigPaths];
82
+ //TODO use dynamic import with JSON assertion (TS complains that resolveJsonModule is not set)
83
+ const references = JSON.parse(
84
+ fs.readFileSync(tsConfigPath).toString(),
85
+ ).references;
86
+ if (!tsConfigs.includes(tsConfigPath)) {
87
+ if (references) {
88
+ const ignore =
89
+ ignorePatterns && ignorePatterns.length > 0
90
+ ? new RegExp(`${ignorePatterns.join("|")}`)
91
+ : undefined;
92
+ if (includeInitialTsConfig) {
93
+ tsConfigs.push(tsConfigPath);
94
+ }
95
+
96
+ // ignore the packages we don't want to bundle
97
+ const filteredReferences = references.filter(
98
+ (reference: ProjectReference) =>
99
+ ignore ? !ignore.test(reference.path) : false,
100
+ );
101
+ // for each reference, get the tsconfig paths - recursively calling this function
102
+ for (const reference of filteredReferences) {
103
+ // remove tsconfig.*.json from the path and get the path to the new directory via the reference path
104
+ const refTSConfigPath = getReferenceTsConfigPath(
105
+ tsConfigPath,
106
+ reference,
107
+ );
108
+
109
+ // take the reference TS config path (refTSConfigPath) and get the tsconfig paths for it (newTsConfigs),
110
+ // adding both to a distinct list, as there may be duplicates
111
+ const newTsConfigs = getTsConfigs(
112
+ refTSConfigPath,
113
+ ignorePatterns,
114
+ tsConfigs,
115
+ );
116
+ if (newTsConfigs.length > 0) {
117
+ const distinctTsConfigPaths = new Set(tsConfigs.concat(newTsConfigs));
118
+ tsConfigs = [...distinctTsConfigPaths];
119
+ }
120
+ }
121
+ }
122
+ }
123
+ return tsConfigs;
124
+ }
125
+
126
+ /**
127
+ * Get the workspace externals for a package
128
+ * @param tsConfigPath
129
+ * @param ignorePatterns
130
+ */
131
+ export async function getExternalsFromReferences(
132
+ tsConfigPath: string,
133
+ ignorePatterns: RegExp[] = [],
134
+ ): Promise<string[]> {
135
+ const tsConfigPaths = getTsConfigs(tsConfigPath, ignorePatterns, [], false);
136
+ console.debug({ tsConfigPaths });
137
+ const promises: Promise<string>[] = [];
138
+ for (const refTsConfigPath of tsConfigPaths) {
139
+ const packageJsonPath = path.resolve(
140
+ getTsconfigDir(refTsConfigPath),
141
+ "package.json",
142
+ );
143
+ promises.push(
144
+ new Promise((resolve, reject) => {
145
+ // if package.json exists, read it and get the package name
146
+ fs.stat(packageJsonPath, (err) => {
147
+ if (err) {
148
+ reject(err);
149
+ }
150
+ fs.readFile(packageJsonPath, (err, buffer) => {
151
+ if (err) {
152
+ reject(err);
153
+ } else {
154
+ const packageJson = JSON.parse(buffer.toString());
155
+ const pkg = packageJson.name;
156
+ resolve(pkg);
157
+ }
158
+ });
159
+ });
160
+ }),
161
+ );
162
+ }
163
+ const externals = await Promise.all(promises);
164
+ console.debug({ externals });
165
+ return externals;
166
+ }
167
+
168
+ /**
169
+ * Get the dependencies for a package
170
+ * @param packageName
171
+ * @param production
172
+ */
173
+ export async function getDependencies(
174
+ packageName?: string,
175
+ production?: boolean,
176
+ ): Promise<{ dependencies: string[]; optionalPeerDependencies: string[] }> {
177
+ let cmd = production
178
+ ? "npm ls -a --silent --omit=dev --package-lock-only"
179
+ : "npm ls --silent -a --package-lock-only";
180
+
181
+ if (packageName) {
182
+ const packageDir = await getPackageDir(packageName);
183
+ cmd = `cd ${packageDir.trim()} && ${cmd}`;
184
+ console.info(`Running command ${cmd} in ${packageDir}`);
185
+ }
186
+
187
+ let concat = "";
188
+ const { stdout, stderr } = await exec(cmd);
189
+ concat = stdout + stderr;
190
+
191
+ let deps: string[] = [];
192
+ let peerDeps: string[] = [];
193
+ // for each line, check if there is an unmet optional dependency
194
+ for (const line of concat.split("\n")) {
195
+ if (line.includes("UNMET OPTIONAL DEPENDENCY")) {
196
+ // │ │ │ ├── UNMET OPTIONAL DEPENDENCY bufferutil@^4.0.1
197
+ const parts = line.match(peerDepsRegex);
198
+ if (parts && parts.length > 1) {
199
+ peerDeps.push(parts[1] as string);
200
+ }
201
+ } else {
202
+ // │ │ │ ├─┬ mongodb-memory-server-core@8.15.1
203
+ const parts = line.match(depsRegex);
204
+ if (parts && parts.length > 1) {
205
+ deps.push(parts[1] as string);
206
+ }
207
+ }
208
+ }
209
+
210
+ // ensure deps and peerDeps are unique
211
+ deps = [...new Set(deps)];
212
+ peerDeps = [...new Set(peerDeps)];
213
+
214
+ // dedupe and return deps and peer deps
215
+ return {
216
+ dependencies: deps.filter((x, i) => i === deps.indexOf(x)),
217
+ optionalPeerDependencies: peerDeps.filter(
218
+ (x, i) => i === peerDeps.indexOf(x),
219
+ ),
220
+ };
221
+ }
222
+
223
+ /**
224
+ * Filter out the dependencies we don't want
225
+ * @param deps
226
+ * @param filters
227
+ */
228
+ export function filterDependencies(
229
+ deps: string[],
230
+ filters: string[],
231
+ ): { internal: string[]; external: string[] } {
232
+ const depsDeduped = deps.filter((x, i) => i === deps.indexOf(x));
233
+ const depsWithLength = depsDeduped.filter((dep) => dep.length > 0).sort();
234
+ const exclude = new RegExp(`${filters.join("|")}`);
235
+ // filter out the deps we don't want
236
+ const internal: string[] = [];
237
+ const external: string[] = [];
238
+ for (const dep of depsWithLength) {
239
+ if (exclude.test(dep)) {
240
+ external.push(dep);
241
+ } else {
242
+ internal.push(dep);
243
+ }
244
+ }
245
+ return { internal, external };
246
+ }
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ export * from "./vite/index.js";
15
+ export * from "./dependencies.js";
16
+ export * from "./webpack/index.js";
@@ -0,0 +1,45 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ export const nodejsPolarsDirnamePlugin = () => {
16
+ const name = "nodejs-polars-dirname-plugin";
17
+ return {
18
+ name,
19
+ // biome-ignore lint/suspicious/noExplicitAny: TODO not sure of options type
20
+ resolveId(source: string, importer: string | undefined, options: any) {
21
+ // aim for the node_modules/nodejs-polars/bin/native-polars.js file
22
+ if (source.endsWith("nodejs-polars/bin/native-polars.js")) {
23
+ console.debug(name, "resolves", source, "imported by", importer);
24
+ // return the source to indicate this plugin can resolve the import
25
+ return source;
26
+ }
27
+ // return null if this plugin can't resolve the import
28
+ return null;
29
+ },
30
+ transform(code: string, id: string) {
31
+ // aim for the node_modules/nodejs-polars/bin/native-polars.js file
32
+ if (id.endsWith("nodejs-polars/bin/native-polars.js")) {
33
+ // replace all instances of __dirname with the path relative to the output bundle
34
+ console.debug(name, "transform", id);
35
+ const newCode = code.replaceAll(
36
+ "__dirname",
37
+ `new URL(import.meta.url).pathname.split('/').slice(0,-1).join('/')`,
38
+ );
39
+ return newCode;
40
+ }
41
+ // else return the original code (leave code unrelated to nodejs-polars untouched)
42
+ return code;
43
+ },
44
+ };
45
+ };
@@ -0,0 +1,83 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import fs from "node:fs";
16
+ import path from "node:path";
17
+
18
+ export const nodejsPolarsNativeFilePlugin = (
19
+ nodeFiles: string[],
20
+ outDir: string,
21
+ ) => {
22
+ const name = "nodejs-polars-native-file-plugin";
23
+ return {
24
+ name,
25
+ // biome-ignore lint/suspicious/noExplicitAny: TODO not sure of options type
26
+ resolveId(source: string, importer: string | undefined, options: any) {
27
+ // return the id if this plugin can resolve the import
28
+ for (const file of nodeFiles) {
29
+ if (path.basename(source) === path.basename(file)) {
30
+ console.debug(name, "resolves", source, "imported by", importer);
31
+ return source;
32
+ }
33
+ }
34
+ return null; // otherwise return null indicating that this plugin can't handle the import
35
+ },
36
+ transform(code: string, id: string) {
37
+ for (const file of nodeFiles) {
38
+ // rewrite the code to import the .node file
39
+ if (path.basename(id) === path.basename(file)) {
40
+ console.debug(name, "transform", id);
41
+ // https://stackoverflow.com/questions/66378682/nodejs-loading-es-modules-and-native-addons-in-the-same-project
42
+ // this makes the .node file load at runtime from an esm context. .node files aren't native to esm, so we have to create a custom require function to load them. The custom require function is equivalent to the require function in commonjs, thus allowing the .node file to be loaded.
43
+ return `
44
+ // create a custom require function to load .node files
45
+ import { createRequire } from 'module';
46
+ const customRequire = createRequire(import.meta.url)
47
+
48
+ // load the .node file expecting it to be in the same directory as the output bundle
49
+ const content = customRequire('./${file}')
50
+
51
+ // export the content straight back out again
52
+ export default content
53
+ `;
54
+ }
55
+ }
56
+ return code;
57
+ },
58
+ load(id: string) {
59
+ for (const file of nodeFiles) {
60
+ if (path.basename(id) === path.basename(file)) {
61
+ console.debug(name, "load", id);
62
+ // whenever we encounter an import of the .node file, we return an empty string. This makes it look like the .node file is empty to the bundler. This is because we're going to copy the .node file to the output directory ourselves, so we don't want the bundler to include it in the output bundle (also because the bundler can't handle .node files, it tries to read them as js and then complains that it's invalid js)
63
+ const newCode = "";
64
+ return newCode;
65
+ }
66
+ }
67
+ return null;
68
+ },
69
+ // biome-ignore lint/suspicious/noExplicitAny: TODO not sure of options/bundle type
70
+ generateBundle(options: any, bundle: any) {
71
+ for (const fileAbs of nodeFiles) {
72
+ const file = path.basename(fileAbs);
73
+ // copy the .node file to the output directory
74
+ const out = `${outDir}/${file}`;
75
+ const src = `${fileAbs}`;
76
+ console.debug(name, "copy", src, "to", out);
77
+ const nodeFile = fs.readFileSync(src);
78
+ fs.mkdirSync(path.dirname(out), { recursive: true });
79
+ fs.writeFileSync(out, nodeFile);
80
+ }
81
+ },
82
+ };
83
+ };
@@ -0,0 +1,27 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ export function tsNoCheckPlugin() {
15
+ return {
16
+ name: "vite-plugin-ts-nocheck",
17
+ // biome-ignore lint/suspicious/noExplicitAny: TODO not sure of options/bundle type (same as NodejsPolarsNativeFilePlugin)
18
+ generateBundle(_: any, bundle: any) {
19
+ for (const fileName in bundle) {
20
+ const chunk = bundle[fileName];
21
+ if (chunk.type === "chunk" && chunk.code) {
22
+ chunk.code = `// @ts-nocheck\n${chunk.code}`;
23
+ }
24
+ }
25
+ },
26
+ };
27
+ }
@@ -0,0 +1,25 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ export { default as VitePluginCloseAndCopy } from "./vite-plugin-close-and-copy.js";
15
+ export { default as ViteTestConfig } from "./vite.test.config.js";
16
+ export { default as ViteThreadsTestConfig } from "./vite.threads.test.config.js";
17
+ export { default as VitePluginSourceMapExclude } from "./vite-plugin-sourcemap-exclude.js";
18
+ export { default as ViteFrontendConfig } from "./vite.frontend.config.js";
19
+ export { default as ViteBackendConfig } from "./vite.backend.config.js";
20
+ export { default as VitePluginFixAbsoluteImports } from "./vite-plugin-fix-absolute-imports.js";
21
+ export { default as ViteCommonJSConfig } from "./vite.commonjs.config.js";
22
+ export { default as ViteEsmConfig } from "./vite.esm.config.js";
23
+ export { default as VitePluginRemoveUnusedTranslations } from "./vite-plugin-remove-unused-translations.js";
24
+ export * from "./TsNoCheckPlugin.js";
25
+ export { default as VitePluginCopy } from "./vite-plugin-copy.js";
@@ -0,0 +1,13 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
@@ -0,0 +1,76 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import fs from "node:fs";
16
+ import path from "node:path";
17
+ import type { Plugin } from "vite";
18
+
19
+ export interface ClosePluginOptions {
20
+ srcDir: string;
21
+ destDir: string[];
22
+ }
23
+
24
+ /**
25
+ * description: Closes Vite after the bundle has been build. Optionally copies the bundle to a different directory.
26
+ * @param { ClosePluginOptions } options - The options object
27
+ **/
28
+ export default function VitePluginCloseAndCopy(
29
+ options?: ClosePluginOptions,
30
+ ): Plugin {
31
+ const __dirname = path.resolve();
32
+ return {
33
+ name: "close-plugin", // required, will show up in warnings and errors
34
+ buildStart() {
35
+ console.info("Bundle build started");
36
+ },
37
+ buildEnd(error) {
38
+ console.info("Build end");
39
+ if (error) {
40
+ console.log(error);
41
+ console.error(error);
42
+ }
43
+ },
44
+ closeBundle() {
45
+ if (options) {
46
+ for (const destDir of options.destDir) {
47
+ clearOutputDirJS(__dirname, destDir);
48
+ console.info(`Bundle cleared from ${options.destDir}`);
49
+ copyBundle(__dirname, options.srcDir, destDir);
50
+ console.info(`Bundle copied to ${options.destDir}`);
51
+ }
52
+ console.info("Bundle closed");
53
+ }
54
+ },
55
+ };
56
+ }
57
+
58
+ const clearOutputDirJS = (__dirname: string, destDir: string) =>
59
+ fs
60
+ .readdirSync(path.resolve(__dirname, destDir))
61
+ .filter((file) => file.endsWith("js"))
62
+ .map((file) => {
63
+ fs.rmSync(path.resolve(__dirname, destDir, file));
64
+ });
65
+
66
+ const copyBundle = (__dirname: string, srcDir: string, destDir: string) => {
67
+ console.info(
68
+ "Copying",
69
+ path.resolve(__dirname, srcDir),
70
+ "to",
71
+ path.resolve(__dirname, destDir),
72
+ );
73
+ fs.cpSync(path.resolve(__dirname, srcDir), path.resolve(__dirname, destDir), {
74
+ recursive: true,
75
+ });
76
+ };