@tsparticles/cli 3.3.1 → 3.3.2

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.
Files changed (40) hide show
  1. package/.github/dependabot.yml +7 -0
  2. package/.planning/codebase/ARCHITECTURE.md +83 -51
  3. package/.planning/codebase/CONCERNS.md +61 -58
  4. package/.planning/codebase/CONVENTIONS.md +47 -52
  5. package/.planning/codebase/INTEGRATIONS.md +26 -17
  6. package/.planning/codebase/STACK.md +37 -31
  7. package/.planning/codebase/STRUCTURE.md +87 -53
  8. package/.planning/codebase/TESTING.md +80 -62
  9. package/dist/build/build-distfiles.js +14 -13
  10. package/dist/build/build-diststats.js +8 -7
  11. package/dist/build/build-prettier.js +16 -15
  12. package/dist/build/build-tsc.js +4 -3
  13. package/dist/build/build.js +10 -8
  14. package/dist/cli.js +3 -3
  15. package/dist/create/plugin/create-plugin.js +4 -3
  16. package/dist/create/preset/create-preset.js +4 -3
  17. package/dist/create/shape/create-shape.js +4 -3
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/utils/file-utils.js +7 -6
  20. package/dist/utils/template-utils.js +4 -3
  21. package/files/empty-project/package.json +7 -7
  22. package/files/empty-project/webpack.config.js +11 -11
  23. package/package.json +9 -11
  24. package/src/build/build-distfiles.ts +15 -14
  25. package/src/build/build-diststats.ts +8 -8
  26. package/src/build/build-prettier.ts +16 -15
  27. package/src/build/build-tsc.ts +4 -3
  28. package/src/build/build.ts +10 -10
  29. package/src/cli.ts +3 -3
  30. package/src/create/plugin/create-plugin.ts +4 -3
  31. package/src/create/preset/create-preset.ts +4 -3
  32. package/src/create/shape/create-shape.ts +4 -3
  33. package/src/utils/file-utils.ts +7 -6
  34. package/src/utils/template-utils.ts +4 -3
  35. package/tests/create-plugin.test.ts +25 -25
  36. package/tests/create-preset.test.ts +25 -25
  37. package/tests/create-shape.test.ts +25 -25
  38. package/tests/file-utils.test.ts +87 -78
  39. package/tests/tsconfig.json +12 -11
  40. package/tsconfig.json +52 -53
@@ -1,138 +1,156 @@
1
1
  # Testing Patterns
2
2
 
3
- **Analysis Date:** 2026-03-08
3
+ **Analysis Date:** 2026-03-10
4
4
 
5
5
  ## Test Framework
6
6
 
7
- **Runner:**
7
+ Runner:
8
8
 
9
- - Vitest (`vitest`) - configured in `vitest.config.ts` with `environment: "node"` and `include: ["tests/**/*.test.ts"]`.
10
-
11
- Config: `vitest.config.ts`
9
+ - Vitest (see `package.json` devDependencies `vitest` and `vitest.config.ts`).
10
+ - Config file: `vitest.config.ts` (sets `globals: true`, `environment: "node"`, `include: ["tests/**/*.test.ts"]`).
12
11
 
13
12
  Run Commands:
14
13
 
15
14
  ```bash
16
- pnpm test # Run all tests (runs `vitest run` as defined in package.json)
17
- pnpm test --watch # Run in watch mode (Vitest supports --watch)
18
- pnpm test --coverage # Coverage if configured via vitest options (not explicitly configured here)
15
+ pnpm test # Runs: `vitest run` (non-watch)
16
+ pnpm run test # Alias to the same command
19
17
  ```
20
18
 
21
19
  ## Test File Organization
22
20
 
23
21
  Location:
24
22
 
25
- - Tests live under `tests/` at the repo root: `tests/*.test.ts` (e.g., `tests/create-shape.test.ts`, `tests/file-utils.test.ts`).
23
+ - Tests live in the `tests/` directory at project root.
24
+ - Files: `tests/create-shape.test.ts`, `tests/create-preset.test.ts`, `tests/create-plugin.test.ts`, `tests/file-utils.test.ts`, `tests/string-utils.test.ts`.
25
+ - Pattern: tests are colocated under a top-level `tests/` folder rather than next to source files.
26
26
 
27
27
  Naming:
28
28
 
29
- - Test files use the pattern `<feature>.test.ts` (Vitest `include` config picks `tests/**/*.test.ts`).
29
+ - Pattern: `*.test.ts` suffix for test files (see `vitest.config.ts` include pattern).
30
30
 
31
31
  Structure:
32
32
 
33
33
  ```
34
34
  tests/
35
- ├── create-shape.test.ts
36
- ├── create-preset.test.ts
37
- ├── create-plugin.test.ts
38
- ├── file-utils.test.ts
39
- └── string-utils.test.ts
35
+ ├── <feature>.test.ts # top-level test file for a single module/feature
40
36
  ```
41
37
 
42
- ## Test Structure
38
+ ## Test Structure and Patterns
43
39
 
44
- Suite Organization (example from `tests/create-shape.test.ts`):
40
+ Suite Organization:
45
41
 
46
- ```ts
47
- import { describe, it, expect } from "vitest";
48
- import { createShapeTemplate } from "../src/create/shape/create-shape.js";
42
+ - Tests use `describe` blocks to group scenarios and `it` for assertions (Vitest globals enabled). Example: `tests/file-utils.test.ts`.
49
43
 
50
- describe("create-shape", () => {
51
- it("should have created the shape project", async () => {
52
- // arrange: compute destDir
53
- // act: call createShapeTemplate
54
- // assert: read package.json and assert properties using fs-extra
55
- });
44
+ Setup / Teardown:
45
+
46
+ - Tests frequently perform async setup at the top-level of `describe` by awaiting operations before `it` blocks. Example: in `tests/file-utils.test.ts` the `baseDir` is created with `await fs.ensureDir(baseDir)` before assertions.
47
+ - Teardown uses `afterAll` to remove temporary test artifacts. Example: `afterAll(async () => { await fs.remove(baseDir); });` in `tests/file-utils.test.ts`.
48
+
49
+ Assertions:
50
+
51
+ - Vitest's `expect` is used with matchers like `toBe`.
52
+
53
+ Async Tests:
54
+
55
+ - Most IO-heavy tests are `async` and use `await`. Pattern:
56
+
57
+ ```typescript
58
+ it("does something async", async () => {
59
+ const result = await someAsyncFunction();
60
+ expect(result).toBe(...);
56
61
  });
57
62
  ```
58
63
 
59
- Patterns:
64
+ Error Testing Pattern:
60
65
 
61
- - Tests create temporary directories under `tests/tmp-files` and remove them after assertions (`fs-extra` used to clean up).
62
- - Tests use actual file system operations to verify template creation (integration-style unit tests).
66
+ - When verifying exceptions, tests use try/catch with a boolean flag and assert the flag at the end. Example in `tests/file-utils.test.ts`:
63
67
 
64
- Setup/Teardown:
68
+ ```typescript
69
+ let ex = false;
70
+ try {
71
+ await getDestinationDir(path.join("tmp-files", "baz"));
72
+ } catch {
73
+ ex = true;
74
+ }
75
+ expect(ex).toBe(true);
76
+ ```
65
77
 
66
- - Tests manually create and remove directories within each test case (no global setup file detected).
78
+ Prefer using `await expect(...).rejects.toThrow()` for clearer intent when adding tests.
67
79
 
68
80
  ## Mocking
69
81
 
70
- Framework: Vitest built-in mocking utilities are available but not heavily used in current tests.
71
-
72
- Patterns:
82
+ Framework:
73
83
 
74
- - Tests primarily exercise filesystem operations without mocking `fs-extra` or child processes. When external commands are invoked, the code checks for the presence of `npm` using `lookpath` before running `exec` which avoids executing if not present.
84
+ - No mocking libraries observed; tests perform filesystem operations against a temporary directory (`tests/tmp-files`) and rely on actual `fs-extra` operations.
75
85
 
76
- What to Mock:
86
+ Patterns:
77
87
 
78
- - When adding unit tests for functions that call `exec` or modify the environment, mock `child_process.exec` or `lookpath` to avoid running external processes.
88
+ - Tests use real file operations (create files, write content, call functions under test, assert file contents). Example: `tests/file-utils.test.ts` writes files into `tmp-files` and later reads them.
79
89
 
80
- What NOT to Mock:
90
+ What to mock / not to mock:
81
91
 
82
- - For integration-style tests that verify file scaffolding, prefer real `fs` operations in a temporary directory to validate end-to-end behavior.
92
+ - Current tests intentionally avoid mocking to validate filesystem interactions. Continue to avoid mocking for these utilities unless external network/long-running processes are involved (e.g., `exec` calls in `template-utils.ts` could be mocked if tests should not run `npm install` or `npm run build`).
83
93
 
84
94
  ## Fixtures and Factories
85
95
 
86
96
  Test Data:
87
97
 
88
- - Tests programmatically generate temporary directories under `tests/tmp-files` and use template functions to create artifacts. No centralized fixtures directory is present.
98
+ - Tests create temporary files under `tests/tmp-files` using `fs-extra`. Example: `tests/create-shape.test.ts` writes to `tests/tmp-files/foo-shape` and later removes it.
89
99
 
90
100
  Location:
91
101
 
92
- - Temporary test artifacts are created in `tests/tmp-files` during tests and cleaned up by tests (see `tests/create-shape.test.ts`).
102
+ - Temporary test artifacts are written under `tests/tmp-files/` and removed by test code or CI before/after runs (CI workflow runs `rm -rf tests/tmp-files`). See `.github/workflows/node.js-ci.yml`.
93
103
 
94
104
  ## Coverage
95
105
 
96
- Requirements: None enforced in repo. CI runs `pnpm test` but coverage thresholds are not configured.
97
-
98
- View Coverage:
99
-
100
- ```bash
106
+ Coverage tool: Not enforced in repo (no explicit coverage script), but `.nyc_output` directory exists suggesting past use of NYC. No CI step collects coverage.
101
107
 
102
- ```
108
+ To run coverage (suggested): add a script using `vitest run --coverage` and configure thresholds in `package.json` if required.
103
109
 
104
110
  ## Test Types
105
111
 
106
112
  Unit Tests:
107
113
 
108
- - Small utilities tested (e.g., `tests/file-utils.test.ts`, `tests/string-utils.test.ts`).
114
+ - Scope: small, deterministic units that interact with filesystem helpers and template generation functions. Examples: `tests/string-utils.test.ts`, `tests/file-utils.test.ts`.
109
115
 
110
- Integration Tests:
116
+ Integration-ish Tests:
111
117
 
112
- - Template creation tests behave like integration tests, performing file operations and validating outputs (`tests/create-*.test.ts`).
118
+ - Scope: template creation tests (`tests/create-*.test.ts`) copy files and run `runInstall`/`runBuild` indirectly; these can execute `npm` commands if present (templating functions call `runInstall` and `runBuild` which execute `npm` if `lookpath('npm')` returns true). These tests currently run in CI where `pnpm install` is executed and `npm` may be present.
113
119
 
114
120
  E2E Tests:
115
121
 
116
122
  - Not used.
117
123
 
118
- ## Common Patterns
124
+ ## Common Patterns and Recommendations
119
125
 
120
- Async Testing:
126
+ 1. Use `afterAll` to clean up filesystem artifacts (example: `tests/file-utils.test.ts` removes `baseDir`).
127
+ 2. Prefer `await expect(promise).rejects.toThrow()` for negative tests instead of boolean-flag try/catch pattern.
128
+ 3. Keep filesystem-based tests under `tests/tmp-files` and ensure CI cleans them before runs (CI step already removes `tests/tmp-files`). See `.github/workflows/node.js-ci.yml` lines 44-46 and 84-86.
129
+ 4. If tests should avoid running `npm install`/`npm run build` during template creation, add a test flag or mock `lookpath`/`exec` in `src/utils/template-utils.ts` to bypass `runInstall`/`runBuild` during tests.
121
130
 
122
- ```ts
123
- it("does async work", async () => {
124
- await expect(someAsyncFn()).resolves.toBeTruthy();
125
- });
126
- ```
131
+ ## Example Test Template (observed pattern)
132
+
133
+ ```typescript
134
+ import { describe, it, expect } from "vitest";
135
+ import fs from "fs-extra";
136
+ import path from "node:path";
137
+ import { someFunction } from "../src/utils/some.ts";
127
138
 
128
- Error Testing:
139
+ describe("someFunction", () => {
140
+ it("behaves correctly", async () => {
141
+ const dest = path.join(__dirname, "tmp-files", "some");
142
+ await fs.ensureDir(dest);
129
143
 
130
- ```ts
131
- it("throws on bad input", async () => {
132
- await expect(badAsync()).rejects.toThrow();
144
+ await someFunction(dest);
145
+
146
+ const data = await fs.readFile(path.join(dest, "file.txt"), "utf8");
147
+ expect(data).toBe("expected");
148
+
149
+ await fs.remove(dest);
150
+ });
133
151
  });
134
152
  ```
135
153
 
136
154
  ---
137
155
 
138
- _Testing analysis: 2026-03-08_
156
+ _Testing analysis: 2026-03-10_
@@ -1,4 +1,5 @@
1
- import fs from "fs-extra";
1
+ import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
2
3
  import klaw from "klaw";
3
4
  import path from "node:path";
4
5
  /**
@@ -12,7 +13,7 @@ export async function buildDistFiles(basePath, silent) {
12
13
  }
13
14
  let res;
14
15
  try {
15
- const pkgInfo = JSON.parse((await fs.readFile(path.join(basePath, "package.json"))).toString()), libPackage = path.join(basePath, "package.dist.json"), distPath = path.join(basePath, pkgInfo.publishConfig?.directory ?? "dist"), data = await fs.readFile(libPackage), text = data.toString(), libObj = JSON.parse(text);
16
+ const pkgInfo = JSON.parse((await readFile(path.join(basePath, "package.json"))).toString()), libPackage = path.join(basePath, "package.dist.json"), distPath = path.join(basePath, pkgInfo.publishConfig?.directory ?? "dist"), data = await readFile(libPackage), text = data.toString(), libObj = JSON.parse(text);
16
17
  libObj["version"] = pkgInfo.version;
17
18
  if (pkgInfo.dependencies) {
18
19
  libObj["dependencies"] = JSON.parse(JSON.stringify(pkgInfo.dependencies).replaceAll("workspace:", ""));
@@ -21,7 +22,7 @@ export async function buildDistFiles(basePath, silent) {
21
22
  libObj["peerDependencies"] = JSON.parse(JSON.stringify(pkgInfo.peerDependencies).replaceAll("workspace:", ""));
22
23
  }
23
24
  const jsonIndent = 2;
24
- await fs.writeFile(libPackage, `${JSON.stringify(libObj, undefined, jsonIndent)}\n`, "utf8");
25
+ await writeFile(libPackage, `${JSON.stringify(libObj, undefined, jsonIndent)}\n`, "utf8");
25
26
  if (!silent) {
26
27
  console.log(`package.dist.json updated successfully to version ${pkgInfo.version}`);
27
28
  }
@@ -35,22 +36,22 @@ export async function buildDistFiles(basePath, silent) {
35
36
  ];
36
37
  for (const file of rootFilesToCopy) {
37
38
  const src = path.join(basePath, typeof file === "string" ? file : file.source), dest = path.join(distPath, typeof file === "string" ? file : file.destination);
38
- await fs.copyFile(src, dest);
39
+ await copyFile(src, dest);
39
40
  }
40
41
  const scriptsPath = path.join(basePath, "scripts"), distScriptsPath = path.join(distPath, "scripts");
41
- if ((await fs.exists(scriptsPath)) && !(await fs.exists(distScriptsPath))) {
42
- await fs.mkdir(distScriptsPath);
42
+ if (existsSync(scriptsPath) && !existsSync(distScriptsPath)) {
43
+ await mkdir(distScriptsPath);
43
44
  const installPath = path.join(scriptsPath, "install.js");
44
- if (await fs.exists(installPath)) {
45
- await fs.copyFile(installPath, path.join(distScriptsPath, "install.js"));
45
+ if (existsSync(installPath)) {
46
+ await copyFile(installPath, path.join(distScriptsPath, "install.js"));
46
47
  }
47
48
  }
48
49
  for await (const file of klaw(distPath)) {
49
50
  if (file.stats.isDirectory()) {
50
51
  continue;
51
52
  }
52
- const contents = await fs.readFile(file.path, "utf8");
53
- await fs.writeFile(file.path, contents.replaceAll("__VERSION__", `"${pkgInfo.version}"`), "utf8");
53
+ const contents = await readFile(file.path, "utf8");
54
+ await writeFile(file.path, contents.replaceAll("__VERSION__", `"${pkgInfo.version}"`), "utf8");
54
55
  }
55
56
  /* for await (const file of klaw(path.join(distPath, "cjs"))) {
56
57
  await fs.rename(file.path, file.path.replace(/\.js$/, ".cjs"));
@@ -59,9 +60,9 @@ export async function buildDistFiles(basePath, silent) {
59
60
  for await (const file of klaw(path.join(distPath, "esm"))) {
60
61
  await fs.rename(file.path, file.path.replace(/\.js$/, ".mjs"));
61
62
  } */
62
- await fs.writeFile(path.join(distPath, "cjs", "package.json"), `{ "type": "commonjs" }`);
63
- await fs.writeFile(path.join(distPath, "esm", "package.json"), `{ "type": "module" }`);
64
- await fs.writeFile(path.join(distPath, "browser", "package.json"), `{ "type": "module" }`);
63
+ await writeFile(path.join(distPath, "cjs", "package.json"), `{ "type": "commonjs" }`);
64
+ await writeFile(path.join(distPath, "esm", "package.json"), `{ "type": "module" }`);
65
+ await writeFile(path.join(distPath, "browser", "package.json"), `{ "type": "module" }`);
65
66
  res = true;
66
67
  }
67
68
  catch (e) {
@@ -1,4 +1,5 @@
1
- import fs from "fs-extra";
1
+ import { opendir, readFile, stat } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
2
3
  /**
3
4
  * @param folderPath - the path to the folder to get the stats for
4
5
  * @param bundlePath - the bundle path to get the bundle size for
@@ -11,10 +12,10 @@ async function getFolderStats(folderPath, bundlePath) {
11
12
  totalFolders: 0,
12
13
  totalSize: 0,
13
14
  };
14
- if (!(await fs.pathExists(folderPath))) {
15
+ if (!existsSync(folderPath)) {
15
16
  return stats;
16
17
  }
17
- const dir = await fs.promises.opendir(folderPath), path = await import("path");
18
+ const dir = await opendir(folderPath), path = await import("path");
18
19
  for await (const dirent of dir) {
19
20
  const increment = 1;
20
21
  if (dirent.isDirectory()) {
@@ -24,7 +25,7 @@ async function getFolderStats(folderPath, bundlePath) {
24
25
  stats.totalSize += subDirStats.totalSize;
25
26
  }
26
27
  else {
27
- const fileStats = await fs.stat(path.join(folderPath, dirent.name));
28
+ const fileStats = await stat(path.join(folderPath, dirent.name));
28
29
  stats.totalFiles++;
29
30
  stats.totalSize += fileStats.size;
30
31
  if (bundlePath && path.join(folderPath, dirent.name) === bundlePath) {
@@ -40,8 +41,8 @@ async function getFolderStats(folderPath, bundlePath) {
40
41
  * @returns the stats for the dist folder
41
42
  */
42
43
  export async function getDistStats(basePath) {
43
- const path = await import("path"), distFolder = path.join(basePath, "dist"), pkgInfo = (await fs.exists(path.join(distFolder, "package.json")))
44
- ? JSON.parse((await fs.readFile(path.join(distFolder, "package.json"))).toString())
45
- : {}, bundlePath = (await fs.exists(distFolder)) && pkgInfo.jsdelivr ? path.join(distFolder, pkgInfo.jsdelivr) : undefined;
44
+ const path = await import("path"), distFolder = path.join(basePath, "dist"), pkgInfo = existsSync(path.join(distFolder, "package.json"))
45
+ ? JSON.parse((await readFile(path.join(distFolder, "package.json"))).toString())
46
+ : {}, bundlePath = existsSync(distFolder) && pkgInfo.jsdelivr ? path.join(distFolder, pkgInfo.jsdelivr) : undefined;
46
47
  return await getFolderStats(distFolder, bundlePath);
47
48
  }
@@ -1,4 +1,5 @@
1
- import fs from "fs-extra";
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
2
3
  import klaw from "klaw";
3
4
  import path from "node:path";
4
5
  import prettier from "prettier";
@@ -19,7 +20,7 @@ export async function prettifySrc(basePath, srcPath, ci, silent) {
19
20
  if (file.stats.isDirectory()) {
20
21
  continue;
21
22
  }
22
- const contents = await fs.readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
23
+ const contents = await readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
23
24
  options.printWidth = 120;
24
25
  options.endOfLine = "lf";
25
26
  options.parser = "typescript";
@@ -32,7 +33,7 @@ export async function prettifySrc(basePath, srcPath, ci, silent) {
32
33
  }
33
34
  else {
34
35
  const formatted = await prettier.format(contents, options);
35
- await fs.writeFile(file.path, formatted, "utf8");
36
+ await writeFile(file.path, formatted, "utf8");
36
37
  }
37
38
  }
38
39
  res = true;
@@ -58,7 +59,7 @@ export async function prettifyPackageJson(basePath, ci, silent) {
58
59
  }
59
60
  let res;
60
61
  try {
61
- const contents = await fs.readFile("package.json", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
62
+ const contents = await readFile("package.json", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
62
63
  options.tabWidth = 2;
63
64
  options.printWidth = 120;
64
65
  options.endOfLine = "lf";
@@ -70,7 +71,7 @@ export async function prettifyPackageJson(basePath, ci, silent) {
70
71
  }
71
72
  else {
72
73
  const formatted = await prettier.format(contents, options);
73
- await fs.writeFile("package.json", formatted, "utf8");
74
+ await writeFile("package.json", formatted, "utf8");
74
75
  }
75
76
  res = true;
76
77
  }
@@ -95,7 +96,7 @@ export async function prettifyPackageDistJson(basePath, ci, silent) {
95
96
  }
96
97
  let res;
97
98
  try {
98
- const contents = await fs.readFile("package.dist.json", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
99
+ const contents = await readFile("package.dist.json", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
99
100
  options.tabWidth = 2;
100
101
  options.printWidth = 120;
101
102
  options.endOfLine = "lf";
@@ -107,7 +108,7 @@ export async function prettifyPackageDistJson(basePath, ci, silent) {
107
108
  }
108
109
  else {
109
110
  const formatted = await prettier.format(contents, options);
110
- await fs.writeFile("package.dist.json", formatted, "utf8");
111
+ await writeFile("package.dist.json", formatted, "utf8");
111
112
  }
112
113
  res = true;
113
114
  }
@@ -132,7 +133,7 @@ export async function prettifyReadme(basePath, ci, silent) {
132
133
  }
133
134
  let res;
134
135
  try {
135
- const contents = await fs.readFile("README.md", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
136
+ const contents = await readFile("README.md", "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
136
137
  options.printWidth = 120;
137
138
  options.endOfLine = "lf";
138
139
  options.parser = "markdown";
@@ -143,7 +144,7 @@ export async function prettifyReadme(basePath, ci, silent) {
143
144
  }
144
145
  else {
145
146
  const formatted = await prettier.format(contents, options);
146
- await fs.writeFile("README.md", formatted, "utf8");
147
+ await writeFile("README.md", formatted, "utf8");
147
148
  }
148
149
  res =
149
150
  (await prettifyTraductions(basePath, ci, silent)) && (await prettifyMarkdownTypeDocFiles(basePath, ci, silent));
@@ -170,7 +171,7 @@ async function prettifyTraductions(basePath, ci, silent) {
170
171
  let res = false;
171
172
  try {
172
173
  const folder = "traduction", folderPath = path.join(basePath, folder);
173
- if (!fs.existsSync(folderPath)) {
174
+ if (!existsSync(folderPath)) {
174
175
  res = true;
175
176
  }
176
177
  if (!res) {
@@ -178,7 +179,7 @@ async function prettifyTraductions(basePath, ci, silent) {
178
179
  if (file.stats.isDirectory()) {
179
180
  continue;
180
181
  }
181
- const contents = await fs.readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
182
+ const contents = await readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
182
183
  options.printWidth = 120;
183
184
  options.endOfLine = "lf";
184
185
  options.parser = "markdown";
@@ -189,7 +190,7 @@ async function prettifyTraductions(basePath, ci, silent) {
189
190
  }
190
191
  else {
191
192
  const formatted = await prettier.format(contents, options);
192
- await fs.writeFile(file.path, formatted, "utf8");
193
+ await writeFile(file.path, formatted, "utf8");
193
194
  }
194
195
  }
195
196
  res = true;
@@ -217,7 +218,7 @@ async function prettifyMarkdownTypeDocFiles(basePath, ci, silent) {
217
218
  let res = false;
218
219
  try {
219
220
  const folder = "markdown", folderPath = path.join(basePath, folder);
220
- if (!fs.existsSync(folderPath)) {
221
+ if (!existsSync(folderPath)) {
221
222
  res = true;
222
223
  }
223
224
  if (!res) {
@@ -225,7 +226,7 @@ async function prettifyMarkdownTypeDocFiles(basePath, ci, silent) {
225
226
  if (file.stats.isDirectory()) {
226
227
  continue;
227
228
  }
228
- const contents = await fs.readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
229
+ const contents = await readFile(file.path, "utf8"), options = (await prettier.resolveConfig(basePath)) ?? {};
229
230
  options.printWidth = 120;
230
231
  options.endOfLine = "lf";
231
232
  options.parser = "markdown";
@@ -236,7 +237,7 @@ async function prettifyMarkdownTypeDocFiles(basePath, ci, silent) {
236
237
  }
237
238
  else {
238
239
  const formatted = await prettier.format(contents, options);
239
- await fs.writeFile(file.path, formatted, "utf8");
240
+ await writeFile(file.path, formatted, "utf8");
240
241
  }
241
242
  }
242
243
  res = true;
@@ -1,5 +1,6 @@
1
- import fs from "fs-extra";
1
+ import { existsSync } from "node:fs";
2
2
  import path from "node:path";
3
+ import { readFile } from "node:fs/promises";
3
4
  var ExitCodes;
4
5
  (function (ExitCodes) {
5
6
  ExitCodes[ExitCodes["OK"] = 0] = "OK";
@@ -15,8 +16,8 @@ var ExitCodes;
15
16
  */
16
17
  async function readConfig(basePath, file) {
17
18
  const tsconfigPath = path.join(basePath, file);
18
- if (await fs.pathExists(tsconfigPath)) {
19
- const data = await fs.readFile(path.join(basePath, file));
19
+ if (existsSync(tsconfigPath)) {
20
+ const data = await readFile(path.join(basePath, file));
20
21
  return data.toString();
21
22
  }
22
23
  return undefined;
@@ -1,4 +1,6 @@
1
1
  import { Command } from "commander";
2
+ import { existsSync } from "node:fs";
3
+ import path from "node:path";
2
4
  const buildCommand = new Command("build");
3
5
  buildCommand.description("Build the tsParticles library using TypeScript");
4
6
  buildCommand.option("-a, --all", "Do all build steps (default if no flags are specified) (same as -b -c -d -l -p -t)", false);
@@ -19,8 +21,8 @@ buildCommand.action(async (argPath) => {
19
21
  const { clearDist } = await import("./build-clear.js");
20
22
  await clearDist(basePath, silent);
21
23
  }
22
- const path = await import("path"), srcPath = path.join(basePath, argPath), fs = await import("fs-extra");
23
- if (!(await fs.pathExists(srcPath))) {
24
+ const srcPath = path.join(basePath, argPath);
25
+ if (!existsSync(srcPath)) {
24
26
  throw new Error("Provided path does not exist");
25
27
  }
26
28
  let canContinue = true;
@@ -63,12 +65,12 @@ buildCommand.action(async (argPath) => {
63
65
  const newStats = await getDistStats(basePath), diffSize = newStats.totalSize - oldStats.totalSize, bundleDiffSize = newStats.bundleSize - oldStats.bundleSize, minSize = 0, bundleSizeIncreased = bundleDiffSize > minSize, bundleSizeIncreasedText = bundleSizeIncreased ? "increased" : "decreased", diffSizeIncreasedText = diffSize > minSize ? "increased" : "decreased";
64
66
  outputFunc = bundleSizeIncreased ? console.warn : console.info;
65
67
  texts = [
66
- !bundleDiffSize
67
- ? "Bundle size unchanged"
68
- : `Bundle size ${bundleSizeIncreasedText} from ${oldStats.bundleSize.toString()} to ${newStats.bundleSize.toString()} (${Math.abs(bundleDiffSize).toString()}B)`,
69
- !diffSize
70
- ? "Size unchanged"
71
- : `Size ${diffSizeIncreasedText} from ${oldStats.totalSize.toString()} to ${newStats.totalSize.toString()} (${Math.abs(diffSize).toString()}B)`,
68
+ bundleDiffSize
69
+ ? `Bundle size ${bundleSizeIncreasedText} from ${oldStats.bundleSize.toString()} to ${newStats.bundleSize.toString()} (${Math.abs(bundleDiffSize).toString()}B)`
70
+ : "Bundle size unchanged",
71
+ diffSize
72
+ ? `Size ${diffSizeIncreasedText} from ${oldStats.totalSize.toString()} to ${newStats.totalSize.toString()} (${Math.abs(diffSize).toString()}B)`
73
+ : "Size unchanged",
72
74
  `Files count changed from ${oldStats.totalFiles.toString()} to ${newStats.totalFiles.toString()} (${(newStats.totalFiles - oldStats.totalFiles).toString()})`,
73
75
  `Folders count changed from ${oldStats.totalFolders.toString()} to ${newStats.totalFolders.toString()} (${(newStats.totalFolders - oldStats.totalFolders).toString()})`,
74
76
  ];
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { buildCommand } from "./build/build.js";
3
3
  import { createCommand } from "./create/create.js";
4
- import { fileURLToPath } from "url";
5
- import fs from "fs-extra";
4
+ import { fileURLToPath } from "node:url";
6
5
  import path from "node:path";
7
6
  import { program } from "commander";
8
- const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__filename), rootPkgPath = path.join(__dirname, "..", "package.json"), pkg = (await fs.readJson(rootPkgPath));
7
+ import { readFile } from "node:fs/promises";
8
+ const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__filename), rootPkgPath = path.join(__dirname, "..", "package.json"), pkg = JSON.parse(await readFile(rootPkgPath, "utf-8"));
9
9
  program.name("tsparticles-cli");
10
10
  program.description("tsParticles CLI");
11
11
  program.version(pkg.version, "-v, --version", "output the current version");
@@ -1,6 +1,6 @@
1
1
  import { camelize, capitalize, dash } from "../../utils/string-utils.js";
2
2
  import { copyEmptyTemplateFiles, copyFilter, runBuild, runInstall, updatePackageDistFile, updatePackageFile, updateWebpackFile, } from "../../utils/template-utils.js";
3
- import fs from "fs-extra";
3
+ import { cp } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { replaceTokensInFile } from "../../utils/file-utils.js";
6
6
  /**
@@ -110,8 +110,9 @@ async function updatePluginWebpackFile(destPath, name, description) {
110
110
  export async function createPluginTemplate(name, description, repoUrl, destPath) {
111
111
  const sourcePath = path.join(__dirname, "..", "..", "..", "files", "create-plugin");
112
112
  await copyEmptyTemplateFiles(destPath);
113
- await fs.copy(sourcePath, destPath, {
114
- overwrite: true,
113
+ await cp(sourcePath, destPath, {
114
+ recursive: true,
115
+ force: true,
115
116
  filter: copyFilter,
116
117
  });
117
118
  await updateIndexFile(destPath, name);
@@ -1,6 +1,6 @@
1
1
  import { camelize, capitalize, dash } from "../../utils/string-utils.js";
2
2
  import { copyEmptyTemplateFiles, copyFilter, runBuild, runInstall, updatePackageDistFile, updatePackageFile, updateWebpackFile, } from "../../utils/template-utils.js";
3
- import fs from "fs-extra";
3
+ import { cp } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { replaceTokensInFile } from "../../utils/file-utils.js";
6
6
  /**
@@ -127,8 +127,9 @@ async function updatePresetWebpackFile(destPath, name, description) {
127
127
  export async function createPresetTemplate(name, description, repoUrl, destPath) {
128
128
  const sourcePath = path.join(__dirname, "..", "..", "..", "files", "create-preset");
129
129
  await copyEmptyTemplateFiles(destPath);
130
- await fs.copy(sourcePath, destPath, {
131
- overwrite: true,
130
+ await cp(sourcePath, destPath, {
131
+ recursive: true,
132
+ force: true,
132
133
  filter: copyFilter,
133
134
  });
134
135
  await updateBundleFile(destPath, name);
@@ -1,6 +1,6 @@
1
1
  import { camelize, capitalize, dash } from "../../utils/string-utils.js";
2
2
  import { copyEmptyTemplateFiles, copyFilter, runBuild, runInstall, updatePackageDistFile, updatePackageFile, updateWebpackFile, } from "../../utils/template-utils.js";
3
- import fs from "fs-extra";
3
+ import { cp } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { replaceTokensInFile } from "../../utils/file-utils.js";
6
6
  /**
@@ -115,8 +115,9 @@ async function updateShapeWebpackFile(destPath, name, description) {
115
115
  export async function createShapeTemplate(name, description, repoUrl, destPath) {
116
116
  const sourcePath = path.join(__dirname, "..", "..", "..", "files", "create-shape");
117
117
  await copyEmptyTemplateFiles(destPath);
118
- await fs.copy(sourcePath, destPath, {
119
- overwrite: true,
118
+ await cp(sourcePath, destPath, {
119
+ recursive: true,
120
+ force: true,
120
121
  filter: copyFilter,
121
122
  });
122
123
  await updateIndexFile(destPath, name);