@tsparticles/cli 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.
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 +8 -7
  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 +8 -7
  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
@@ -0,0 +1,7 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ target-branch: "dev"
5
+ directory: "/" # Location of package manifests
6
+ schedule:
7
+ interval: "daily"
@@ -1,100 +1,132 @@
1
1
  # Architecture
2
2
 
3
- **Analysis Date:** 2026-03-08
3
+ **Analysis Date:** 2026-03-10
4
4
 
5
5
  ## Pattern Overview
6
6
 
7
- **Overall:** Modular CLI application structured as command modules (command-per-file) with utility layers for filesystem and template operations.
7
+ Overall: Small modular CLI application organized as command modules with utility libraries and build tooling.
8
8
 
9
- **Key Characteristics:**
9
+ Key Characteristics:
10
10
 
11
- - Command-oriented boundaries implemented with `commander` (commands registered in `src/cli.ts` and `src/create/*`, `src/build/*`).
12
- - Utilities are centralized under `src/utils/` for file operations, templating, and string manipulation.
13
- - Build-related logic is under `src/build/` and creation/template generation logic under `src/create/`.
11
+ - Single-process Node.js CLI built in TypeScript (compiled to ESM JavaScript).
12
+ - Commands are organized as independent modules and registered with a central `commander`-based entrypoint.
13
+ - Clear separation between "command" code (user-facing CLI actions) and utilities (I/O, template manipulation, subprocess execution).
14
+ - Build scripts live under `src/build` and are implemented as programmatic build tasks callable from `build` command.
14
15
 
15
16
  ## Layers
16
17
 
17
- **CLI / Entry Layer:**
18
+ Command Layer:
18
19
 
19
- - Purpose: Expose CLI commands and wiring.
20
- - Location: `src/cli.ts`
21
- - Contains: Program initialization, command registration (`build`, `create`).
22
- - Depends on: `src/build/*`, `src/create/*`.
23
- - Used by: End users invoking the installed binary.
20
+ - Purpose: Exposes CLI commands and their behaviors to end users.
21
+ - Location: `src/cli.ts`, `src/create/*`, `src/build/*`
22
+ - Contains: `commander` Command instances, argument parsing, user prompts.
23
+ - Depends on: `src/utils/*` for filesystem and template operations, `prompts` for interactive input.
24
+ - Used by: CLI entrypoint `src/cli.ts` registers commands for runtime.
25
+
26
+ Core/Template Layer:
24
27
 
25
- **Command Implementations:**
28
+ - Purpose: Implement the core operations that create projects and manipulate templates.
29
+ - Location: `src/create/preset/create-preset.ts`, `src/create/shape/create-shape.ts`, `src/create/plugin/create-plugin.ts`, `src/utils/template-utils.ts`, `src/utils/file-utils.ts`
30
+ - Contains: file copy, token replacement, package.json updates, npm execution, webpack/package dist adjustments.
31
+ - Depends on: `fs-extra`, `lookpath`, child_process `exec`.
32
+ - Used by: Command actions in `src/create/*`.
26
33
 
27
- - Purpose: Implement individual subcommands for build and create flows.
28
- - Location: `src/create/*` (e.g. `src/create/create.ts`, `src/create/preset/*`, `src/create/plugin/*`, `src/create/shape/*`) and `src/build/*` (e.g. `src/build/build.ts`, `src/build/build-*.ts`).
29
- - Contains: Command definitions, argument parsing (uses `commander`), orchestration of utilities.
30
- - Depends on: `src/utils/*` for filesystem and templating, `fs-extra`, `prettier`, `webpack` where needed.
34
+ Build Tooling Layer:
31
35
 
32
- **Utilities / Core Logic:**
36
+ - Purpose: Project build and CI helpers exposed as `build` command.
37
+ - Location: `src/build/*.ts` (`src/build/build.ts`, `src/build/build-tsc.ts`, `src/build/build-bundle.ts`, etc.)
38
+ - Contains: tasks to run prettier, eslint, tsc, bundling and other project checks.
39
+ - Depends on: dev tooling in `package.json` and runtime tools (SWC, Webpack, etc.).
33
40
 
34
- - Purpose: Reusable helpers for file operations, token replacement, template manipulation, and string utilities.
35
- - Location: `src/utils/` (`file-utils.ts`, `template-utils.ts`, `string-utils.ts`).
36
- - Contains: `replaceTokensInFile`, `runInstall`, `runBuild`, copy filter helpers, string transforms.
37
- - Depends on: `fs-extra`, `lookpath`, `child_process` (`exec`).
41
+ Utilities Layer:
38
42
 
39
- **Files & Templates:**
43
+ - Purpose: Shared helpers for string manipulation, file operations and token replacement.
44
+ - Location: `src/utils/string-utils.ts`, `src/utils/file-utils.ts`, `src/utils/template-utils.ts`
45
+ - Contains: helper functions with small focused responsibilities (e.g., `replaceTokensInFile`, `getDestinationDir`, `getRepositoryUrl`).
40
46
 
41
- - Purpose: Template resources used to scaffold projects.
42
- - Location: `files/` (e.g., `files/create-shape`, `files/create-preset`, `files/create-plugin`, `files/empty-project`).
47
+ Test Layer:
48
+
49
+ - Purpose: Unit tests for templates and generator functions.
50
+ - Location: `tests/*.test.ts`, `vitest.config.ts`
43
51
 
44
52
  ## Data Flow
45
53
 
46
- Create flow (example `create shape`):
54
+ Create command flow (example `preset`):
47
55
 
48
- 1. User runs CLI: `tsparticles-cli create shape <dest>` (`src/cli.ts` -> `src/create/create.ts` -> `src/create/shape/*`).
49
- 2. Command handler calls `createShapeTemplate` in `src/create/shape/create-shape.ts`.
50
- 3. `createShapeTemplate` copies template files from `files/create-shape` to destination using `fs-extra` and `template-utils.copyEmptyTemplateFiles`.
51
- 4. Token replacement and file updates are performed using `src/utils/file-utils.ts` functions like `replaceTokensInFile` and helpers in `src/utils/template-utils.ts`.
52
- 5. Optional lifecycle commands `runInstall` and `runBuild` invoke external commands (`npm install`, `npm run build`) via `child_process.exec` if `npm` is present (checked via `lookpath`).
56
+ 1. User invokes CLI: `tsparticles-cli create preset <destination>` -> `src/cli.ts` boots and routes to `src/create/create.ts` -> `src/create/preset/preset.ts`.
57
+ 2. `preset.ts` gathers interactive input via `prompts` and computes `destPath` using `src/utils/file-utils.ts:getDestinationDir`.
58
+ 3. `createPresetTemplate` in `src/create/preset/create-preset.ts` runs sequence:
59
+ - copy empty template files (`src/utils/template-utils.ts:copyEmptyTemplateFiles`) -> uses `files` templates under repo
60
+ - copy project-specific files via `fs.copy`
61
+ - run a series of `replaceTokensInFile` operations (`src/utils/file-utils.ts`) to customize bundle/index/readme/package files
62
+ - run `runInstall` and `runBuild` (`src/utils/template-utils.ts`) which spawn subprocesses (`npm install`, `npm run build`) if `npm` found
53
63
 
54
64
  State Management:
55
65
 
56
- - Stateless CLI; state is the filesystem and created project files. No in-memory long-lived state across runs.
66
+ - Stateless CLI operations. Functions operate on input parameters and filesystem state. There is no in-memory application-wide state beyond individual command execution.
57
67
 
58
68
  ## Key Abstractions
59
69
 
60
- **Template Updater:**
70
+ Command Module:
71
+
72
+ - Purpose: Encapsulate a single CLI command and its action handler.
73
+ - Examples: `src/create/preset/preset.ts`, `src/create/shape/shape.ts`, `src/create/plugin/plugin.ts`, `src/create/create.ts`.
74
+ - Pattern: Each command is a `commander.Command` with `argument` declarations and an `action` async function.
61
75
 
62
- - Purpose: Replace tokens and update produced scaffold files.
63
- - Examples: `src/utils/file-utils.ts` (`replaceTokensInFile`), `src/utils/template-utils.ts` (`updatePackageFile`, `updateWebpackFile`, `updatePackageDistFile`).
64
- - Pattern: Imperative token-replacement using regexes and file writes.
76
+ Template Manipulation Utility:
65
77
 
66
- **Command Modules:**
78
+ - Purpose: Replace tokens and patch files in a project template.
79
+ - Examples: `src/utils/file-utils.ts` (`replaceTokensInFile`, `replaceTokensInFiles`), `src/utils/template-utils.ts` (`updatePackageFile`, `updateWebpackFile`).
67
80
 
68
- - Purpose: Each subcommand is an isolated module exposing a `Command` (from `commander`).
69
- - Examples: `src/create/create.ts`, `src/build/build.ts`, `src/create/shape/create-shape.ts`.
81
+ Build Task Modules:
82
+
83
+ - Purpose: Implement discrete build subtasks called from `src/build/build.ts`.
84
+ - Examples: `src/build/build-tsc.ts`, `src/build/build-bundle.ts`, `src/build/build-eslint.ts`.
70
85
 
71
86
  ## Entry Points
72
87
 
73
- **CLI Entrypoint:**
88
+ CLI Entrypoint:
74
89
 
75
90
  - Location: `src/cli.ts`
76
- - Triggers: Node process when user runs `tsparticles-cli` or package `bin` mapping.
77
- - Responsibilities: Read package version (`package.json`), register commands and parse args.
91
+ - Triggers: Executed when package binary `dist/cli.js` is run (shebang present); `npm run build` ensures `dist/cli.js` is executable.
92
+ - Responsibilities: Read package version (`package.json`), register `build` and `create` commands and parse `process.argv`.
78
93
 
79
- ## Error Handling
94
+ Create Command Aggregator:
95
+
96
+ - Location: `src/create/create.ts`
97
+ - Triggers: Registered by `src/cli.ts` as `create` command
98
+ - Responsibilities: Add subcommands `plugin`, `preset`, `shape` from their respective modules.
80
99
 
81
- Strategy:
100
+ Build Aggregator:
82
101
 
83
- - Try/catch around file operations and external command execution; errors logged to console with `console.error` and boolean success values returned (e.g., `src/build/*` functions return `Promise<boolean>`). Examples: `src/build/build-prettier.ts`, `src/build/build-bundle.ts`.
102
+ - Location: `src/build/build.ts`
103
+ - Triggers: Registered by `src/cli.ts` as `build` command
104
+ - Responsibilities: Compose and run smaller build tasks (prettier, lint, tsc, circular deps, dist packaging).
105
+
106
+ ## Error Handling
107
+
108
+ Strategy: Throw and bubble errors from async functions; top-level command handlers are async and do not wrap all exceptions. Some tests and callers catch errors for logging.
84
109
 
85
110
  Patterns:
86
111
 
87
- - Propagate failures by throwing or returning `false` and logging details.
88
- - `replaceTokensInFiles` performs read/replace/write with no specialized rollback.
112
+ - Synchronous validation: `getDestinationDir` checks destination existence and throws an Error if folder not empty (`src/utils/file-utils.ts:getDestinationDir`).
113
+ - Subprocess execution: `exec` wrappers (`runInstall`, `runBuild`) return Promises and reject on `exec` error; calling code awaits and therefore receives the rejection (`src/utils/template-utils.ts`).
114
+ - Tests catch and log errors selectively (`tests/*.test.ts`), but many command entrypoints do not add global try/catch.
89
115
 
90
116
  ## Cross-Cutting Concerns
91
117
 
92
- Logging: `console.log`, `console.warn`, `console.error` used across `src/build/*` and `src/utils/*`.
118
+ Logging:
119
+
120
+ - Approach: Minimal; code uses `console.error` in tests. No centralized logger present. Files: `tests/*`, most modules do not log.
121
+
122
+ Validation:
123
+
124
+ - Approach: Input validation is enforced by `prompts` validators and `getDestinationDir` pre-checks. See `src/create/*` for validators on required fields.
93
125
 
94
- Validation: Input validation is minimal — `commander` performs CLI argument parsing; `getDestinationDir` validates destination directory emptiness in `src/utils/file-utils.ts`.
126
+ Authentication:
95
127
 
96
- Authentication: Not applicable; tool is local and does not call external authenticated services.
128
+ - Approach: Not applicable to this CLI: no remote APIs or credential storage.
97
129
 
98
130
  ---
99
131
 
100
- _Architecture analysis: 2026-03-08_
132
+ _Architecture analysis: 2026-03-10_
@@ -1,102 +1,105 @@
1
1
  # Codebase Concerns
2
2
 
3
- **Analysis Date:** 2026-03-08
3
+ **Analysis Date:** 2026-03-10
4
4
 
5
5
  ## Tech Debt
6
6
 
7
- 1. Minimal input validation and transactional safety when writing files
7
+ **Regex-based token replacement (critical):**
8
8
 
9
- - Issue: `replaceTokensInFiles` and other template-updating functions perform read/replace/write in-place without atomic writes or rollback. A failed intermediate step can leave partially updated files.
10
- - Files: `src/utils/file-utils.ts`, `src/utils/template-utils.ts`, `src/create/shape/create-shape.ts`
11
- - Impact: Corrupted template output when an operation fails mid-flow; harder to recover from errors.
12
- - Fix approach: Write to temporary files and rename atomically (use `fs-extra` `outputFile` + `move`), or create the target in a staging directory and move into destination once all transformations succeed.
9
+ - Issue: `src/utils/file-utils.ts` implements `replaceTokensInFiles` and constructs a RegExp with `new RegExp(token.from, "g")` regardless of whether `token.from` is a `string` or a `RegExp`.
10
+ - Files: `src/utils/file-utils.ts`, callers in `src/utils/template-utils.ts`, `src/create/preset/create-preset.ts` (many tokens are passed as `RegExp` literals).
11
+ - Impact: When `token.from` is already a `RegExp` and flags are passed as the second argument to `RegExp` constructor, Node throws a TypeError. This makes token replacement fragile and causes runtime exceptions in template updates. Tests and callers may swallow the error (see `tests/create-preset.test.ts`) so the issue can be silent in CI but still indicate a bug.
12
+ - Fix approach: Update `replaceTokensInFiles` to detect `RegExp` values and use them directly, or construct a `RegExp` only when `token.from` is a string. Example change in `src/utils/file-utils.ts`:
13
13
 
14
- 2. Running external commands directly in template flow (`npm install`, `npm run build`)
14
+ ```ts
15
+ const regex = token.from instanceof RegExp ? token.from : new RegExp(String(token.from), "g");
16
+ data = data.replace(regex, token.to);
17
+ ```
15
18
 
16
- - Issue: `runInstall` and `runBuild` call `exec("npm install")` and `exec("npm run build")` without timeouts or stdout/stderr piping; they rely on `lookpath` only.
17
- - Files: `src/utils/template-utils.ts` (functions `runInstall`, `runBuild`)
18
- - Impact: Tests or CI running on environments lacking `npm` may silently skip or hang if `lookpath` returns true but command misbehaves; poor control over failure modes.
19
- - Fix approach: Use spawned child process with streaming logs and a configurable timeout, or provide a dry-run flag. In tests, mock these exec calls to avoid long-running operations.
19
+ Applying this fix ensures RegExp arguments are respected and avoids TypeErrors.
20
20
 
21
- 3. Prettier plugin compatibility workaround
21
+ **Template JSON changes performed with regex (moderate):**
22
22
 
23
- - Issue: `src/build/build-prettier.ts` contains a TODO disabling Prettier check for `prettier-plugin-multiline-arrays` compatibility with Prettier 3.0.0.
24
- - Files: `src/build/build-prettier.ts` (line with TODO)
25
- - Impact: Formatting checks may be inconsistent across CI and local dev environments.
26
- - Fix approach: Update dependencies to versions compatible with Prettier 3.x or pin Prettier to a compatible 2.x in CI until plugins are updated. Add a CI check that fails early with a clear error message.
23
+ - Issue: `src/utils/template-utils.ts` updates `package.json` and `package.dist.json` using regex replacements (`replaceTokensInFile`) instead of reading and writing JSON.
24
+ - Files: `src/utils/template-utils.ts`, `src/create/preset/create-preset.ts`.
25
+ - Impact: Regex-based edits are brittle: formatting differences, comments, CRLF vs LF, or unexpected matches can break JSON structure or fail to update fields correctly.
26
+ - Fix approach: Parse the JSON files with `fs.readJSON` / `fs.writeJSON` and modify the relevant fields (name, description, repository, files). This is more robust and easier to test. Example target: update `updatePackageFile` to `const pkg = await fs.readJSON(pkgPath); pkg.name = packageName; await fs.writeJSON(pkgPath, pkg, { spaces: 2 });`
27
27
 
28
28
  ## Known Bugs
29
29
 
30
- None detected by static analysis in the repository. Tests pass in CI (workflow present) but no failing patterns discovered in code scan.
30
+ **RegExp constructor TypeError during replacements:**
31
31
 
32
- ## Security Considerations
33
-
34
- 1. Running external commands with user-provided template inputs
32
+ - Symptoms: Token replacement throws TypeError when token pattern is a `RegExp` and code calls `new RegExp(token.from, "g")`.
33
+ - Files: `src/utils/file-utils.ts` (replacement implementation).
34
+ - Trigger: Calling any create/template flow that passes `RegExp` literals into tokens (e.g., `src/create/preset/create-preset.ts`).
35
+ - Workaround: Tests and callers often wrap calls in try/catch (see `tests/create-preset.test.ts`) so tests still assert package.json existence, masking the problem. Do not rely on that; fix the replacement implementation.
35
36
 
36
- - Risk: If destination paths or template tokens contain malicious content, shell commands executed via `exec` could be abused.
37
- - Files: `src/utils/template-utils.ts` (`runInstall`, `runBuild`), `src/utils/file-utils.ts` (token replacement using regex from code, not user input directly).
38
- - Current mitigation: `exec` is invoked with static commands (`npm install`) and not interpolated with user-supplied strings. `replaceTokensInFile` uses regex replacements defined in code.
39
- - Recommendation: Avoid invoking shell with interpolated user input. If needed, sanitize inputs and prefer `spawn` with argument arrays.
37
+ ## Security Considerations
40
38
 
41
- 2. Reading git remote URL via `exec` in `getRepositoryUrl`
39
+ **Arbitrary script execution via `npm install` / `npm run build`:**
42
40
 
43
- - Risk: `exec` result is returned directly; if git not present it rejects.
44
- - Files: `src/utils/file-utils.ts` (`getRepositoryUrl`)
45
- - Recommendation: Wrap with timeout and sanitize output before using it in template substitution.
41
+ - Area: `src/utils/template-utils.ts` functions `runInstall` and `runBuild` execute `npm install` and `npm run build` in generated projects.
42
+ - Files: `src/utils/template-utils.ts`, `src/create/*` where `runInstall` and `runBuild` are invoked (e.g., `src/create/preset/create-preset.ts`).
43
+ - Risk: Running `npm install` in a directory containing an attacker-controlled `package.json` can execute lifecycle scripts (postinstall, preinstall). The CLI currently runs installs automatically during template creation, which can execute arbitrary code on the user's machine.
44
+ - Current mitigation: `lookpath("npm")` is used to avoid running when `npm` is not available, but this does not mitigate script execution risks.
45
+ - Recommendation: Do not run `npm install` / `npm run build` automatically. Instead:
46
+ - Require an explicit flag (e.g., `--install`) to run automatic installs, or
47
+ - Use `npm ci --ignore-scripts` or `npm install --ignore-scripts` as a safer default, and clearly warn users before running scripts, or
48
+ - Prompt for confirmation before running `npm` and print the exact command being run.
46
49
 
47
50
  ## Performance Bottlenecks
48
51
 
49
- 1. Synchronous/serial file traversal in prettify
52
+ **Use of `child_process.exec` for long-running, high-output commands (moderate):**
50
53
 
51
- - Problem: `prettier` formatting in `prettifySrc` iterates files sequentially (`for await (const file of klaw(srcPath))`), performing `prettier.resolveConfig` per file which may be expensive.
52
- - Files: `src/build/build-prettier.ts`
53
- - Cause: Recomputing config and formatting each file sequentially.
54
- - Improvement path: Resolve config once outside the loop, run formatting in parallel batches, and avoid repeated IO for options.
54
+ - Area: `src/utils/template-utils.ts` and `src/utils/file-utils.ts` (the latter uses `exec` in `getRepositoryUrl`).
55
+ - Files: `src/utils/template-utils.ts` (`runInstall`, `runBuild`), `src/utils/file-utils.ts` (`getRepositoryUrl`).
56
+ - Problem: `exec` buffers the full stdout/stderr and has a default buffer size; heavy outputs (e.g., `npm install`) can overflow the buffer and cause the subprocess to fail. Also, using `exec` hides streaming logs from the user.
57
+ - Improvement path: Use `child_process.spawn` with streaming of stdout/stderr and proper error/exit-code handling. Stream logs to the console or into a logger so users see progress.
55
58
 
56
59
  ## Fragile Areas
57
60
 
58
- 1. Regex-based token replacement
61
+ **Broad regex replacements over multiple file types (fragile):**
59
62
 
60
- - Files: `src/utils/file-utils.ts`, `src/utils/template-utils.ts`, `src/create/*` token replacement usage
61
- - Why fragile: Regexes operate on file contents and can unintentionally match similar substrings; no schema validation after replacement.
62
- - Safe modification: Add tests for each token replacement case, and perform replacements against structured JSON (for `package.json`) using AST parsing where possible.
63
- - Test coverage: Token replacement used heavily but tests exercise many flows; add more unit tests for edge cases.
63
+ - Files: `src/utils/file-utils.ts`, call sites in `src/utils/template-utils.ts` and `src/create/*`.
64
+ - Why fragile: Replacing text with global regexes across files risks accidental substitution (e.g., replacing occurrences in unrelated files). It also makes reasoning about what changed difficult.
65
+ - Safe modification: Limit replacements to specific files and, where possible, use structured transforms (JSON AST edits for `package.json`, templating tools for code files) rather than blind regex.
64
66
 
65
- ## Scaling Limits
67
+ **No centralized logging or structured errors (minor):**
66
68
 
67
- Not applicable: CLI scaffolding and local build tool; not intended for high-concurrency server workloads.
69
+ - Files: `src/cli.ts`, `src/build/*.ts`, `src/create/*` modules log via `console` or propagate exceptions.
70
+ - Why fragile: Lack of a central logger and consistent error formatting makes debugging and user-facing error messages inconsistent. Adding a simple logging utility (e.g., `src/utils/logger.ts`) and top-level error handling in `src/cli.ts` would improve UX.
68
71
 
69
72
  ## Dependencies at Risk
70
73
 
71
- 1. Prettier plugin `prettier-plugin-multiline-arrays`
74
+ **Self-referential devDependency:**
72
75
 
73
- - Risk: Incompatibility with Prettier 3.x noted in `src/build/build-prettier.ts` TODO.
74
- - Impact: Formatting and CI checks could be disrupted.
75
- - Migration plan: Upgrade plugin or pin Prettier; monitor plugin releases.
76
+ - Files: `package.json` lists `"@tsparticles/cli": "latest"` in `devDependencies`.
77
+ - Risk: This can lead to confusing local development semantics. It is common for monorepo setups but should be intentional.
78
+ - Migration plan: If not required, remove the self-reference. If needed for local testing, ensure a documented developer workflow.
76
79
 
77
80
  ## Missing Critical Features
78
81
 
79
- 1. No centralized logging or telemetry
82
+ **Safe-by-default template creation (missing):**
80
83
 
81
- - Problem: Uses `console.*` directly; no centralized structured logs for debugging CI or for library consumers.
82
- - Blocks: Advanced observability and consistent log levels.
84
+ - Problem: Template creation runs `npm install`/`npm run build` by default. There is no opt-in flag to skip these actions for safer, faster creation in CI or sandboxed environments.
85
+ - Blocks: CI runs, offline usage, and security-conscious users.
86
+ - Recommendation: Add a `--no-install` / `--skip-install` option to `create` commands or a top-level config, and ensure `runInstall`/`runBuild` respect that option.
83
87
 
84
88
  ## Test Coverage Gaps
85
89
 
86
- 1. Lack of mocks for external process execution
90
+ **Replacement function tests (high priority):**
87
91
 
88
- - What's not tested: Behavior of `runInstall`/`runBuild` when `npm` present and when the commands fail.
89
- - Files: `src/utils/template-utils.ts` and tests in `tests/` currently avoid actually running `npm` by relying on environment; but there are no unit tests mocking `exec`.
90
- - Risk: Breakage during publish/cmd execution might not be caught in unit tests.
91
- - Priority: Medium — add tests that stub `child_process.exec` and `lookpath` to verify behavior on success and failure.
92
+ - What's not tested: `replaceTokensInFiles` behavior when `token.from` is a `RegExp` object vs a `string` (no explicit unit tests for this edge case).
93
+ - Files: `src/utils/file-utils.ts`, tests should be added under `tests/file-utils.test.ts` or similar.
94
+ - Risk: Future regressions and silent failures in template flows.
95
+ - Priority: High — add targeted unit tests that exercise both `string` and `RegExp` token inputs and verify no exceptions are thrown and replacements occur as expected.
92
96
 
93
- 2. Token replacement edge cases
97
+ **Integration tests should avoid running real npm:**
94
98
 
95
- - What's not tested: Regex collisions and JSON-encoded fields in `package.json` and `package.dist.json` replacements.
96
- - Files: `src/utils/file-utils.ts`, `src/utils/template-utils.ts`
97
- - Risk: Incorrect package metadata produced for scaffolds.
98
- - Priority: High — add unit tests that run replacements on fixture files with edge-case tokens.
99
+ - What's not tested safely: `createPresetTemplate` currently calls `runInstall` and `runBuild` which invoke `npm` and may perform network operations in CI.
100
+ - Files: `tests/create-preset.test.ts`, `src/utils/template-utils.ts`.
101
+ - Recommendation: Mock `lookpath` and `child_process.exec` in tests, or refactor `runInstall`/`runBuild` to accept an injectable runner (dependency injection) so tests can inject a no-op runner.
99
102
 
100
103
  ---
101
104
 
102
- _Concerns audit: 2026-03-08_
105
+ _Concerns audit: 2026-03-10_
@@ -1,96 +1,91 @@
1
1
  # Coding Conventions
2
2
 
3
- **Analysis Date:** 2026-03-08
3
+ **Analysis Date:** 2026-03-10
4
4
 
5
5
  ## Naming Patterns
6
6
 
7
7
  Files:
8
8
 
9
- - Source files are placed under feature directories (e.g., `src/create/shape/create-shape.ts`). Use descriptive names matching the feature.
9
+ - Pattern: kebab-case for source filenames and CLI commands
10
+ - Examples: `src/create/create.ts`, `src/create/preset/create-preset.ts`, `src/build/build-tsc.ts`
10
11
 
11
12
  Functions:
12
13
 
13
- - Use camelCase for function names (e.g., `createShapeTemplate` in `src/create/shape/create-shape.ts`, `replaceTokensInFile` in `src/utils/file-utils.ts`).
14
+ - Pattern: camelCase for free functions and helpers
15
+ - Examples: `replaceTokensInFile` in `src/utils/file-utils.ts`, `createPresetTemplate` in `src/create/preset/create-preset.ts`
14
16
 
15
17
  Variables:
16
18
 
17
- - Use camelCase for variables and constants. TypeScript types use PascalCase.
19
+ - Pattern: camelCase for local variables and constants; use `const` when value is not reassigned
20
+ - Examples: `destPath`, `camelizedName` in `src/create/shape/create-shape.ts`
18
21
 
19
- Types:
22
+ Types / Interfaces:
20
23
 
21
- - Interfaces and types use PascalCase (e.g., `ReplaceTokensOptions`, `ReplaceTokensData` in `src/utils/file-utils.ts`).
24
+ - Pattern: PascalCase for interfaces and type names
25
+ - Examples: `ReplaceTokensOptions`, `ReplaceTokensData` in `src/utils/file-utils.ts`
26
+
27
+ Exports:
28
+
29
+ - Pattern: named exports from modules (no default exports observed)
30
+ - Examples: `export async function replaceTokensInFiles` in `src/utils/file-utils.ts`
22
31
 
23
32
  ## Code Style
24
33
 
25
34
  Formatting:
26
35
 
27
- - Prettier is the formatting tool; root `package.json` sets `prettier` to `@tsparticles/prettier-config`. Formatting settings are applied in `src/build/build-prettier.ts` (printWidth 120, tabWidth 2, endOfLine lf).
36
+ - Prettier is used via the package `prettier` and project config referenced in `package.json` (`prettier": "@tsparticles/prettier-config"`).
37
+ - Scripts: `prettify:src`, `prettify:readme`, `prettify:ci:src` in `package.json`
28
38
 
29
39
  Linting:
30
40
 
31
- - ESLint config in `eslint.config.js` extends `@tsparticles/eslint-config`. Linting is enforced in `package.json` scripts (`lint`, `lint:ci`) and CI runs `pnpm run lint:ci` in `node.js-ci.yml`.
32
-
33
- ## Import Organization
34
-
35
- Order:
36
-
37
- 1. Node built-ins (e.g., `path`, `fs-extra` import as `fs`)
38
- 2. External dependencies (e.g., `commander`, `prompts`)
39
- 3. Internal modules (relative imports under `src/`)
40
-
41
- Examples: `src/cli.ts` imports `buildCommand` and `createCommand` from local modules after Node imports.
42
-
43
- Path Aliases:
44
-
45
- - None detected. Imports use relative paths and package names. Keep using relative imports within `src/`.
41
+ - ESLint is configured in `eslint.config.js` and reuses `@tsparticles/eslint-config` (see `eslint.config.js`).
42
+ - Scripts: `lint` (auto-fix) and `lint:ci` in `package.json`
43
+ - Rule note: `no-console` is disabled in `eslint.config.js` to allow `console` usage in CLI code and tests.
46
44
 
47
- ## Error Handling
48
-
49
- Patterns:
50
-
51
- - Use try/catch around file system operations and external command execution; log errors with `console.error` (see `src/build/*.ts`, `src/utils/*`).
52
- - Functions that perform operations return boolean success flags (`Promise<boolean>`) where appropriate (e.g., `src/build/build-prettier.ts`, `src/build/build-bundle.ts`).
53
-
54
- ## Logging
45
+ TypeScript:
55
46
 
56
- Framework: console
47
+ - Strict TypeScript settings are enabled in `tsconfig.json` (many `strict` flags set: `strict`, `noImplicitAny`, `noUnusedLocals`, etc.).
57
48
 
58
- Patterns:
49
+ Doc comments:
59
50
 
60
- - Use `console.log` for informational messages, `console.warn` for warnings, `console.error` for errors. Follow existing use in `src/build/*` and `src/utils/*`.
51
+ - Use JSDoc/TSDoc style comments on exported functions and complex helpers.
52
+ - Examples: function headers in `src/utils/string-utils.ts`, `src/utils/template-utils.ts`.
61
53
 
62
- ## Comments
63
-
64
- When to Comment:
54
+ ## Import Organization
65
55
 
66
- - Use JSDoc/TSDoc comments for exported functions and modules. Code contains JSDoc-style function headers (e.g., `src/build/build-prettier.ts`).
56
+ - Pattern observed: third-party packages first, then Node built-ins, then local relative imports.
57
+ - Example from `src/create/preset/create-preset.ts`:
58
+ - `import { camelize, capitalize, dash } from "../../utils/string-utils.js";`
59
+ - `import fs from "fs-extra"`; `import path from "node:path"`;
67
60
 
68
- JSDoc/TSDoc:
61
+ Path aliases:
69
62
 
70
- - Use TSDoc/JSDoc annotations for function parameters and return values on public utilities.
63
+ - Not detected. Imports use relative paths (e.g., `../../utils/*`) and explicit `.js` extension when imported from tests or other ESM contexts.
71
64
 
72
- ## Function Design
65
+ ## Error Handling
73
66
 
74
- Size:
67
+ - Pattern: functions either throw synchronous errors (`throw new Error(...)`) for validation or reject Promises when asynchronous operations fail.
68
+ - Example: `getDestinationDir` throws `new Error("Destination folder already exists and is not empty")` in `src/utils/file-utils.ts`.
69
+ - Example: `runInstall`/`runBuild` use the `exec` callback to `reject(error)` in `src/utils/template-utils.ts`.
75
70
 
76
- - Functions typically remain under ~200 lines and perform a single responsibility (e.g., `createShapeTemplate` orchestrates template copying and updates but delegates to small helpers).
71
+ ## Logging
77
72
 
78
- Parameters:
73
+ - Pattern: CLI code and tests use `console` for informational output and debugging. ESLint `no-console` is turned off to permit this.
74
+ - Files: `src/cli.ts`, tests in `tests/*.test.ts` (see `tests/file-utils.test.ts` where `console.log`/`console.error` is used).
79
75
 
80
- - Prefer explicit parameters and typed signatures. Existing functions are strongly typed (see `tsconfig.json` with `strict: true`).
76
+ ## Comments and Documentation
81
77
 
82
- Return Values:
78
+ - Public helpers include JSDoc comments (examples in `src/utils/*`). Maintain comments for exported functions to describe parameters and return values.
83
79
 
84
- - Use typed return values (`Promise<void>`, `Promise<boolean>`) and avoid implicit `any`.
80
+ ## Function & Module Design
85
81
 
86
- ## Module Design
82
+ - Small single-responsibility functions are the norm (examples: `replaceTokensInFiles`, `updatePackageFile`, `copyEmptyTemplateFiles`).
83
+ - Modules export multiple named helpers rather than a default export (see `src/utils/template-utils.ts`).
87
84
 
88
- Exports:
85
+ ## Barrel files
89
86
 
90
- - Modules export named functions (e.g., `export async function createShapeTemplate ...` in `src/create/shape/create-shape.ts`). Prefer named exports.
91
- Barrel Files:
92
- - Not used. Add explicit exports per-file instead of index barrel files unless a clear grouping is required.
87
+ - Not used. Individual modules are imported with relative paths.
93
88
 
94
89
  ---
95
90
 
96
- _Convention analysis: 2026-03-08_
91
+ _Convention analysis: 2026-03-10_