Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 44c193d4a8 | |||
| 44d259a0ae | |||
| f0adff8784 | |||
| fb453e62c3 | |||
| 001721a8e9 | |||
| b191464ff9 | |||
| 4d7eaa238f | |||
| 601e0d1063 | |||
| 4bb1a2f8c7 | |||
| b506bf8785 | |||
| d5fbeb3fc6 | |||
| 2ecdeff3dc | |||
| 5a663ae767 | |||
| 218c84a39b | |||
| 27d5cdca35 | |||
| 3ebf072bfb | |||
| 08f56ae0a4 | |||
| b2d2684895 |
@@ -6,19 +6,19 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${-{gitea.repository_owner}-}:${-{secrets.GITEA_TOKEN}-}@{{module.githost}}/${-{gitea.repository}-}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
NPMCI_TOKEN_NPM: ${-{secrets.NPMCI_TOKEN_NPM}-}
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
NPMCI_TOKEN_NPM2: ${-{secrets.NPMCI_TOKEN_NPM2}-}
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
NPMCI_GIT_GITHUBTOKEN: ${-{secrets.NPMCI_GIT_GITHUBTOKEN}-}
|
||||||
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
NPMCI_URL_CLOUDLY: ${-{secrets.NPMCI_URL_CLOUDLY}-}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
security:
|
security:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -44,11 +44,11 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
test:
|
test:
|
||||||
if: ${{ always() }}
|
if: ${-{ always() }-}
|
||||||
needs: security
|
needs: security
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|||||||
@@ -6,19 +6,19 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${-{gitea.repository_owner}-}:${-{secrets.GITEA_TOKEN}-}@{{module.githost}}/${-{gitea.repository}-}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
NPMCI_TOKEN_NPM: ${-{secrets.NPMCI_TOKEN_NPM}-}
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
NPMCI_TOKEN_NPM2: ${-{secrets.NPMCI_TOKEN_NPM2}-}
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
NPMCI_GIT_GITHUBTOKEN: ${-{secrets.NPMCI_GIT_GITHUBTOKEN}-}
|
||||||
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
NPMCI_URL_CLOUDLY: ${-{secrets.NPMCI_URL_CLOUDLY}-}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
security:
|
security:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -42,11 +42,11 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
test:
|
test:
|
||||||
if: ${{ always() }}
|
if: ${-{ always() }-}
|
||||||
needs: security
|
needs: security
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -74,7 +74,7 @@ jobs:
|
|||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -95,7 +95,7 @@ jobs:
|
|||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ${{ env.IMAGE }}
|
image: ${-{ env.IMAGE }-}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -3,8 +3,6 @@
|
|||||||
# artifacts
|
# artifacts
|
||||||
coverage/
|
coverage/
|
||||||
public/
|
public/
|
||||||
test/
|
|
||||||
test2/
|
|
||||||
|
|
||||||
# installs
|
# installs
|
||||||
node_modules/
|
node_modules/
|
||||||
@@ -18,6 +16,10 @@ node_modules/
|
|||||||
dist/
|
dist/
|
||||||
dist_*/
|
dist_*/
|
||||||
|
|
||||||
|
# AI
|
||||||
|
.claude/
|
||||||
|
.serena/
|
||||||
|
|
||||||
#------# custom
|
#------# custom
|
||||||
.serena
|
.serena
|
||||||
test-output.json
|
test-output.json
|
||||||
|
|||||||
115
changelog.md
115
changelog.md
@@ -1,6 +1,76 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.12.1 - fix(cli)
|
||||||
|
No changes detected — no version bump required
|
||||||
|
|
||||||
|
- Current package version: 2.12.0
|
||||||
|
- No files changed in this commit
|
||||||
|
- No release or version bump necessary
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.12.0 - feat(ci,test)
|
||||||
|
feat(ci/test): add test scaffold, GitLab CI, update gitea workflows and .gitignore
|
||||||
|
|
||||||
|
- Add comprehensive test/ scaffold including sample tests, test package.json, npmextra.json, test fixtures and TypeScript test sources
|
||||||
|
- Add GitLab CI pipeline (test/.gitlab-ci.yml), test-specific .npmrc, VSCode launch/settings and supporting qenv/readme files for CI/local test runs
|
||||||
|
- Update .gitea workflow YAML files to use templated placeholders and corrected container image path for CI execution
|
||||||
|
- Update .gitignore to exclude AI assistant and tooling dirs (.claude/, .serena/) and add test/.gitignore to ignore test artifacts
|
||||||
|
- Update changelog and documentation files to reflect recent formatter/commit/service changes and the new test/CI additions
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.11.1 - fix(mod_format/formatters)
|
||||||
|
|
||||||
|
fix(packagejson.formatter): correctly parse scoped package dependency arguments and default to latest
|
||||||
|
|
||||||
|
- Handle scoped packages (e.g. @scope/name@version) by detecting the last '@' after the scope slash so package name and version are split correctly.
|
||||||
|
- Fallback to 'latest' when no version is provided.
|
||||||
|
- Fixes earlier incorrect splitting on every '@' which broke scoped package names.
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.11.0 - feat(mod_format)
|
||||||
|
|
||||||
|
feat(mod_format): use unified diff formatter with filenames and context in BaseFormatter.displayDiff
|
||||||
|
|
||||||
|
- Replaced plugins.smartdiff.formatLineDiffForConsole(...) with plugins.smartdiff.formatUnifiedDiffForConsole(...) when both before and after are present.
|
||||||
|
- Passes originalFileName and revisedFileName as diff.path and sets context to 3 to show a unified diff with surrounding lines.
|
||||||
|
- Improves console output for multi-line diffs by using unified diff format and including file names.
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.10.0 - feat(mod_format)
|
||||||
|
|
||||||
|
Refactor formatting modules to new BaseFormatter and implement concrete analyze/apply logic
|
||||||
|
|
||||||
|
- Replace generic LegacyFormatter with explicit BaseFormatter implementations for formatters: copy, gitignore, license, npmextra, packagejson, prettier, readme, templates, tsconfig (legacy.formatter.ts removed).
|
||||||
|
- Copy formatter: implemented pattern-based copying, template-preserve path handling, content equality check and planned change generation/apply.
|
||||||
|
- Gitignore formatter: canonical template with preservation of custom section when updating/creating .gitignore.
|
||||||
|
- License formatter: added runtime license check against node_modules for incompatible licenses and reporting (no file changes).
|
||||||
|
- Npmextra formatter: automatic migrations for old namespace keys to package-scoped keys and migration of npmAccessLevel -> @git.zone/cli.release.accessLevel; reformatting and interactive prompting to fill missing repo metadata.
|
||||||
|
- Package.json formatter: enforces repository/metadata, sets module type/private/license/scripts/files, ensures/updates dependencies (including fetching latest via registry), and applies pnpm overrides from assets.
|
||||||
|
- Prettier formatter: added check() to compute diffs by running Prettier and returning per-file before/after diffs.
|
||||||
|
- Readme formatter: create readme.md and readme.hints.md when missing with default content.
|
||||||
|
- Templates formatter: apply templates from templatesDir based on project type (vscode, CI, docker, website/service/wcc), compare template vs destination and create/modify files as needed; ensures dest directories exist.
|
||||||
|
- Tsconfig formatter: sets compilerOptions.baseUrl and computes path mappings from @git.zone/tspublish modules.
|
||||||
|
- General: extensive use of plugins (smartfs, path, smartnpm, smartinteract, smartobject, smartlegal), improved logging and verbose messages.
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.9.0 - feat(format)
|
||||||
|
|
||||||
|
Add --diff option to format command to display file diffs; pass flag through CLI and show formatter diffs. Bump @git.zone/tsdoc to ^1.11.0.
|
||||||
|
|
||||||
|
- Add a diff boolean option to mod_format to enable showing file diffs during format operations.
|
||||||
|
- CLI change: pass argvArg.diff into the options so the --diff flag is honored by the format command.
|
||||||
|
- When diff is enabled, run formatter.check() for each active formatter and call displayAllDiffs() for those with differences, with informational logging.
|
||||||
|
- Update dependency @git.zone/tsdoc from ^1.10.2 to ^1.11.0.
|
||||||
|
|
||||||
|
## 2025-12-15 - 2.8.0 - feat(commit)
|
||||||
|
|
||||||
|
Add commit configuration and automatic pre-commit tests
|
||||||
|
|
||||||
|
- Add CommitConfig class to manage @git.zone/cli.commit settings in npmextra.json (alwaysTest, alwaysBuild).
|
||||||
|
- Export CommitConfig from mod_config for use by the CLI.
|
||||||
|
- Add 'gitzone config commit' subcommand with interactive and direct-setting modes (alwaysTest, alwaysBuild).
|
||||||
|
- Merge CLI flags and npmextra config: -t/--test and -b/--build now respect commit.alwaysTest and commit.alwaysBuild.
|
||||||
|
- Run 'pnpm test' early in the commit flow when tests are enabled; abort the commit on failing tests and log results.
|
||||||
|
- Update commit UI/plan to show the test option and include the test step when enabled.
|
||||||
|
- Add 'gitzone config services' entry to configure services via ServiceManager.
|
||||||
|
|
||||||
## 2025-12-14 - 2.7.0 - feat(mod_format)
|
## 2025-12-14 - 2.7.0 - feat(mod_format)
|
||||||
|
|
||||||
Add check-only formatting with interactive diff preview; make formatting default to dry-run and extend formatting API
|
Add check-only formatting with interactive diff preview; make formatting default to dry-run and extend formatting API
|
||||||
|
|
||||||
- Add BaseFormatter.check(), displayDiff() and displayAllDiffs() to compute and render diffs without applying changes.
|
- Add BaseFormatter.check(), displayDiff() and displayAllDiffs() to compute and render diffs without applying changes.
|
||||||
@@ -13,6 +83,7 @@ Add check-only formatting with interactive diff preview; make formatting default
|
|||||||
- Bump dependency @push.rocks/smartdiff to ^1.1.0.
|
- Bump dependency @push.rocks/smartdiff to ^1.1.0.
|
||||||
|
|
||||||
## 2025-12-14 - 2.6.1 - fix(npmextra)
|
## 2025-12-14 - 2.6.1 - fix(npmextra)
|
||||||
|
|
||||||
Normalize npmextra.json: move tsdoc legal entry and reposition @git.zone/cli configuration
|
Normalize npmextra.json: move tsdoc legal entry and reposition @git.zone/cli configuration
|
||||||
|
|
||||||
- Move TSDoc legal text into a top-level "tsdoc.legal" property in npmextra.json
|
- Move TSDoc legal text into a top-level "tsdoc.legal" property in npmextra.json
|
||||||
@@ -21,6 +92,7 @@ Normalize npmextra.json: move tsdoc legal entry and reposition @git.zone/cli con
|
|||||||
- Pure configuration change (JSON structure) — no functional code changes
|
- Pure configuration change (JSON structure) — no functional code changes
|
||||||
|
|
||||||
## 2025-12-14 - 2.6.0 - feat(mod_commit)
|
## 2025-12-14 - 2.6.0 - feat(mod_commit)
|
||||||
|
|
||||||
Add execution plan output to commit command
|
Add execution plan output to commit command
|
||||||
|
|
||||||
- Print an execution plan at the start of the commit flow (shows active options and planned steps)
|
- Print an execution plan at the start of the commit flow (shows active options and planned steps)
|
||||||
@@ -29,6 +101,7 @@ Add execution plan output to commit command
|
|||||||
- Execution plan reflects flags: auto-accept (-y), push (-p), build (-b), release (-r), --format, and target registries
|
- Execution plan reflects flags: auto-accept (-y), push (-p), build (-b), release (-r), --format, and target registries
|
||||||
|
|
||||||
## 2025-12-14 - 2.5.0 - feat(mod_standard)
|
## 2025-12-14 - 2.5.0 - feat(mod_standard)
|
||||||
|
|
||||||
Add interactive main menu and help to standard CLI module; route commands via dynamic imports
|
Add interactive main menu and help to standard CLI module; route commands via dynamic imports
|
||||||
|
|
||||||
- Introduce interactive CLI menu using @push.rocks/smartinteract to prompt user for actions.
|
- Introduce interactive CLI menu using @push.rocks/smartinteract to prompt user for actions.
|
||||||
@@ -37,6 +110,7 @@ Add interactive main menu and help to standard CLI module; route commands via dy
|
|||||||
- Remove previous static template listing and logger.warn placeholder.
|
- Remove previous static template listing and logger.warn placeholder.
|
||||||
|
|
||||||
## 2025-12-14 - 2.4.0 - feat(cli)
|
## 2025-12-14 - 2.4.0 - feat(cli)
|
||||||
|
|
||||||
Add optional build step to release flow and auto-format npmextra config when registries change
|
Add optional build step to release flow and auto-format npmextra config when registries change
|
||||||
|
|
||||||
- Introduce a --build/-b flag in the commit/release flow to run 'pnpm build' before pushing/releases
|
- Introduce a --build/-b flag in the commit/release flow to run 'pnpm build' before pushing/releases
|
||||||
@@ -47,6 +121,7 @@ Add optional build step to release flow and auto-format npmextra config when reg
|
|||||||
- Add npmextra registry config entry (https://verdaccio.lossless.digital) to npmextra.json
|
- Add npmextra registry config entry (https://verdaccio.lossless.digital) to npmextra.json
|
||||||
|
|
||||||
## 2025-12-14 - 2.3.0 - feat(config)
|
## 2025-12-14 - 2.3.0 - feat(config)
|
||||||
|
|
||||||
Add interactive menu and help to config command, handle unknown commands, and bump dependencies
|
Add interactive menu and help to config command, handle unknown commands, and bump dependencies
|
||||||
|
|
||||||
- When running the 'config' command with no arguments, show an interactive menu (via SmartInteract) to choose actions (show, add, remove, clear, access, help) instead of defaulting to 'show'.
|
- When running the 'config' command with no arguments, show an interactive menu (via SmartInteract) to choose actions (show, add, remove, clear, access, help) instead of defaulting to 'show'.
|
||||||
@@ -55,6 +130,7 @@ Add interactive menu and help to config command, handle unknown commands, and bu
|
|||||||
- Update dependency: @push.rocks/smartjson -> ^6.0.0.
|
- Update dependency: @push.rocks/smartjson -> ^6.0.0.
|
||||||
|
|
||||||
## 2025-12-04 - 2.2.1 - fix(commit)
|
## 2025-12-04 - 2.2.1 - fix(commit)
|
||||||
|
|
||||||
Prevent auto-accept for BREAKING CHANGE commits; require manual confirmation and warn when --yes is used
|
Prevent auto-accept for BREAKING CHANGE commits; require manual confirmation and warn when --yes is used
|
||||||
|
|
||||||
- Do not auto-accept AI commit recommendations when the suggested change is a BREAKING CHANGE (major bump).
|
- Do not auto-accept AI commit recommendations when the suggested change is a BREAKING CHANGE (major bump).
|
||||||
@@ -63,6 +139,7 @@ Prevent auto-accept for BREAKING CHANGE commits; require manual confirmation and
|
|||||||
- Introduced isBreakingChange and canAutoAccept flags to centralize the auto-accept logic.
|
- Introduced isBreakingChange and canAutoAccept flags to centralize the auto-accept logic.
|
||||||
|
|
||||||
## 2025-12-02 - 2.2.0 - feat(services)
|
## 2025-12-02 - 2.2.0 - feat(services)
|
||||||
|
|
||||||
Improve services manager and configuration; switch test templates to @git.zone/tstest; bump dev dependencies and update docs
|
Improve services manager and configuration; switch test templates to @git.zone/tstest; bump dev dependencies and update docs
|
||||||
|
|
||||||
- services: Add robust ServiceConfiguration (creates .nogit/env.json with sane defaults, syncs ports from existing Docker containers, validates and can reconfigure ports)
|
- services: Add robust ServiceConfiguration (creates .nogit/env.json with sane defaults, syncs ports from existing Docker containers, validates and can reconfigure ports)
|
||||||
@@ -73,6 +150,7 @@ Improve services manager and configuration; switch test templates to @git.zone/t
|
|||||||
- docs: README updates — add issue reporting/security section, AI-powered commit recommendation notes, and clarify trademark/legal wording
|
- docs: README updates — add issue reporting/security section, AI-powered commit recommendation notes, and clarify trademark/legal wording
|
||||||
|
|
||||||
## 2025-11-29 - 2.1.0 - feat(mod_services)
|
## 2025-11-29 - 2.1.0 - feat(mod_services)
|
||||||
|
|
||||||
Add global service registry and global commands for managing project containers
|
Add global service registry and global commands for managing project containers
|
||||||
|
|
||||||
- Introduce GlobalRegistry class to track registered projects, their containers, ports and last activity (ts/mod_services/classes.globalregistry.ts)
|
- Introduce GlobalRegistry class to track registered projects, their containers, ports and last activity (ts/mod_services/classes.globalregistry.ts)
|
||||||
@@ -82,30 +160,34 @@ Add global service registry and global commands for managing project containers
|
|||||||
- Bump dependency @push.rocks/smartfile to ^13.1.0 in package.json
|
- Bump dependency @push.rocks/smartfile to ^13.1.0 in package.json
|
||||||
|
|
||||||
## 2025-11-27 - 2.0.0 - BREAKING CHANGE(core)
|
## 2025-11-27 - 2.0.0 - BREAKING CHANGE(core)
|
||||||
|
|
||||||
Migrate filesystem to smartfs (async) and add Elasticsearch service support; refactor format/commit/meta modules
|
Migrate filesystem to smartfs (async) and add Elasticsearch service support; refactor format/commit/meta modules
|
||||||
|
|
||||||
- Replace @push.rocks/smartfile usage with @push.rocks/smartfs across the codebase; all filesystem operations are now async (SmartFs.file(...).read()/write(), SmartFs.directory(...).list()/create()/delete(), etc.)
|
- Replace @push.rocks/smartfile usage with @push.rocks/smartfs across the codebase; all filesystem operations are now async (SmartFs.file(...).read()/write(), SmartFs.directory(...).list()/create()/delete(), etc.)
|
||||||
- Convert formerly synchronous helpers and APIs to async (notable: detectProjectType, getProjectName, readCurrentVersion and related version bumping logic). Callers updated accordingly.
|
- Convert formerly synchronous helpers and APIs to async (notable: detectProjectType, getProjectName, readCurrentVersion and related version bumping logic). Callers updated accordingly.
|
||||||
- Add Elasticsearch support to services: new config fields (ELASTICSEARCH_*), Docker run/start/stop/logs/status handling, and ELASTICSEARCH_URL in service configuration.
|
- Add Elasticsearch support to services: new config fields (ELASTICSEARCH\_\*), Docker run/start/stop/logs/status handling, and ELASTICSEARCH_URL in service configuration.
|
||||||
- Refactor formatting subsystem: cache and rollback/backup systems removed/disabled for stability, format planner execution simplified (sequential), diff/stats reporting updated to use smartfs.
|
- Refactor formatting subsystem: cache and rollback/backup systems removed/disabled for stability, format planner execution simplified (sequential), diff/stats reporting updated to use smartfs.
|
||||||
- Update package.json dependencies: bump @git.zone/tsbuild, tsrun, tstest; upgrade @push.rocks/smartfile to v13 and add @push.rocks/smartfs dependency; update @types/node.
|
- Update package.json dependencies: bump @git.zone/tsbuild, tsrun, tstest; upgrade @push.rocks/smartfile to v13 and add @push.rocks/smartfs dependency; update @types/node.
|
||||||
- Update commit flow and changelog generation to use smartfs for reading/writing files and to await version/branch detection where necessary.
|
- Update commit flow and changelog generation to use smartfs for reading/writing files and to await version/branch detection where necessary.
|
||||||
- Expose a SmartFs instance via plugins and adjust all mod.* plugin files to import/use smartfs where required.
|
- Expose a SmartFs instance via plugins and adjust all mod.\* plugin files to import/use smartfs where required.
|
||||||
- Breaking change: Public and internal APIs that previously used synchronous smartfile APIs are now asynchronous. Consumers and scripts must await these functions and use the new smartfs API.
|
- Breaking change: Public and internal APIs that previously used synchronous smartfile APIs are now asynchronous. Consumers and scripts must await these functions and use the new smartfs API.
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.5 - fix(tsconfig)
|
## 2025-11-17 - 1.21.5 - fix(tsconfig)
|
||||||
|
|
||||||
Remove emitDecoratorMetadata from tsconfig template
|
Remove emitDecoratorMetadata from tsconfig template
|
||||||
|
|
||||||
- Removed the "emitDecoratorMetadata" compiler option from assets/templates/tsconfig_update/tsconfig.json
|
- Removed the "emitDecoratorMetadata" compiler option from assets/templates/tsconfig_update/tsconfig.json
|
||||||
- This updates the tsconfig template to avoid emitting decorator metadata when targeting ES2022
|
- This updates the tsconfig template to avoid emitting decorator metadata when targeting ES2022
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.4 - fix(tsconfig template)
|
## 2025-11-17 - 1.21.4 - fix(tsconfig template)
|
||||||
|
|
||||||
Remove experimentalDecorators and useDefineForClassFields from tsconfig template
|
Remove experimentalDecorators and useDefineForClassFields from tsconfig template
|
||||||
|
|
||||||
- Removed experimentalDecorators option from assets/templates/tsconfig_update/tsconfig.json
|
- Removed experimentalDecorators option from assets/templates/tsconfig_update/tsconfig.json
|
||||||
- Removed useDefineForClassFields option from assets/templates/tsconfig_update/tsconfig.json
|
- Removed useDefineForClassFields option from assets/templates/tsconfig_update/tsconfig.json
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.3 - fix(assets/templates/multienv)
|
## 2025-11-17 - 1.21.3 - fix(assets/templates/multienv)
|
||||||
|
|
||||||
Remove unused Bun configuration template (assets/templates/multienv/bunfig.toml)
|
Remove unused Bun configuration template (assets/templates/multienv/bunfig.toml)
|
||||||
|
|
||||||
- Deleted assets/templates/multienv/bunfig.toml which previously provided Bun TypeScript decorator configuration
|
- Deleted assets/templates/multienv/bunfig.toml which previously provided Bun TypeScript decorator configuration
|
||||||
@@ -113,17 +195,20 @@ Remove unused Bun configuration template (assets/templates/multienv/bunfig.toml)
|
|||||||
- No functional code changes; removes an unused asset file
|
- No functional code changes; removes an unused asset file
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.2 - fix(templates/multienv)
|
## 2025-11-17 - 1.21.2 - fix(templates/multienv)
|
||||||
|
|
||||||
Disable useDefineForClassFields in multienv TypeScript configs to ensure decorator compatibility
|
Disable useDefineForClassFields in multienv TypeScript configs to ensure decorator compatibility
|
||||||
|
|
||||||
- Set useDefineForClassFields = false in assets/templates/multienv/bunfig.toml to keep Bun's transpiler compatible with decorator usage
|
- Set useDefineForClassFields = false in assets/templates/multienv/bunfig.toml to keep Bun's transpiler compatible with decorator usage
|
||||||
- Set "useDefineForClassFields": false in assets/templates/multienv/deno.json to ensure Deno/TypeScript compiler emits class fields compatible with decorators
|
- Set "useDefineForClassFields": false in assets/templates/multienv/deno.json to ensure Deno/TypeScript compiler emits class fields compatible with decorators
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.1 - fix(templates.multienv)
|
## 2025-11-17 - 1.21.1 - fix(templates.multienv)
|
||||||
|
|
||||||
Enable checkJs in multienv Deno template to enable JS type checking
|
Enable checkJs in multienv Deno template to enable JS type checking
|
||||||
|
|
||||||
- Added "checkJs": true to compilerOptions in assets/templates/multienv/deno.json to enable JavaScript type checking for the Deno multienv template
|
- Added "checkJs": true to compilerOptions in assets/templates/multienv/deno.json to enable JavaScript type checking for the Deno multienv template
|
||||||
|
|
||||||
## 2025-11-17 - 1.21.0 - feat(multienv)
|
## 2025-11-17 - 1.21.0 - feat(multienv)
|
||||||
|
|
||||||
Add multi-env templates enabling TypeScript decorators for Bun and Deno; rename npmextra config key to szci
|
Add multi-env templates enabling TypeScript decorators for Bun and Deno; rename npmextra config key to szci
|
||||||
|
|
||||||
- Added assets/templates/multienv/bunfig.toml to enable Bun TypeScript transpiler experimentalDecorators
|
- Added assets/templates/multienv/bunfig.toml to enable Bun TypeScript transpiler experimentalDecorators
|
||||||
@@ -131,6 +216,7 @@ Add multi-env templates enabling TypeScript decorators for Bun and Deno; rename
|
|||||||
- Updated npmextra.json: renamed top-level config key from "npmci" to "szci" (keeps npmGlobalTools, npmAccessLevel and npmRegistryUrl unchanged)
|
- Updated npmextra.json: renamed top-level config key from "npmci" to "szci" (keeps npmGlobalTools, npmAccessLevel and npmRegistryUrl unchanged)
|
||||||
|
|
||||||
## 2025-11-06 - 1.20.0 - feat(commit)
|
## 2025-11-06 - 1.20.0 - feat(commit)
|
||||||
|
|
||||||
Add non-interactive --yes (-y) flag to commit command to auto-accept AI recommendations and optionally push with -p
|
Add non-interactive --yes (-y) flag to commit command to auto-accept AI recommendations and optionally push with -p
|
||||||
|
|
||||||
- Add -y / --yes flag to gitzone commit to auto-accept AI-generated commit recommendations without interactive prompts
|
- Add -y / --yes flag to gitzone commit to auto-accept AI-generated commit recommendations without interactive prompts
|
||||||
@@ -140,6 +226,7 @@ Add non-interactive --yes (-y) flag to commit command to auto-accept AI recommen
|
|||||||
- Updated CLI usage and documentation (readme.hints.md) to document the new flags
|
- Updated CLI usage and documentation (readme.hints.md) to document the new flags
|
||||||
|
|
||||||
## 2025-11-05 - 1.19.9 - fix(mod_commit)
|
## 2025-11-05 - 1.19.9 - fix(mod_commit)
|
||||||
|
|
||||||
Refactor version bumping to a unified implementation for npm and Deno; remove npm-exec based helpers and add file-based version readers/updaters to avoid npm warning pollution
|
Refactor version bumping to a unified implementation for npm and Deno; remove npm-exec based helpers and add file-based version readers/updaters to avoid npm warning pollution
|
||||||
|
|
||||||
- Removed legacy npm/deno-specific helpers (bumpNpmVersion, syncVersionToDenoJson, bumpDenoVersion) that relied on executing npm and caused warning pollution
|
- Removed legacy npm/deno-specific helpers (bumpNpmVersion, syncVersionToDenoJson, bumpDenoVersion) that relied on executing npm and caused warning pollution
|
||||||
@@ -150,39 +237,46 @@ Refactor version bumping to a unified implementation for npm and Deno; remove np
|
|||||||
- Benefits: no npm warning pollution in deno.json, simpler git history, consistent behavior across project types
|
- Benefits: no npm warning pollution in deno.json, simpler git history, consistent behavior across project types
|
||||||
|
|
||||||
## 2025-11-04 - 1.19.8 - fix(package.json)
|
## 2025-11-04 - 1.19.8 - fix(package.json)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc dependency to ^1.9.2
|
Bump @git.zone/tsdoc dependency to ^1.9.2
|
||||||
|
|
||||||
- Updated dependency @git.zone/tsdoc from ^1.9.1 to ^1.9.2 in package.json
|
- Updated dependency @git.zone/tsdoc from ^1.9.1 to ^1.9.2 in package.json
|
||||||
|
|
||||||
## 2025-11-04 - 1.19.7 - fix(dependencies)
|
## 2025-11-04 - 1.19.7 - fix(dependencies)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc to ^1.9.1
|
Bump @git.zone/tsdoc to ^1.9.1
|
||||||
|
|
||||||
- Updated package.json dependency @git.zone/tsdoc from ^1.9.0 to ^1.9.1
|
- Updated package.json dependency @git.zone/tsdoc from ^1.9.0 to ^1.9.1
|
||||||
|
|
||||||
## 2025-11-04 - 1.19.6 - fix(cli)
|
## 2025-11-04 - 1.19.6 - fix(cli)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc dependency to ^1.9.0
|
Bump @git.zone/tsdoc dependency to ^1.9.0
|
||||||
|
|
||||||
- Updated dependency @git.zone/tsdoc from ^1.8.3 to ^1.9.0 in package.json
|
- Updated dependency @git.zone/tsdoc from ^1.8.3 to ^1.9.0 in package.json
|
||||||
|
|
||||||
## 2025-11-04 - 1.19.5 - fix(cli)
|
## 2025-11-04 - 1.19.5 - fix(cli)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc to ^1.8.3 and add local .claude settings for allowed permissions
|
Bump @git.zone/tsdoc to ^1.8.3 and add local .claude settings for allowed permissions
|
||||||
|
|
||||||
- Updated dependency @git.zone/tsdoc from ^1.8.2 to ^1.8.3
|
- Updated dependency @git.zone/tsdoc from ^1.8.2 to ^1.8.3
|
||||||
- Added .claude/settings.local.json to declare allowed permissions for local tooling (Bash commands, Docker, npm, WebFetch and MCP actions)
|
- Added .claude/settings.local.json to declare allowed permissions for local tooling (Bash commands, Docker, npm, WebFetch and MCP actions)
|
||||||
|
|
||||||
## 2025-11-03 - 1.19.3 - fix(tsdoc)
|
## 2025-11-03 - 1.19.3 - fix(tsdoc)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc to ^1.8.0 and add .claude local settings
|
Bump @git.zone/tsdoc to ^1.8.0 and add .claude local settings
|
||||||
|
|
||||||
- Upgrade dependency @git.zone/tsdoc from ^1.6.1 to ^1.8.0 in package.json
|
- Upgrade dependency @git.zone/tsdoc from ^1.6.1 to ^1.8.0 in package.json
|
||||||
- Add .claude/settings.local.json for local assistant permissions/configuration
|
- Add .claude/settings.local.json for local assistant permissions/configuration
|
||||||
|
|
||||||
## 2025-11-03 - 1.19.2 - fix(tsdoc)
|
## 2025-11-03 - 1.19.2 - fix(tsdoc)
|
||||||
|
|
||||||
Bump @git.zone/tsdoc to ^1.6.1 and add .claude/settings.local.json
|
Bump @git.zone/tsdoc to ^1.6.1 and add .claude/settings.local.json
|
||||||
|
|
||||||
- Update dependency @git.zone/tsdoc from ^1.6.0 to ^1.6.1
|
- Update dependency @git.zone/tsdoc from ^1.6.0 to ^1.6.1
|
||||||
- Add .claude/settings.local.json to include local Claude settings/permissions
|
- Add .claude/settings.local.json to include local Claude settings/permissions
|
||||||
|
|
||||||
## 2025-11-02 - 1.19.1 - fix(dependencies)
|
## 2025-11-02 - 1.19.1 - fix(dependencies)
|
||||||
|
|
||||||
Bump dependencies and add local Claude settings
|
Bump dependencies and add local Claude settings
|
||||||
|
|
||||||
- Bump devDependencies: @git.zone/tsbuild -> ^2.7.1, @git.zone/tsrun -> ^1.6.2, @git.zone/tstest -> ^2.7.0
|
- Bump devDependencies: @git.zone/tsbuild -> ^2.7.1, @git.zone/tsrun -> ^1.6.2, @git.zone/tstest -> ^2.7.0
|
||||||
@@ -190,6 +284,7 @@ Bump dependencies and add local Claude settings
|
|||||||
- Add .claude/settings.local.json (local project permissions/settings file)
|
- Add .claude/settings.local.json (local project permissions/settings file)
|
||||||
|
|
||||||
## 2025-10-23 - 1.19.0 - feat(mod_commit)
|
## 2025-10-23 - 1.19.0 - feat(mod_commit)
|
||||||
|
|
||||||
Add CLI UI helpers and improve commit workflow with progress, recommendations and summary
|
Add CLI UI helpers and improve commit workflow with progress, recommendations and summary
|
||||||
|
|
||||||
- Introduce ts/mod_commit/mod.ui.ts: reusable CLI UI helpers (pretty headers, sections, AI recommendation box, step printer, commit summary and helpers for consistent messaging).
|
- Introduce ts/mod_commit/mod.ui.ts: reusable CLI UI helpers (pretty headers, sections, AI recommendation box, step printer, commit summary and helpers for consistent messaging).
|
||||||
@@ -198,6 +293,7 @@ Add CLI UI helpers and improve commit workflow with progress, recommendations an
|
|||||||
- Add .claude/settings.local.json: local permissions configuration for development tooling.
|
- Add .claude/settings.local.json: local permissions configuration for development tooling.
|
||||||
|
|
||||||
## 2025-10-23 - 1.18.9 - fix(mod_commit)
|
## 2025-10-23 - 1.18.9 - fix(mod_commit)
|
||||||
|
|
||||||
Stage and commit deno.json when bumping/syncing versions and create/update git tags
|
Stage and commit deno.json when bumping/syncing versions and create/update git tags
|
||||||
|
|
||||||
- bumpDenoVersion now creates a Smartshell instance and runs git add deno.json, git commit -m "v<newVersion>", and git tag v<newVersion> to persist the version bump
|
- bumpDenoVersion now creates a Smartshell instance and runs git add deno.json, git commit -m "v<newVersion>", and git tag v<newVersion> to persist the version bump
|
||||||
@@ -205,6 +301,7 @@ Stage and commit deno.json when bumping/syncing versions and create/update git t
|
|||||||
- Added informative logger messages after creating commits and tags
|
- Added informative logger messages after creating commits and tags
|
||||||
|
|
||||||
## 2025-10-23 - 1.18.8 - fix(mod_commit)
|
## 2025-10-23 - 1.18.8 - fix(mod_commit)
|
||||||
|
|
||||||
Improve commit workflow: detect project type and current branch; add robust version bump helpers for npm/deno
|
Improve commit workflow: detect project type and current branch; add robust version bump helpers for npm/deno
|
||||||
|
|
||||||
- Add mod_commit/mod.helpers.ts with utilities: detectCurrentBranch(), detectProjectType(), bumpProjectVersion(), bumpDenoVersion(), bumpNpmVersion(), syncVersionToDenoJson(), and calculateNewVersion()
|
- Add mod_commit/mod.helpers.ts with utilities: detectCurrentBranch(), detectProjectType(), bumpProjectVersion(), bumpDenoVersion(), bumpNpmVersion(), syncVersionToDenoJson(), and calculateNewVersion()
|
||||||
@@ -214,12 +311,14 @@ Improve commit workflow: detect project type and current branch; add robust vers
|
|||||||
- Add local Claude settings file (.claude/settings.local.json) (editor/CI config) — no code behavior change but included in diff
|
- Add local Claude settings file (.claude/settings.local.json) (editor/CI config) — no code behavior change but included in diff
|
||||||
|
|
||||||
## 2025-09-07 - 1.18.7 - fix(claude)
|
## 2025-09-07 - 1.18.7 - fix(claude)
|
||||||
|
|
||||||
Add .claude local settings to whitelist dev tool permissions
|
Add .claude local settings to whitelist dev tool permissions
|
||||||
|
|
||||||
- Add .claude/settings.local.json to configure allowed permissions for local AI/tooling helpers (Bash commands, WebFetch, and mcp_serena actions).
|
- Add .claude/settings.local.json to configure allowed permissions for local AI/tooling helpers (Bash commands, WebFetch, and mcp_serena actions).
|
||||||
- Disable enableAllProjectMcpServers (set to false) to limit automatic project MCP server usage.
|
- Disable enableAllProjectMcpServers (set to false) to limit automatic project MCP server usage.
|
||||||
|
|
||||||
## 2025-09-07 - 1.18.6 - fix(deps)
|
## 2025-09-07 - 1.18.6 - fix(deps)
|
||||||
|
|
||||||
Bump dependency versions and add local Claude settings
|
Bump dependency versions and add local Claude settings
|
||||||
|
|
||||||
- Updated devDependencies: @git.zone/tsbuild ^2.6.4 → ^2.6.8, @git.zone/tstest ^2.3.4 → ^2.3.6, @push.rocks/smartfile ^11.2.5 → ^11.2.7
|
- Updated devDependencies: @git.zone/tsbuild ^2.6.4 → ^2.6.8, @git.zone/tstest ^2.3.4 → ^2.3.6, @push.rocks/smartfile ^11.2.5 → ^11.2.7
|
||||||
@@ -227,6 +326,7 @@ Bump dependency versions and add local Claude settings
|
|||||||
- Added .claude/settings.local.json to configure local Claude permissions/settings
|
- Added .claude/settings.local.json to configure local Claude permissions/settings
|
||||||
|
|
||||||
## 2025-08-17 - 1.18.5 - fix(dependencies)
|
## 2025-08-17 - 1.18.5 - fix(dependencies)
|
||||||
|
|
||||||
Bump smartshell and smartscaf versions; add .claude local settings
|
Bump smartshell and smartscaf versions; add .claude local settings
|
||||||
|
|
||||||
- Update @push.rocks/smartshell from ^3.2.4 to ^3.3.0 in package.json
|
- Update @push.rocks/smartshell from ^3.2.4 to ^3.3.0 in package.json
|
||||||
@@ -234,6 +334,7 @@ Bump smartshell and smartscaf versions; add .claude local settings
|
|||||||
- Add .claude/settings.local.json for local assistant permissions/configuration
|
- Add .claude/settings.local.json for local assistant permissions/configuration
|
||||||
|
|
||||||
## 2025-08-17 - 1.18.4 - fix(cli)
|
## 2025-08-17 - 1.18.4 - fix(cli)
|
||||||
|
|
||||||
Update dependencies, add local Claude settings, and update gitignore template
|
Update dependencies, add local Claude settings, and update gitignore template
|
||||||
|
|
||||||
- Bump several dependencies: @git.zone/tsbuild -> ^2.6.4, @git.zone/tspublish -> ^1.10.1, @git.zone/tstest -> ^2.3.4, @push.rocks/smartfile -> ^11.2.5, @push.rocks/npmextra -> ^5.3.3, @push.rocks/smartchok -> ^1.1.1, @push.rocks/smartlog -> ^3.1.8, @push.rocks/smartpath -> ^6.0.0, prettier -> ^3.6.2
|
- Bump several dependencies: @git.zone/tsbuild -> ^2.6.4, @git.zone/tspublish -> ^1.10.1, @git.zone/tstest -> ^2.3.4, @push.rocks/smartfile -> ^11.2.5, @push.rocks/npmextra -> ^5.3.3, @push.rocks/smartchok -> ^1.1.1, @push.rocks/smartlog -> ^3.1.8, @push.rocks/smartpath -> ^6.0.0, prettier -> ^3.6.2
|
||||||
@@ -242,6 +343,7 @@ Update dependencies, add local Claude settings, and update gitignore template
|
|||||||
- Add pnpm onlyBuiltDependencies entries: esbuild and mongodb-memory-server
|
- Add pnpm onlyBuiltDependencies entries: esbuild and mongodb-memory-server
|
||||||
|
|
||||||
## 2025-08-16 - 1.18.3 - fix(services)
|
## 2025-08-16 - 1.18.3 - fix(services)
|
||||||
|
|
||||||
Simplify S3 endpoint handling in ServiceConfiguration to store host only
|
Simplify S3 endpoint handling in ServiceConfiguration to store host only
|
||||||
|
|
||||||
- S3_ENDPOINT now stores the raw host (e.g. 'localhost') instead of a full URL with protocol and port.
|
- S3_ENDPOINT now stores the raw host (e.g. 'localhost') instead of a full URL with protocol and port.
|
||||||
@@ -250,6 +352,7 @@ Simplify S3 endpoint handling in ServiceConfiguration to store host only
|
|||||||
- Consumers that previously relied on S3_ENDPOINT containing protocol and port should now construct the full endpoint URL using S3_USESSL, S3_HOST and S3_PORT.
|
- Consumers that previously relied on S3_ENDPOINT containing protocol and port should now construct the full endpoint URL using S3_USESSL, S3_HOST and S3_PORT.
|
||||||
|
|
||||||
## 2025-08-16 - 1.18.1 - fix(services)
|
## 2025-08-16 - 1.18.1 - fix(services)
|
||||||
|
|
||||||
Improve services and commit flow: stop AiDoc, use silent docker inspect, sync ports with logging, fix config loading, and bump deps
|
Improve services and commit flow: stop AiDoc, use silent docker inspect, sync ports with logging, fix config loading, and bump deps
|
||||||
|
|
||||||
- Ensure AiDoc is stopped after building commit recommendation to avoid resource leaks
|
- Ensure AiDoc is stopped after building commit recommendation to avoid resource leaks
|
||||||
@@ -261,6 +364,7 @@ Improve services and commit flow: stop AiDoc, use silent docker inspect, sync po
|
|||||||
- Add local Claude settings file (.claude/settings.local.json) with development permissions
|
- Add local Claude settings file (.claude/settings.local.json) with development permissions
|
||||||
|
|
||||||
## 2025-08-16 - 1.18.0 - feat(services)
|
## 2025-08-16 - 1.18.0 - feat(services)
|
||||||
|
|
||||||
Add Docker port mapping sync and reconfigure workflow for local services
|
Add Docker port mapping sync and reconfigure workflow for local services
|
||||||
|
|
||||||
- Add getPortMappings to DockerContainer to extract port bindings from docker inspect output
|
- Add getPortMappings to DockerContainer to extract port bindings from docker inspect output
|
||||||
@@ -273,6 +377,7 @@ Add Docker port mapping sync and reconfigure workflow for local services
|
|||||||
- Add .claude/settings.local.json (local permissions config) to repository
|
- Add .claude/settings.local.json (local permissions config) to repository
|
||||||
|
|
||||||
## 2025-08-15 - 1.17.5 - fix(services)
|
## 2025-08-15 - 1.17.5 - fix(services)
|
||||||
|
|
||||||
Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved MinIO integration
|
Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved MinIO integration
|
||||||
|
|
||||||
- Replaced S3_USER/S3_PASS with S3_ACCESSKEY/S3_SECRETKEY in ServiceConfiguration
|
- Replaced S3_USER/S3_PASS with S3_ACCESSKEY/S3_SECRETKEY in ServiceConfiguration
|
||||||
@@ -282,6 +387,7 @@ Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved
|
|||||||
- Added .claude/settings.local.json for local permission settings
|
- Added .claude/settings.local.json for local permission settings
|
||||||
|
|
||||||
## 2025-08-15 - 1.17.4 - fix(services)
|
## 2025-08-15 - 1.17.4 - fix(services)
|
||||||
|
|
||||||
Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved MinIO integration
|
Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved MinIO integration
|
||||||
|
|
||||||
- Replaced S3_USER/S3_PASS with S3_ACCESSKEY/S3_SECRETKEY in ServiceConfiguration
|
- Replaced S3_USER/S3_PASS with S3_ACCESSKEY/S3_SECRETKEY in ServiceConfiguration
|
||||||
@@ -290,12 +396,14 @@ Update S3 credentials naming and add S3_ENDPOINT/S3_USESSL support for improved
|
|||||||
- Updated ServiceManager to use new credential names in container setup and logging
|
- Updated ServiceManager to use new credential names in container setup and logging
|
||||||
|
|
||||||
## 2025-08-15 - 1.17.3 - fix(serviceconfig)
|
## 2025-08-15 - 1.17.3 - fix(serviceconfig)
|
||||||
|
|
||||||
Update service configuration to include dynamic MongoDB connection string and add local permissions settings
|
Update service configuration to include dynamic MongoDB connection string and add local permissions settings
|
||||||
|
|
||||||
- Added .claude/settings.local.json for local permissions configuration
|
- Added .claude/settings.local.json for local permissions configuration
|
||||||
- Updated ServiceConfiguration to compute and update MONGODB_URL based on current config values
|
- Updated ServiceConfiguration to compute and update MONGODB_URL based on current config values
|
||||||
|
|
||||||
## 2025-08-15 - 1.17.2 - fix(ci-test-services)
|
## 2025-08-15 - 1.17.2 - fix(ci-test-services)
|
||||||
|
|
||||||
Update CI/CD configurations, test settings, and Docker service for MongoDB.
|
Update CI/CD configurations, test settings, and Docker service for MongoDB.
|
||||||
|
|
||||||
- Add .claude/settings.local.json with updated permission settings
|
- Add .claude/settings.local.json with updated permission settings
|
||||||
@@ -304,6 +412,7 @@ Update CI/CD configurations, test settings, and Docker service for MongoDB.
|
|||||||
- Fix MongoDB Docker container command by adding '--bind_ip_all' for proper network binding
|
- Fix MongoDB Docker container command by adding '--bind_ip_all' for proper network binding
|
||||||
|
|
||||||
## 2025-08-15 - 1.17.1 - fix(services)
|
## 2025-08-15 - 1.17.1 - fix(services)
|
||||||
|
|
||||||
Improve services module logging and enhance MongoDB Compass integration
|
Improve services module logging and enhance MongoDB Compass integration
|
||||||
|
|
||||||
- Refactored services module to use centralized logger from gitzone.logging.ts
|
- Refactored services module to use centralized logger from gitzone.logging.ts
|
||||||
@@ -312,6 +421,7 @@ Improve services module logging and enhance MongoDB Compass integration
|
|||||||
- Consistent logging across all service commands
|
- Consistent logging across all service commands
|
||||||
|
|
||||||
## 2025-08-14 - 1.17.0 - feat(services)
|
## 2025-08-14 - 1.17.0 - feat(services)
|
||||||
|
|
||||||
Add comprehensive development services management for MongoDB and MinIO containers
|
Add comprehensive development services management for MongoDB and MinIO containers
|
||||||
|
|
||||||
- Implemented `gitzone services` command for managing local development services
|
- Implemented `gitzone services` command for managing local development services
|
||||||
@@ -325,6 +435,7 @@ Add comprehensive development services management for MongoDB and MinIO containe
|
|||||||
- Interactive confirmations for destructive operations
|
- Interactive confirmations for destructive operations
|
||||||
|
|
||||||
## 2025-08-08 - 1.16.10 - fix(format)
|
## 2025-08-08 - 1.16.10 - fix(format)
|
||||||
|
|
||||||
Improve concurrency control in caching and rollback modules, refine gitignore custom section handling, and enhance Prettier file processing.
|
Improve concurrency control in caching and rollback modules, refine gitignore custom section handling, and enhance Prettier file processing.
|
||||||
|
|
||||||
- Added mutex locking in ChangeCache and RollbackManager to prevent race conditions during manifest updates
|
- Added mutex locking in ChangeCache and RollbackManager to prevent race conditions during manifest updates
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@git.zone/cli",
|
"name": "@git.zone/cli",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "2.7.0",
|
"version": "2.12.1",
|
||||||
"description": "A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.",
|
"description": "A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.",
|
||||||
"main": "dist_ts/index.ts",
|
"main": "dist_ts/index.ts",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"@types/node": "^25.0.2"
|
"@types/node": "^25.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@git.zone/tsdoc": "^1.10.2",
|
"@git.zone/tsdoc": "^1.11.3",
|
||||||
"@git.zone/tspublish": "^1.10.3",
|
"@git.zone/tspublish": "^1.10.3",
|
||||||
"@push.rocks/commitinfo": "^1.0.12",
|
"@push.rocks/commitinfo": "^1.0.12",
|
||||||
"@push.rocks/early": "^4.0.4",
|
"@push.rocks/early": "^4.0.4",
|
||||||
|
|||||||
90
pnpm-lock.yaml
generated
90
pnpm-lock.yaml
generated
@@ -9,8 +9,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@git.zone/tsdoc':
|
'@git.zone/tsdoc':
|
||||||
specifier: ^1.10.2
|
specifier: ^1.11.3
|
||||||
version: 1.10.2(ws@8.18.3)(zod@3.25.76)
|
version: 1.11.3(ws@8.18.3)(zod@3.25.76)
|
||||||
'@git.zone/tspublish':
|
'@git.zone/tspublish':
|
||||||
specifier: ^1.10.3
|
specifier: ^1.10.3
|
||||||
version: 1.10.3
|
version: 1.10.3
|
||||||
@@ -520,8 +520,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-YD1qMYA/4eOuF57V0ccR+xo6ww1+QOYFA2K5gBPFBDNh9VdfvWxxDhOUybja8lT9PVMoli8PHG5WA5tKJkdXIQ==}
|
resolution: {integrity: sha512-YD1qMYA/4eOuF57V0ccR+xo6ww1+QOYFA2K5gBPFBDNh9VdfvWxxDhOUybja8lT9PVMoli8PHG5WA5tKJkdXIQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@git.zone/tsdoc@1.10.2':
|
'@git.zone/tsdoc@1.11.3':
|
||||||
resolution: {integrity: sha512-r4pKv74CH0KtzRvGdLioJd3DznSKmr8ZVE43QPFfGSNftH5P2eLAe5lc5nK8gCWb8mgEkb8WNfqtTL3Lkg+XyQ==}
|
resolution: {integrity: sha512-U6X9laKv9CTZiqtQpqVMZ2x3qKH1ucey3y16T5UQ70j7wza2GV9rwdkTIHgpYrWFBMSoh909T+ELH8qWbRqimw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@git.zone/tspublish@1.10.3':
|
'@git.zone/tspublish@1.10.3':
|
||||||
@@ -999,12 +999,18 @@ packages:
|
|||||||
'@push.rocks/qenv@6.1.3':
|
'@push.rocks/qenv@6.1.3':
|
||||||
resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==}
|
resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==}
|
||||||
|
|
||||||
|
'@push.rocks/smartagent@1.2.5':
|
||||||
|
resolution: {integrity: sha512-qV7zyHbp5p5ySg16uipjIdYzKM85fn5/l97pKlZz9awRZhOcvYblmypQRKHlMc+O2mVevxLY4Q/6pzYwI8UXvw==}
|
||||||
|
|
||||||
'@push.rocks/smartai@0.8.0':
|
'@push.rocks/smartai@0.8.0':
|
||||||
resolution: {integrity: sha512-guzi28meUDc3mydC8kpoA+4pzExRQqygXYFDD4qQSWPpIRHQ7qhpeNqJzrrGezT1yOH5Gb9taPEGwT56hI+nwQ==}
|
resolution: {integrity: sha512-guzi28meUDc3mydC8kpoA+4pzExRQqygXYFDD4qQSWPpIRHQ7qhpeNqJzrrGezT1yOH5Gb9taPEGwT56hI+nwQ==}
|
||||||
|
|
||||||
'@push.rocks/smartarchive@4.2.4':
|
'@push.rocks/smartarchive@4.2.4':
|
||||||
resolution: {integrity: sha512-uiqVAXPxmr8G5rv3uZvZFMOCt8l7cZC3nzvsy4YQqKf/VkPhKIEX+b7LkAeNlxPSYUiBQUkNRoawg9+5BaMcHg==}
|
resolution: {integrity: sha512-uiqVAXPxmr8G5rv3uZvZFMOCt8l7cZC3nzvsy4YQqKf/VkPhKIEX+b7LkAeNlxPSYUiBQUkNRoawg9+5BaMcHg==}
|
||||||
|
|
||||||
|
'@push.rocks/smartarchive@5.0.1':
|
||||||
|
resolution: {integrity: sha512-x4bie9IIdL9BZqBZLc8Pemp8xZOJGa6mXSVgKJRL4/Rw+E5N4rVHjQOYGRV75nC2mAMJh9GIbixuxLnWjj77ag==}
|
||||||
|
|
||||||
'@push.rocks/smartarray@1.1.0':
|
'@push.rocks/smartarray@1.1.0':
|
||||||
resolution: {integrity: sha512-b5YgBmUdglOJH8zeUf2ZWdPCoqySgwvkycRi2BhA9zVZHkpASh39Ej0q0fxFJetlUVyYqGfVoMVjbVrLFfFV7g==}
|
resolution: {integrity: sha512-b5YgBmUdglOJH8zeUf2ZWdPCoqySgwvkycRi2BhA9zVZHkpASh39Ej0q0fxFJetlUVyYqGfVoMVjbVrLFfFV7g==}
|
||||||
|
|
||||||
@@ -1042,6 +1048,9 @@ packages:
|
|||||||
'@push.rocks/smartdelay@3.0.5':
|
'@push.rocks/smartdelay@3.0.5':
|
||||||
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
|
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
|
||||||
|
|
||||||
|
'@push.rocks/smartdeno@1.2.0':
|
||||||
|
resolution: {integrity: sha512-6S1plCaMUVOZiRSflfoz9Fqk9phACCuKmc7Z6SfTvfl+p9VcPUmewKgaa/0QiLOpiI6ksfxdfmkS5Rw5HpYeIA==}
|
||||||
|
|
||||||
'@push.rocks/smartdiff@1.1.0':
|
'@push.rocks/smartdiff@1.1.0':
|
||||||
resolution: {integrity: sha512-AAz/unmko0C+g+60odOoK32PE3Ci3YLoB+zfg1LGLyVRCthcdzjqa1C2Km0MfG7IyJQKPdj8J5HPubtpm3ZeaQ==}
|
resolution: {integrity: sha512-AAz/unmko0C+g+60odOoK32PE3Ci3YLoB+zfg1LGLyVRCthcdzjqa1C2Km0MfG7IyJQKPdj8J5HPubtpm3ZeaQ==}
|
||||||
|
|
||||||
@@ -2704,9 +2713,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
|
resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
gpt-tokenizer@3.4.0:
|
|
||||||
resolution: {integrity: sha512-wxFLnhIXTDjYebd9A9pGl3e31ZpSypbpIJSOswbgop5jLte/AsZVDvjlbEuVFlsqZixVKqbcoNmRlFDf6pz/UQ==}
|
|
||||||
|
|
||||||
graceful-fs@4.2.10:
|
graceful-fs@4.2.10:
|
||||||
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
|
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
|
||||||
|
|
||||||
@@ -2905,8 +2911,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
|
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
isomorphic-git@1.36.0:
|
isomorphic-git@1.36.1:
|
||||||
resolution: {integrity: sha512-22tU165ptowHYoDEwYJy5EKRzpHiuLMliaR01fH9ZwaUj1z/IqE++tGpjw/pD6eCWoxiOp6TPWX434aJ9zA4Lg==}
|
resolution: {integrity: sha512-fC8SRT8MwoaXDK8G4z5biPEbqf2WyEJUb2MJ2ftSd39/UIlsnoZxLGux+lae0poLZO4AEcx6aUVOh5bV+P8zFA==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -5060,12 +5066,13 @@ snapshots:
|
|||||||
- '@swc/helpers'
|
- '@swc/helpers'
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@git.zone/tsdoc@1.10.2(ws@8.18.3)(zod@3.25.76)':
|
'@git.zone/tsdoc@1.11.3(ws@8.18.3)(zod@3.25.76)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@git.zone/tspublish': 1.10.3
|
'@git.zone/tspublish': 1.10.3
|
||||||
'@push.rocks/early': 4.0.4
|
'@push.rocks/early': 4.0.4
|
||||||
'@push.rocks/npmextra': 5.3.3
|
'@push.rocks/npmextra': 5.3.3
|
||||||
'@push.rocks/qenv': 6.1.3
|
'@push.rocks/qenv': 6.1.3
|
||||||
|
'@push.rocks/smartagent': 1.2.5(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
|
||||||
'@push.rocks/smartai': 0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
|
'@push.rocks/smartai': 0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
|
||||||
'@push.rocks/smartcli': 4.0.19
|
'@push.rocks/smartcli': 4.0.19
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@@ -5078,7 +5085,6 @@ snapshots:
|
|||||||
'@push.rocks/smartpath': 6.0.0
|
'@push.rocks/smartpath': 6.0.0
|
||||||
'@push.rocks/smartshell': 3.3.0
|
'@push.rocks/smartshell': 3.3.0
|
||||||
'@push.rocks/smarttime': 4.1.1
|
'@push.rocks/smarttime': 4.1.1
|
||||||
gpt-tokenizer: 3.4.0
|
|
||||||
typedoc: 0.28.15(typescript@5.9.3)
|
typedoc: 0.28.15(typescript@5.9.3)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -5877,6 +5883,30 @@ snapshots:
|
|||||||
'@push.rocks/smartlog': 3.1.10
|
'@push.rocks/smartlog': 3.1.10
|
||||||
'@push.rocks/smartpath': 6.0.0
|
'@push.rocks/smartpath': 6.0.0
|
||||||
|
|
||||||
|
'@push.rocks/smartagent@1.2.5(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)':
|
||||||
|
dependencies:
|
||||||
|
'@push.rocks/smartai': 0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
|
||||||
|
'@push.rocks/smartbrowser': 2.0.8(typescript@5.9.3)
|
||||||
|
'@push.rocks/smartdeno': 1.2.0
|
||||||
|
'@push.rocks/smartfs': 1.2.0
|
||||||
|
'@push.rocks/smartrequest': 5.0.1
|
||||||
|
'@push.rocks/smartshell': 3.3.0
|
||||||
|
minimatch: 10.1.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@nuxt/kit'
|
||||||
|
- aws-crt
|
||||||
|
- bare-abort-controller
|
||||||
|
- bare-buffer
|
||||||
|
- bufferutil
|
||||||
|
- react
|
||||||
|
- react-native-b4a
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
- utf-8-validate
|
||||||
|
- vue
|
||||||
|
- ws
|
||||||
|
- zod
|
||||||
|
|
||||||
'@push.rocks/smartai@0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)':
|
'@push.rocks/smartai@0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@anthropic-ai/sdk': 0.65.0(zod@3.25.76)
|
'@anthropic-ai/sdk': 0.65.0(zod@3.25.76)
|
||||||
@@ -5923,6 +5953,26 @@ snapshots:
|
|||||||
- react-native-b4a
|
- react-native-b4a
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@push.rocks/smartarchive@5.0.1':
|
||||||
|
dependencies:
|
||||||
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
|
'@push.rocks/smartfile': 13.1.2
|
||||||
|
'@push.rocks/smartpath': 6.0.0
|
||||||
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
|
'@push.rocks/smartrequest': 4.4.2
|
||||||
|
'@push.rocks/smartrx': 3.0.10
|
||||||
|
'@push.rocks/smartstream': 3.2.5
|
||||||
|
'@push.rocks/smartunique': 3.0.9
|
||||||
|
'@push.rocks/smarturl': 3.1.0
|
||||||
|
'@types/tar-stream': 3.1.4
|
||||||
|
fflate: 0.8.2
|
||||||
|
file-type: 21.1.1
|
||||||
|
tar-stream: 3.1.7
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bare-abort-controller
|
||||||
|
- react-native-b4a
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@push.rocks/smartarray@1.1.0': {}
|
'@push.rocks/smartarray@1.1.0': {}
|
||||||
|
|
||||||
'@push.rocks/smartbrowser@2.0.8(typescript@5.9.3)':
|
'@push.rocks/smartbrowser@2.0.8(typescript@5.9.3)':
|
||||||
@@ -6046,6 +6096,18 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartpromise': 4.2.3
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
|
|
||||||
|
'@push.rocks/smartdeno@1.2.0':
|
||||||
|
dependencies:
|
||||||
|
'@push.rocks/smartarchive': 5.0.1
|
||||||
|
'@push.rocks/smartfs': 1.2.0
|
||||||
|
'@push.rocks/smartpath': 6.0.0
|
||||||
|
'@push.rocks/smartshell': 3.3.0
|
||||||
|
'@push.rocks/smartunique': 3.0.9
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bare-abort-controller
|
||||||
|
- react-native-b4a
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@push.rocks/smartdiff@1.1.0':
|
'@push.rocks/smartdiff@1.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
diff: 8.0.2
|
diff: 8.0.2
|
||||||
@@ -6177,7 +6239,7 @@ snapshots:
|
|||||||
'@push.rocks/smarttime': 4.1.1
|
'@push.rocks/smarttime': 4.1.1
|
||||||
'@types/diff': 8.0.0
|
'@types/diff': 8.0.0
|
||||||
diff: 8.0.2
|
diff: 8.0.2
|
||||||
isomorphic-git: 1.36.0
|
isomorphic-git: 1.36.1
|
||||||
minimatch: 10.1.1
|
minimatch: 10.1.1
|
||||||
|
|
||||||
'@push.rocks/smartguard@3.1.0':
|
'@push.rocks/smartguard@3.1.0':
|
||||||
@@ -8359,8 +8421,6 @@ snapshots:
|
|||||||
p-cancelable: 3.0.0
|
p-cancelable: 3.0.0
|
||||||
responselike: 3.0.0
|
responselike: 3.0.0
|
||||||
|
|
||||||
gpt-tokenizer@3.4.0: {}
|
|
||||||
|
|
||||||
graceful-fs@4.2.10: {}
|
graceful-fs@4.2.10: {}
|
||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
@@ -8573,7 +8633,7 @@ snapshots:
|
|||||||
|
|
||||||
isexe@3.1.1: {}
|
isexe@3.1.1: {}
|
||||||
|
|
||||||
isomorphic-git@1.36.0:
|
isomorphic-git@1.36.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
async-lock: 1.4.1
|
async-lock: 1.4.1
|
||||||
clean-git-ref: 2.0.1
|
clean-git-ref: 2.0.1
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ The format module is responsible for project standardization:
|
|||||||
The commit module's version bumping has been refactored to eliminate npm command dependencies:
|
The commit module's version bumping has been refactored to eliminate npm command dependencies:
|
||||||
|
|
||||||
**Changes:**
|
**Changes:**
|
||||||
|
|
||||||
- Removed `bumpNpmVersion()` - was causing npm warnings to pollute deno.json
|
- Removed `bumpNpmVersion()` - was causing npm warnings to pollute deno.json
|
||||||
- Removed `syncVersionToDenoJson()` - no longer needed with unified approach
|
- Removed `syncVersionToDenoJson()` - no longer needed with unified approach
|
||||||
- Removed separate `bumpDenoVersion()` - replaced by unified implementation
|
- Removed separate `bumpDenoVersion()` - replaced by unified implementation
|
||||||
@@ -104,6 +105,7 @@ The commit module's version bumping has been refactored to eliminate npm command
|
|||||||
- Unified `bumpProjectVersion()` - handles npm/deno/both with single clean code path
|
- Unified `bumpProjectVersion()` - handles npm/deno/both with single clean code path
|
||||||
|
|
||||||
**Benefits:**
|
**Benefits:**
|
||||||
|
|
||||||
- No npm warning pollution in version fields
|
- No npm warning pollution in version fields
|
||||||
- Full control over version bumping process
|
- Full control over version bumping process
|
||||||
- Simpler git history (no amending, no force-tagging)
|
- Simpler git history (no amending, no force-tagging)
|
||||||
@@ -115,11 +117,13 @@ The commit module's version bumping has been refactored to eliminate npm command
|
|||||||
The commit module now supports `-y/--yes` flag for non-interactive commits:
|
The commit module now supports `-y/--yes` flag for non-interactive commits:
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
- `gitzone commit -y` - Auto-accepts AI recommendations without prompts
|
- `gitzone commit -y` - Auto-accepts AI recommendations without prompts
|
||||||
- `gitzone commit -yp` - Auto-accepts and pushes to origin
|
- `gitzone commit -yp` - Auto-accepts and pushes to origin
|
||||||
- Separate `-p/--push` flag controls push behavior
|
- Separate `-p/--push` flag controls push behavior
|
||||||
|
|
||||||
**Implementation:**
|
**Implementation:**
|
||||||
|
|
||||||
- Creates AnswerBucket programmatically when `-y` flag detected
|
- Creates AnswerBucket programmatically when `-y` flag detected
|
||||||
- Preserves all UI output for transparency
|
- Preserves all UI output for transparency
|
||||||
- Fully backward compatible with interactive mode
|
- Fully backward compatible with interactive mode
|
||||||
@@ -248,10 +252,12 @@ gitzone format --clean-backups
|
|||||||
The project has been fully migrated from @push.rocks/smartfile v11 to v13, which introduced a major breaking change where filesystem operations were split into two separate packages:
|
The project has been fully migrated from @push.rocks/smartfile v11 to v13, which introduced a major breaking change where filesystem operations were split into two separate packages:
|
||||||
|
|
||||||
**Packages:**
|
**Packages:**
|
||||||
|
|
||||||
- `@push.rocks/smartfile` v13.0.1 - File representation classes (SmartFile, StreamFile, VirtualDirectory)
|
- `@push.rocks/smartfile` v13.0.1 - File representation classes (SmartFile, StreamFile, VirtualDirectory)
|
||||||
- `@push.rocks/smartfs` v1.1.0 - Filesystem operations (read, write, exists, stat, etc.)
|
- `@push.rocks/smartfs` v1.1.0 - Filesystem operations (read, write, exists, stat, etc.)
|
||||||
|
|
||||||
**Key API Changes:**
|
**Key API Changes:**
|
||||||
|
|
||||||
1. **File Reading**:
|
1. **File Reading**:
|
||||||
- Old: `plugins.smartfile.fs.toStringSync(path)` or `plugins.smartfile.fs.toObjectSync(path)`
|
- Old: `plugins.smartfile.fs.toStringSync(path)` or `plugins.smartfile.fs.toObjectSync(path)`
|
||||||
- New: `await plugins.smartfs.file(path).encoding('utf8').read()` + JSON.parse if needed
|
- New: `await plugins.smartfs.file(path).encoding('utf8').read()` + JSON.parse if needed
|
||||||
@@ -290,13 +296,15 @@ The project has been fully migrated from @push.rocks/smartfile v11 to v13, which
|
|||||||
All sync methods must become async. Functions that were previously synchronous (like `getProjectName()`) now return `Promise<T>` and must be awaited.
|
All sync methods must become async. Functions that were previously synchronous (like `getProjectName()`) now return `Promise<T>` and must be awaited.
|
||||||
|
|
||||||
**Affected Modules:**
|
**Affected Modules:**
|
||||||
- ts/mod_format/* (largest area - 15+ files)
|
|
||||||
- ts/mod_commit/* (version bumping)
|
- ts/mod_format/\* (largest area - 15+ files)
|
||||||
- ts/mod_services/* (configuration management)
|
- ts/mod_commit/\* (version bumping)
|
||||||
- ts/mod_meta/* (meta repository management)
|
- ts/mod_services/\* (configuration management)
|
||||||
- ts/mod_standard/* (template listing)
|
- ts/mod_meta/\* (meta repository management)
|
||||||
- ts/mod_template/* (template operations)
|
- ts/mod_standard/\* (template listing)
|
||||||
|
- ts/mod_template/\* (template operations)
|
||||||
|
|
||||||
**Previous API Changes:**
|
**Previous API Changes:**
|
||||||
|
|
||||||
- smartnpm requires instance creation: `new NpmRegistry()`
|
- smartnpm requires instance creation: `new NpmRegistry()`
|
||||||
- Type imports use `import type` for proper verbatim module syntax
|
- Type imports use `import type` for proper verbatim module syntax
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
# GitZone Services Command Implementation Plan
|
# GitZone Services Command Implementation Plan
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Implement the `gitzone services` command to manage MongoDB and MinIO containers for development projects.
|
Implement the `gitzone services` command to manage MongoDB and MinIO containers for development projects.
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
### Module Structure Setup
|
### Module Structure Setup
|
||||||
|
|
||||||
- [x] Create `ts/mod_services/` directory
|
- [x] Create `ts/mod_services/` directory
|
||||||
- [x] Create `mod.plugins.ts` with required imports
|
- [x] Create `mod.plugins.ts` with required imports
|
||||||
- [x] Create `helpers.ts` with utility functions
|
- [x] Create `helpers.ts` with utility functions
|
||||||
@@ -15,6 +17,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
- [x] Create `index.ts` with main command logic
|
- [x] Create `index.ts` with main command logic
|
||||||
|
|
||||||
### Core Functionality
|
### Core Functionality
|
||||||
|
|
||||||
- [x] Implement ServiceConfiguration class
|
- [x] Implement ServiceConfiguration class
|
||||||
- [x] Load/create `.nogit/env.json` configuration
|
- [x] Load/create `.nogit/env.json` configuration
|
||||||
- [x] Generate random available ports (20000-30000 range)
|
- [x] Generate random available ports (20000-30000 range)
|
||||||
@@ -37,6 +40,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
- [x] Generate MongoDB Compass connection strings
|
- [x] Generate MongoDB Compass connection strings
|
||||||
|
|
||||||
### Commands Implementation
|
### Commands Implementation
|
||||||
|
|
||||||
- [x] `start` command - Start services (mongo|s3|all)
|
- [x] `start` command - Start services (mongo|s3|all)
|
||||||
- [x] `stop` command - Stop services (mongo|s3|all)
|
- [x] `stop` command - Stop services (mongo|s3|all)
|
||||||
- [x] `restart` command - Restart services (mongo|s3|all)
|
- [x] `restart` command - Restart services (mongo|s3|all)
|
||||||
@@ -48,12 +52,14 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
- [x] `clean` command - Remove containers and data
|
- [x] `clean` command - Remove containers and data
|
||||||
|
|
||||||
### Integration
|
### Integration
|
||||||
|
|
||||||
- [x] Add `@push.rocks/smartshell` to main plugins.ts
|
- [x] Add `@push.rocks/smartshell` to main plugins.ts
|
||||||
- [x] Add `@push.rocks/smartnetwork` to main plugins.ts
|
- [x] Add `@push.rocks/smartnetwork` to main plugins.ts
|
||||||
- [x] Add `@push.rocks/smartinteraction` to main plugins.ts
|
- [x] Add `@push.rocks/smartinteraction` to main plugins.ts
|
||||||
- [x] Register services command in `gitzone.cli.ts`
|
- [x] Register services command in `gitzone.cli.ts`
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- [x] Auto-configuration with smart defaults
|
- [x] Auto-configuration with smart defaults
|
||||||
- [x] Random port assignment to avoid conflicts
|
- [x] Random port assignment to avoid conflicts
|
||||||
- [x] Project isolation with unique container names
|
- [x] Project isolation with unique container names
|
||||||
@@ -65,6 +71,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
- [x] MongoDB Compass connection string with network IP
|
- [x] MongoDB Compass connection string with network IP
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- [ ] Test service start/stop operations
|
- [ ] Test service start/stop operations
|
||||||
- [ ] Test configuration creation and updates
|
- [ ] Test configuration creation and updates
|
||||||
- [ ] Test port collision handling
|
- [ ] Test port collision handling
|
||||||
@@ -73,6 +80,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
- [ ] Test all command variations
|
- [ ] Test all command variations
|
||||||
|
|
||||||
## Configuration Format
|
## Configuration Format
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"PROJECT_NAME": "derived-from-package-name",
|
"PROJECT_NAME": "derived-from-package-name",
|
||||||
@@ -91,6 +99,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Command Examples
|
## Command Examples
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gitzone services start # Start all services
|
gitzone services start # Start all services
|
||||||
gitzone services start mongo # Start only MongoDB
|
gitzone services start mongo # Start only MongoDB
|
||||||
@@ -104,10 +113,12 @@ gitzone services clean # Remove containers and data
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Progress Notes
|
## Progress Notes
|
||||||
|
|
||||||
Implementation started: 2025-08-14
|
Implementation started: 2025-08-14
|
||||||
Implementation completed: 2025-08-14
|
Implementation completed: 2025-08-14
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
Successfully implemented the `gitzone services` command in TypeScript, providing a complete replacement for the `services.sh` shell script. The implementation includes:
|
Successfully implemented the `gitzone services` command in TypeScript, providing a complete replacement for the `services.sh` shell script. The implementation includes:
|
||||||
|
|
||||||
1. **Complete Docker service management** for MongoDB and MinIO containers
|
1. **Complete Docker service management** for MongoDB and MinIO containers
|
||||||
@@ -118,4 +129,4 @@ Successfully implemented the `gitzone services` command in TypeScript, providing
|
|||||||
6. **Interactive confirmations** for destructive operations
|
6. **Interactive confirmations** for destructive operations
|
||||||
7. **Comprehensive command set** including start, stop, restart, status, config, compass, logs, remove, and clean commands
|
7. **Comprehensive command set** including start, stop, restart, status, config, compass, logs, remove, and clean commands
|
||||||
|
|
||||||
The module is fully integrated into the gitzone CLI and ready for testing.
|
The module is fully integrated into the gitzone CLI and ready for testing.
|
||||||
|
|||||||
1
test
Submodule
1
test
Submodule
Submodule test added at 0b89443584
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/cli',
|
name: '@git.zone/cli',
|
||||||
version: '2.7.0',
|
version: '2.12.1',
|
||||||
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ export let run = async () => {
|
|||||||
interactive: argvArg.interactive !== false,
|
interactive: argvArg.interactive !== false,
|
||||||
parallel: argvArg.parallel !== false,
|
parallel: argvArg.parallel !== false,
|
||||||
verbose: argvArg.verbose,
|
verbose: argvArg.verbose,
|
||||||
|
diff: argvArg.diff,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,20 @@ import * as ui from './mod.ui.js';
|
|||||||
import { ReleaseConfig } from '../mod_config/classes.releaseconfig.js';
|
import { ReleaseConfig } from '../mod_config/classes.releaseconfig.js';
|
||||||
|
|
||||||
export const run = async (argvArg: any) => {
|
export const run = async (argvArg: any) => {
|
||||||
// Check if release flag is set and validate registries early
|
// Read commit config from npmextra.json
|
||||||
|
const npmextraConfig = new plugins.npmextra.Npmextra();
|
||||||
|
const gitzoneConfig = npmextraConfig.dataFor<{
|
||||||
|
commit?: {
|
||||||
|
alwaysTest?: boolean;
|
||||||
|
alwaysBuild?: boolean;
|
||||||
|
};
|
||||||
|
}>('@git.zone/cli', {});
|
||||||
|
const commitConfig = gitzoneConfig.commit || {};
|
||||||
|
|
||||||
|
// Check flags and merge with config options
|
||||||
const wantsRelease = !!(argvArg.r || argvArg.release);
|
const wantsRelease = !!(argvArg.r || argvArg.release);
|
||||||
const wantsBuild = !!(argvArg.b || argvArg.build);
|
const wantsTest = !!(argvArg.t || argvArg.test || commitConfig.alwaysTest);
|
||||||
|
const wantsBuild = !!(argvArg.b || argvArg.build || commitConfig.alwaysBuild);
|
||||||
let releaseConfig: ReleaseConfig | null = null;
|
let releaseConfig: ReleaseConfig | null = null;
|
||||||
|
|
||||||
if (wantsRelease) {
|
if (wantsRelease) {
|
||||||
@@ -28,6 +39,7 @@ export const run = async (argvArg: any) => {
|
|||||||
ui.printExecutionPlan({
|
ui.printExecutionPlan({
|
||||||
autoAccept: !!(argvArg.y || argvArg.yes),
|
autoAccept: !!(argvArg.y || argvArg.yes),
|
||||||
push: !!(argvArg.p || argvArg.push),
|
push: !!(argvArg.p || argvArg.push),
|
||||||
|
test: wantsTest,
|
||||||
build: wantsBuild,
|
build: wantsBuild,
|
||||||
release: wantsRelease,
|
release: wantsRelease,
|
||||||
format: !!argvArg.format,
|
format: !!argvArg.format,
|
||||||
@@ -39,6 +51,21 @@ export const run = async (argvArg: any) => {
|
|||||||
await formatMod.run();
|
await formatMod.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run tests early to fail fast before analysis
|
||||||
|
if (wantsTest) {
|
||||||
|
ui.printHeader('🧪 Running tests...');
|
||||||
|
const smartshellForTest = new plugins.smartshell.Smartshell({
|
||||||
|
executor: 'bash',
|
||||||
|
sourceFilePaths: [],
|
||||||
|
});
|
||||||
|
const testResult = await smartshellForTest.exec('pnpm test');
|
||||||
|
if (testResult.exitCode !== 0) {
|
||||||
|
logger.log('error', 'Tests failed. Aborting commit.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
logger.log('success', 'All tests passed.');
|
||||||
|
}
|
||||||
|
|
||||||
ui.printHeader('🔍 Analyzing repository changes...');
|
ui.printHeader('🔍 Analyzing repository changes...');
|
||||||
|
|
||||||
const aidoc = new plugins.tsdoc.AiDoc();
|
const aidoc = new plugins.tsdoc.AiDoc();
|
||||||
@@ -161,6 +188,7 @@ export const run = async (argvArg: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine total steps based on options
|
// Determine total steps based on options
|
||||||
|
// Note: test runs early (like format) so not counted in numbered steps
|
||||||
const willPush = answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true');
|
const willPush = answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true');
|
||||||
const willRelease = answerBucket.getAnswerFor('createRelease') && releaseConfig?.hasRegistries();
|
const willRelease = answerBucket.getAnswerFor('createRelease') && releaseConfig?.hasRegistries();
|
||||||
let totalSteps = 5; // Base steps: commitinfo, changelog, staging, commit, version
|
let totalSteps = 5; // Base steps: commitinfo, changelog, staging, commit, version
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface ICommitSummary {
|
|||||||
interface IExecutionPlanOptions {
|
interface IExecutionPlanOptions {
|
||||||
autoAccept: boolean;
|
autoAccept: boolean;
|
||||||
push: boolean;
|
push: boolean;
|
||||||
|
test: boolean;
|
||||||
build: boolean;
|
build: boolean;
|
||||||
release: boolean;
|
release: boolean;
|
||||||
format: boolean;
|
format: boolean;
|
||||||
@@ -64,6 +65,7 @@ export function printExecutionPlan(options: IExecutionPlanOptions): void {
|
|||||||
console.log(' Options:');
|
console.log(' Options:');
|
||||||
console.log(` Auto-accept ${options.autoAccept ? '✓ enabled (-y)' : '○ interactive mode'}`);
|
console.log(` Auto-accept ${options.autoAccept ? '✓ enabled (-y)' : '○ interactive mode'}`);
|
||||||
console.log(` Push to remote ${options.push ? '✓ enabled (-p)' : '○ disabled'}`);
|
console.log(` Push to remote ${options.push ? '✓ enabled (-p)' : '○ disabled'}`);
|
||||||
|
console.log(` Test first ${options.test ? '✓ enabled (-t)' : '○ disabled'}`);
|
||||||
console.log(` Build & verify ${options.build ? '✓ enabled (-b)' : '○ disabled'}`);
|
console.log(` Build & verify ${options.build ? '✓ enabled (-b)' : '○ disabled'}`);
|
||||||
console.log(` Release to npm ${options.release ? '✓ enabled (-r)' : '○ disabled'}`);
|
console.log(` Release to npm ${options.release ? '✓ enabled (-r)' : '○ disabled'}`);
|
||||||
if (options.format) {
|
if (options.format) {
|
||||||
@@ -77,6 +79,9 @@ export function printExecutionPlan(options: IExecutionPlanOptions): void {
|
|||||||
if (options.format) {
|
if (options.format) {
|
||||||
console.log(` ${stepNum++}. Format project files`);
|
console.log(` ${stepNum++}. Format project files`);
|
||||||
}
|
}
|
||||||
|
if (options.test) {
|
||||||
|
console.log(` ${stepNum++}. Run tests`);
|
||||||
|
}
|
||||||
console.log(` ${stepNum++}. Analyze repository changes`);
|
console.log(` ${stepNum++}. Analyze repository changes`);
|
||||||
console.log(` ${stepNum++}. Bake commit info into code`);
|
console.log(` ${stepNum++}. Bake commit info into code`);
|
||||||
console.log(` ${stepNum++}. Generate changelog.md`);
|
console.log(` ${stepNum++}. Generate changelog.md`);
|
||||||
|
|||||||
104
ts/mod_config/classes.commitconfig.ts
Normal file
104
ts/mod_config/classes.commitconfig.ts
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
|
||||||
|
export interface ICommitConfig {
|
||||||
|
alwaysTest: boolean;
|
||||||
|
alwaysBuild: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages commit configuration stored in npmextra.json
|
||||||
|
* under @git.zone/cli.commit namespace
|
||||||
|
*/
|
||||||
|
export class CommitConfig {
|
||||||
|
private cwd: string;
|
||||||
|
private config: ICommitConfig;
|
||||||
|
|
||||||
|
constructor(cwd: string = process.cwd()) {
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.config = { alwaysTest: false, alwaysBuild: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a CommitConfig instance from current working directory
|
||||||
|
*/
|
||||||
|
public static async fromCwd(cwd: string = process.cwd()): Promise<CommitConfig> {
|
||||||
|
const instance = new CommitConfig(cwd);
|
||||||
|
await instance.load();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load configuration from npmextra.json
|
||||||
|
*/
|
||||||
|
public async load(): Promise<void> {
|
||||||
|
const npmextraInstance = new plugins.npmextra.Npmextra(this.cwd);
|
||||||
|
const gitzoneConfig = npmextraInstance.dataFor<any>('@git.zone/cli', {});
|
||||||
|
|
||||||
|
this.config = {
|
||||||
|
alwaysTest: gitzoneConfig?.commit?.alwaysTest ?? false,
|
||||||
|
alwaysBuild: gitzoneConfig?.commit?.alwaysBuild ?? false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save configuration to npmextra.json
|
||||||
|
*/
|
||||||
|
public async save(): Promise<void> {
|
||||||
|
const npmextraPath = plugins.path.join(this.cwd, 'npmextra.json');
|
||||||
|
let npmextraData: any = {};
|
||||||
|
|
||||||
|
// Read existing npmextra.json
|
||||||
|
if (await plugins.smartfs.file(npmextraPath).exists()) {
|
||||||
|
const content = await plugins.smartfs.file(npmextraPath).encoding('utf8').read();
|
||||||
|
npmextraData = JSON.parse(content as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure @git.zone/cli namespace exists
|
||||||
|
if (!npmextraData['@git.zone/cli']) {
|
||||||
|
npmextraData['@git.zone/cli'] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure commit object exists
|
||||||
|
if (!npmextraData['@git.zone/cli'].commit) {
|
||||||
|
npmextraData['@git.zone/cli'].commit = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update commit settings
|
||||||
|
npmextraData['@git.zone/cli'].commit.alwaysTest = this.config.alwaysTest;
|
||||||
|
npmextraData['@git.zone/cli'].commit.alwaysBuild = this.config.alwaysBuild;
|
||||||
|
|
||||||
|
// Write back to file
|
||||||
|
await plugins.smartfs
|
||||||
|
.file(npmextraPath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.write(JSON.stringify(npmextraData, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get alwaysTest setting
|
||||||
|
*/
|
||||||
|
public getAlwaysTest(): boolean {
|
||||||
|
return this.config.alwaysTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set alwaysTest setting
|
||||||
|
*/
|
||||||
|
public setAlwaysTest(value: boolean): void {
|
||||||
|
this.config.alwaysTest = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get alwaysBuild setting
|
||||||
|
*/
|
||||||
|
public getAlwaysBuild(): boolean {
|
||||||
|
return this.config.alwaysBuild;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set alwaysBuild setting
|
||||||
|
*/
|
||||||
|
public setAlwaysBuild(value: boolean): void {
|
||||||
|
this.config.alwaysBuild = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.js';
|
||||||
import { ReleaseConfig } from './classes.releaseconfig.js';
|
import { ReleaseConfig } from './classes.releaseconfig.js';
|
||||||
|
import { CommitConfig } from './classes.commitconfig.js';
|
||||||
import { runFormatter, type ICheckResult } from '../mod_format/index.js';
|
import { runFormatter, type ICheckResult } from '../mod_format/index.js';
|
||||||
|
|
||||||
export { ReleaseConfig };
|
export { ReleaseConfig, CommitConfig };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format npmextra.json with diff preview
|
* Format npmextra.json with diff preview
|
||||||
@@ -55,6 +56,12 @@ export const run = async (argvArg: any) => {
|
|||||||
case 'accessLevel':
|
case 'accessLevel':
|
||||||
await handleAccessLevel(value);
|
await handleAccessLevel(value);
|
||||||
break;
|
break;
|
||||||
|
case 'commit':
|
||||||
|
await handleCommit(argvArg._?.[2], argvArg._?.[3]);
|
||||||
|
break;
|
||||||
|
case 'services':
|
||||||
|
await handleServices();
|
||||||
|
break;
|
||||||
case 'help':
|
case 'help':
|
||||||
showHelp();
|
showHelp();
|
||||||
break;
|
break;
|
||||||
@@ -70,7 +77,7 @@ export const run = async (argvArg: any) => {
|
|||||||
async function handleInteractiveMenu(): Promise<void> {
|
async function handleInteractiveMenu(): Promise<void> {
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('╭─────────────────────────────────────────────────────────────╮');
|
console.log('╭─────────────────────────────────────────────────────────────╮');
|
||||||
console.log('│ gitzone config - Release Configuration │');
|
console.log('│ gitzone config - Project Configuration │');
|
||||||
console.log('╰─────────────────────────────────────────────────────────────╯');
|
console.log('╰─────────────────────────────────────────────────────────────╯');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
@@ -86,6 +93,8 @@ async function handleInteractiveMenu(): Promise<void> {
|
|||||||
{ name: 'Remove a registry', value: 'remove' },
|
{ name: 'Remove a registry', value: 'remove' },
|
||||||
{ name: 'Clear all registries', value: 'clear' },
|
{ name: 'Clear all registries', value: 'clear' },
|
||||||
{ name: 'Set access level (public/private)', value: 'access' },
|
{ name: 'Set access level (public/private)', value: 'access' },
|
||||||
|
{ name: 'Configure commit options', value: 'commit' },
|
||||||
|
{ name: 'Configure services', value: 'services' },
|
||||||
{ name: 'Show help', value: 'help' },
|
{ name: 'Show help', value: 'help' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -108,6 +117,12 @@ async function handleInteractiveMenu(): Promise<void> {
|
|||||||
case 'access':
|
case 'access':
|
||||||
await handleAccessLevel();
|
await handleAccessLevel();
|
||||||
break;
|
break;
|
||||||
|
case 'commit':
|
||||||
|
await handleCommit();
|
||||||
|
break;
|
||||||
|
case 'services':
|
||||||
|
await handleServices();
|
||||||
|
break;
|
||||||
case 'help':
|
case 'help':
|
||||||
showHelp();
|
showHelp();
|
||||||
break;
|
break;
|
||||||
@@ -278,6 +293,113 @@ async function handleAccessLevel(level?: string): Promise<void> {
|
|||||||
await formatNpmextraWithDiff();
|
await formatNpmextraWithDiff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle commit configuration
|
||||||
|
*/
|
||||||
|
async function handleCommit(setting?: string, value?: string): Promise<void> {
|
||||||
|
const config = await CommitConfig.fromCwd();
|
||||||
|
|
||||||
|
// No setting = interactive mode
|
||||||
|
if (!setting) {
|
||||||
|
await handleCommitInteractive(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direct setting
|
||||||
|
switch (setting) {
|
||||||
|
case 'alwaysTest':
|
||||||
|
await handleCommitSetting(config, 'alwaysTest', value);
|
||||||
|
break;
|
||||||
|
case 'alwaysBuild':
|
||||||
|
await handleCommitSetting(config, 'alwaysBuild', value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
plugins.logger.log('error', `Unknown commit setting: ${setting}`);
|
||||||
|
showCommitHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interactive commit configuration
|
||||||
|
*/
|
||||||
|
async function handleCommitInteractive(config: CommitConfig): Promise<void> {
|
||||||
|
console.log('');
|
||||||
|
console.log('╭─────────────────────────────────────────────────────────────╮');
|
||||||
|
console.log('│ Commit Configuration │');
|
||||||
|
console.log('╰─────────────────────────────────────────────────────────────╯');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
const interactInstance = new plugins.smartinteract.SmartInteract();
|
||||||
|
const response = await interactInstance.askQuestion({
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'commitOptions',
|
||||||
|
message: 'Select commit options to enable:',
|
||||||
|
choices: [
|
||||||
|
{ name: 'Always run tests before commit (-t)', value: 'alwaysTest' },
|
||||||
|
{ name: 'Always build after commit (-b)', value: 'alwaysBuild' },
|
||||||
|
],
|
||||||
|
default: [
|
||||||
|
...(config.getAlwaysTest() ? ['alwaysTest'] : []),
|
||||||
|
...(config.getAlwaysBuild() ? ['alwaysBuild'] : []),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const selected = (response as any).value || [];
|
||||||
|
config.setAlwaysTest(selected.includes('alwaysTest'));
|
||||||
|
config.setAlwaysBuild(selected.includes('alwaysBuild'));
|
||||||
|
await config.save();
|
||||||
|
|
||||||
|
plugins.logger.log('success', 'Commit configuration updated');
|
||||||
|
await formatNpmextraWithDiff();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a specific commit setting
|
||||||
|
*/
|
||||||
|
async function handleCommitSetting(config: CommitConfig, setting: string, value?: string): Promise<void> {
|
||||||
|
// Parse boolean value
|
||||||
|
const boolValue = value === 'true' || value === '1' || value === 'on';
|
||||||
|
|
||||||
|
if (setting === 'alwaysTest') {
|
||||||
|
config.setAlwaysTest(boolValue);
|
||||||
|
} else if (setting === 'alwaysBuild') {
|
||||||
|
config.setAlwaysBuild(boolValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
await config.save();
|
||||||
|
plugins.logger.log('success', `Set ${setting} to ${boolValue}`);
|
||||||
|
await formatNpmextraWithDiff();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show help for commit subcommand
|
||||||
|
*/
|
||||||
|
function showCommitHelp(): void {
|
||||||
|
console.log('');
|
||||||
|
console.log('Usage: gitzone config commit [setting] [value]');
|
||||||
|
console.log('');
|
||||||
|
console.log('Settings:');
|
||||||
|
console.log(' alwaysTest [true|false] Always run tests before commit');
|
||||||
|
console.log(' alwaysBuild [true|false] Always build after commit');
|
||||||
|
console.log('');
|
||||||
|
console.log('Examples:');
|
||||||
|
console.log(' gitzone config commit # Interactive mode');
|
||||||
|
console.log(' gitzone config commit alwaysTest true');
|
||||||
|
console.log(' gitzone config commit alwaysBuild false');
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle services configuration
|
||||||
|
*/
|
||||||
|
async function handleServices(): Promise<void> {
|
||||||
|
// Import and use ServiceManager's configureServices
|
||||||
|
const { ServiceManager } = await import('../mod_services/classes.servicemanager.js');
|
||||||
|
const serviceManager = new ServiceManager();
|
||||||
|
await serviceManager.init();
|
||||||
|
await serviceManager.configureServices();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show help for config command
|
* Show help for config command
|
||||||
*/
|
*/
|
||||||
@@ -291,6 +413,8 @@ function showHelp(): void {
|
|||||||
console.log(' remove [url] Remove a registry URL');
|
console.log(' remove [url] Remove a registry URL');
|
||||||
console.log(' clear Clear all registries');
|
console.log(' clear Clear all registries');
|
||||||
console.log(' access [public|private] Set npm access level for publishing');
|
console.log(' access [public|private] Set npm access level for publishing');
|
||||||
|
console.log(' commit [setting] [value] Configure commit options');
|
||||||
|
console.log(' services Configure which services are enabled');
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log('Examples:');
|
console.log('Examples:');
|
||||||
console.log(' gitzone config show');
|
console.log(' gitzone config show');
|
||||||
@@ -300,5 +424,8 @@ function showHelp(): void {
|
|||||||
console.log(' gitzone config clear');
|
console.log(' gitzone config clear');
|
||||||
console.log(' gitzone config access public');
|
console.log(' gitzone config access public');
|
||||||
console.log(' gitzone config access private');
|
console.log(' gitzone config access private');
|
||||||
|
console.log(' gitzone config commit # Interactive');
|
||||||
|
console.log(' gitzone config commit alwaysTest true');
|
||||||
|
console.log(' gitzone config services # Interactive');
|
||||||
console.log('');
|
console.log('');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,11 @@ export abstract class BaseFormatter {
|
|||||||
displayDiff(diff: ICheckResult['diffs'][0]): void {
|
displayDiff(diff: ICheckResult['diffs'][0]): void {
|
||||||
console.log(`\n--- ${diff.path}`);
|
console.log(`\n--- ${diff.path}`);
|
||||||
if (diff.before && diff.after) {
|
if (diff.before && diff.after) {
|
||||||
console.log(plugins.smartdiff.formatLineDiffForConsole(diff.before, diff.after));
|
console.log(plugins.smartdiff.formatUnifiedDiffForConsole(diff.before, diff.after, {
|
||||||
|
originalFileName: diff.path,
|
||||||
|
revisedFileName: diff.path,
|
||||||
|
context: 3,
|
||||||
|
}));
|
||||||
} else if (diff.after && !diff.before) {
|
} else if (diff.after && !diff.before) {
|
||||||
console.log(' (new file)');
|
console.log(' (new file)');
|
||||||
// Show first few lines of new content
|
// Show first few lines of new content
|
||||||
|
|||||||
@@ -1,8 +1,117 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatCopy from '../format.copy.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class CopyFormatter extends LegacyFormatter {
|
interface ICopyPattern {
|
||||||
constructor(context: any, project: any) {
|
from: string;
|
||||||
super(context, project, 'copy', formatCopy);
|
to: string;
|
||||||
|
preservePath?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CopyFormatter extends BaseFormatter {
|
||||||
|
get name(): string {
|
||||||
|
return 'copy';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
|
||||||
|
// Get copy configuration from npmextra.json
|
||||||
|
const npmextraConfig = new plugins.npmextra.Npmextra();
|
||||||
|
const copyConfig = npmextraConfig.dataFor<{ patterns: ICopyPattern[] }>(
|
||||||
|
'gitzone.format.copy',
|
||||||
|
{ patterns: [] },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!copyConfig.patterns || copyConfig.patterns.length === 0) {
|
||||||
|
logVerbose('No copy patterns configured in npmextra.json');
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pattern of copyConfig.patterns) {
|
||||||
|
if (!pattern.from || !pattern.to) {
|
||||||
|
logVerbose('Invalid copy pattern - missing "from" or "to" field');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Handle glob patterns
|
||||||
|
const entries = await plugins.smartfs
|
||||||
|
.directory('.')
|
||||||
|
.recursive()
|
||||||
|
.filter(pattern.from)
|
||||||
|
.list();
|
||||||
|
const files = entries.map((entry) => entry.path);
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const sourcePath = file;
|
||||||
|
let destPath = pattern.to;
|
||||||
|
|
||||||
|
// If destination is a directory, preserve filename
|
||||||
|
if (pattern.to.endsWith('/')) {
|
||||||
|
const filename = plugins.path.basename(file);
|
||||||
|
destPath = plugins.path.join(pattern.to, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle template variables in destination path
|
||||||
|
if (pattern.preservePath) {
|
||||||
|
const relativePath = plugins.path.relative(
|
||||||
|
plugins.path.dirname(pattern.from.replace(/\*/g, '')),
|
||||||
|
file,
|
||||||
|
);
|
||||||
|
destPath = plugins.path.join(pattern.to, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read source content
|
||||||
|
const content = (await plugins.smartfs
|
||||||
|
.file(sourcePath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Check if destination exists and has same content
|
||||||
|
let needsCopy = true;
|
||||||
|
const destExists = await plugins.smartfs.file(destPath).exists();
|
||||||
|
if (destExists) {
|
||||||
|
const existingContent = (await plugins.smartfs
|
||||||
|
.file(destPath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
if (existingContent === content) {
|
||||||
|
needsCopy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsCopy) {
|
||||||
|
changes.push({
|
||||||
|
type: destExists ? 'modify' : 'create',
|
||||||
|
path: destPath,
|
||||||
|
module: this.name,
|
||||||
|
description: `Copy from ${sourcePath}`,
|
||||||
|
content: content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Failed to process pattern ${pattern.from}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (!change.content) return;
|
||||||
|
|
||||||
|
// Ensure destination directory exists
|
||||||
|
const destDir = plugins.path.dirname(change.path);
|
||||||
|
await plugins.smartfs.directory(destDir).recursive().create();
|
||||||
|
|
||||||
|
if (change.type === 'create') {
|
||||||
|
await this.createFile(change.path, change.content);
|
||||||
|
} else {
|
||||||
|
await this.modifyFile(change.path, change.content);
|
||||||
|
}
|
||||||
|
logger.log('info', `Copied to ${change.path}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,111 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatGitignore from '../format.gitignore.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import { logger } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class GitignoreFormatter extends LegacyFormatter {
|
// Standard gitignore template content (without front-matter)
|
||||||
constructor(context: any, project: any) {
|
const GITIGNORE_TEMPLATE = `.nogit/
|
||||||
super(context, project, 'gitignore', formatGitignore);
|
|
||||||
|
# artifacts
|
||||||
|
coverage/
|
||||||
|
public/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
|
||||||
|
# AI
|
||||||
|
.claude/
|
||||||
|
.serena/
|
||||||
|
|
||||||
|
#------# custom`;
|
||||||
|
|
||||||
|
export class GitignoreFormatter extends BaseFormatter {
|
||||||
|
get name(): string {
|
||||||
|
return 'gitignore';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const gitignorePath = '.gitignore';
|
||||||
|
|
||||||
|
// Check if file exists and extract custom content
|
||||||
|
let customContent = '';
|
||||||
|
const exists = await plugins.smartfs.file(gitignorePath).exists();
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
const existingContent = (await plugins.smartfs
|
||||||
|
.file(gitignorePath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Extract custom section content
|
||||||
|
const customMarkers = ['#------# custom', '# custom'];
|
||||||
|
for (const marker of customMarkers) {
|
||||||
|
const splitResult = existingContent.split(marker);
|
||||||
|
if (splitResult.length > 1) {
|
||||||
|
customContent = splitResult[1].trim();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute new content
|
||||||
|
let newContent = GITIGNORE_TEMPLATE;
|
||||||
|
if (customContent) {
|
||||||
|
newContent = GITIGNORE_TEMPLATE + '\n' + customContent + '\n';
|
||||||
|
} else {
|
||||||
|
newContent = GITIGNORE_TEMPLATE + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read current content to compare
|
||||||
|
let currentContent = '';
|
||||||
|
if (exists) {
|
||||||
|
currentContent = (await plugins.smartfs
|
||||||
|
.file(gitignorePath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine change type
|
||||||
|
if (!exists) {
|
||||||
|
changes.push({
|
||||||
|
type: 'create',
|
||||||
|
path: gitignorePath,
|
||||||
|
module: this.name,
|
||||||
|
description: 'Create .gitignore',
|
||||||
|
content: newContent,
|
||||||
|
});
|
||||||
|
} else if (newContent !== currentContent) {
|
||||||
|
changes.push({
|
||||||
|
type: 'modify',
|
||||||
|
path: gitignorePath,
|
||||||
|
module: this.name,
|
||||||
|
description: 'Update .gitignore (preserving custom section)',
|
||||||
|
content: newContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (!change.content) return;
|
||||||
|
|
||||||
|
if (change.type === 'create') {
|
||||||
|
await this.createFile(change.path, change.content);
|
||||||
|
logger.log('info', 'Created .gitignore');
|
||||||
|
} else if (change.type === 'modify') {
|
||||||
|
await this.modifyFile(change.path, change.content);
|
||||||
|
logger.log('info', 'Updated .gitignore (preserved custom section)');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { BaseFormatter } from '../classes.baseformatter.js';
|
|
||||||
import type { IPlannedChange } from '../interfaces.format.js';
|
|
||||||
import { Project } from '../../classes.project.js';
|
|
||||||
import * as plugins from '../mod.plugins.js';
|
|
||||||
|
|
||||||
// This is a wrapper for existing format modules
|
|
||||||
export class LegacyFormatter extends BaseFormatter {
|
|
||||||
private moduleName: string;
|
|
||||||
private formatModule: any;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
context: any,
|
|
||||||
project: Project,
|
|
||||||
moduleName: string,
|
|
||||||
formatModule: any,
|
|
||||||
) {
|
|
||||||
super(context, project);
|
|
||||||
this.moduleName = moduleName;
|
|
||||||
this.formatModule = formatModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
get name(): string {
|
|
||||||
return this.moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
async analyze(): Promise<IPlannedChange[]> {
|
|
||||||
// For legacy modules, we can't easily predict changes
|
|
||||||
// So we'll return a generic change that indicates the module will run
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
type: 'modify',
|
|
||||||
path: '<various files>',
|
|
||||||
module: this.name,
|
|
||||||
description: `Run ${this.name} formatter`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
async applyChange(change: IPlannedChange): Promise<void> {
|
|
||||||
// Run the legacy format module
|
|
||||||
await this.formatModule.run(this.project);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,62 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatLicense from '../format.license.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import * as paths from '../../paths.js';
|
||||||
|
import { logger } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class LicenseFormatter extends LegacyFormatter {
|
const INCOMPATIBLE_LICENSES: string[] = ['AGPL', 'GPL', 'SSPL'];
|
||||||
constructor(context: any, project: any) {
|
|
||||||
super(context, project, 'license', formatLicense);
|
export class LicenseFormatter extends BaseFormatter {
|
||||||
|
get name(): string {
|
||||||
|
return 'license';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
// License formatter only checks for incompatible licenses
|
||||||
|
// It does not modify any files, so return empty array
|
||||||
|
// The actual check happens in execute() for reporting purposes
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(changes: IPlannedChange[]): Promise<void> {
|
||||||
|
const startTime = this.stats.moduleStartTime(this.name);
|
||||||
|
this.stats.startModule(this.name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if node_modules exists
|
||||||
|
const nodeModulesPath = plugins.path.join(paths.cwd, 'node_modules');
|
||||||
|
const nodeModulesExists = await plugins.smartfs
|
||||||
|
.directory(nodeModulesPath)
|
||||||
|
.exists();
|
||||||
|
|
||||||
|
if (!nodeModulesExists) {
|
||||||
|
logger.log('warn', 'No node_modules found. Skipping license check');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run license check
|
||||||
|
const licenseChecker = await plugins.smartlegal.createLicenseChecker();
|
||||||
|
const licenseCheckResult = await licenseChecker.excludeLicenseWithinPath(
|
||||||
|
paths.cwd,
|
||||||
|
INCOMPATIBLE_LICENSES,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (licenseCheckResult.failingModules.length === 0) {
|
||||||
|
logger.log('info', 'License check passed - no incompatible licenses found');
|
||||||
|
} else {
|
||||||
|
logger.log('error', 'License check failed - incompatible licenses found:');
|
||||||
|
for (const failedModule of licenseCheckResult.failingModules) {
|
||||||
|
console.log(
|
||||||
|
` ${failedModule.name} has license ${failedModule.license}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.stats.endModule(this.name, startTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
// No file changes for license formatter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,165 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatNpmextra from '../format.npmextra.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class NpmextraFormatter extends LegacyFormatter {
|
/**
|
||||||
constructor(context: any, project: any) {
|
* Migrates npmextra.json from old namespace keys to new package-scoped keys
|
||||||
super(context, project, 'npmextra', formatNpmextra);
|
*/
|
||||||
|
const migrateNamespaceKeys = (npmextraJson: any): boolean => {
|
||||||
|
let migrated = false;
|
||||||
|
const migrations = [
|
||||||
|
{ oldKey: 'gitzone', newKey: '@git.zone/cli' },
|
||||||
|
{ oldKey: 'tsdoc', newKey: '@git.zone/tsdoc' },
|
||||||
|
{ oldKey: 'npmdocker', newKey: '@git.zone/tsdocker' },
|
||||||
|
{ oldKey: 'npmci', newKey: '@ship.zone/szci' },
|
||||||
|
{ oldKey: 'szci', newKey: '@ship.zone/szci' },
|
||||||
|
];
|
||||||
|
for (const { oldKey, newKey } of migrations) {
|
||||||
|
if (npmextraJson[oldKey] && !npmextraJson[newKey]) {
|
||||||
|
npmextraJson[newKey] = npmextraJson[oldKey];
|
||||||
|
delete npmextraJson[oldKey];
|
||||||
|
migrated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return migrated;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates npmAccessLevel from @ship.zone/szci to @git.zone/cli.release.accessLevel
|
||||||
|
*/
|
||||||
|
const migrateAccessLevel = (npmextraJson: any): boolean => {
|
||||||
|
const szciConfig = npmextraJson['@ship.zone/szci'];
|
||||||
|
|
||||||
|
if (!szciConfig?.npmAccessLevel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gitzoneConfig = npmextraJson['@git.zone/cli'] || {};
|
||||||
|
if (gitzoneConfig?.release?.accessLevel) {
|
||||||
|
delete szciConfig.npmAccessLevel;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!npmextraJson['@git.zone/cli']) {
|
||||||
|
npmextraJson['@git.zone/cli'] = {};
|
||||||
|
}
|
||||||
|
if (!npmextraJson['@git.zone/cli'].release) {
|
||||||
|
npmextraJson['@git.zone/cli'].release = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
npmextraJson['@git.zone/cli'].release.accessLevel = szciConfig.npmAccessLevel;
|
||||||
|
delete szciConfig.npmAccessLevel;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class NpmextraFormatter extends BaseFormatter {
|
||||||
|
get name(): string {
|
||||||
|
return 'npmextra';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const npmextraPath = 'npmextra.json';
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
const exists = await plugins.smartfs.file(npmextraPath).exists();
|
||||||
|
if (!exists) {
|
||||||
|
logVerbose('npmextra.json does not exist, skipping');
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read current content
|
||||||
|
const currentContent = (await plugins.smartfs
|
||||||
|
.file(npmextraPath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Parse and compute new content
|
||||||
|
const npmextraJson = JSON.parse(currentContent);
|
||||||
|
|
||||||
|
// Apply migrations (these are automatic, non-interactive)
|
||||||
|
migrateNamespaceKeys(npmextraJson);
|
||||||
|
migrateAccessLevel(npmextraJson);
|
||||||
|
|
||||||
|
// Ensure namespaces exist
|
||||||
|
if (!npmextraJson['@git.zone/cli']) {
|
||||||
|
npmextraJson['@git.zone/cli'] = {};
|
||||||
|
}
|
||||||
|
if (!npmextraJson['@ship.zone/szci']) {
|
||||||
|
npmextraJson['@ship.zone/szci'] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent = JSON.stringify(npmextraJson, null, 2);
|
||||||
|
|
||||||
|
// Only add change if content differs
|
||||||
|
if (newContent !== currentContent) {
|
||||||
|
changes.push({
|
||||||
|
type: 'modify',
|
||||||
|
path: npmextraPath,
|
||||||
|
module: this.name,
|
||||||
|
description: 'Migrate and format npmextra.json',
|
||||||
|
content: newContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (change.type !== 'modify' || !change.content) return;
|
||||||
|
|
||||||
|
// Parse the content to check for missing required fields
|
||||||
|
const npmextraJson = JSON.parse(change.content);
|
||||||
|
|
||||||
|
// Check for missing required module information
|
||||||
|
const expectedRepoInformation: string[] = [
|
||||||
|
'projectType',
|
||||||
|
'module.githost',
|
||||||
|
'module.gitscope',
|
||||||
|
'module.gitrepo',
|
||||||
|
'module.description',
|
||||||
|
'module.npmPackagename',
|
||||||
|
'module.license',
|
||||||
|
];
|
||||||
|
|
||||||
|
const interactInstance = new plugins.smartinteract.SmartInteract();
|
||||||
|
for (const expectedRepoInformationItem of expectedRepoInformation) {
|
||||||
|
if (
|
||||||
|
!plugins.smartobject.smartGet(
|
||||||
|
npmextraJson['@git.zone/cli'],
|
||||||
|
expectedRepoInformationItem,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
interactInstance.addQuestions([
|
||||||
|
{
|
||||||
|
message: `What is the value of ${expectedRepoInformationItem}`,
|
||||||
|
name: expectedRepoInformationItem,
|
||||||
|
type: 'input',
|
||||||
|
default: 'undefined variable',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const answerbucket = await interactInstance.runQueue();
|
||||||
|
for (const expectedRepoInformationItem of expectedRepoInformation) {
|
||||||
|
const cliProvidedValue = answerbucket.getAnswerFor(
|
||||||
|
expectedRepoInformationItem,
|
||||||
|
);
|
||||||
|
if (cliProvidedValue) {
|
||||||
|
plugins.smartobject.smartAdd(
|
||||||
|
npmextraJson['@git.zone/cli'],
|
||||||
|
expectedRepoInformationItem,
|
||||||
|
cliProvidedValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the final content
|
||||||
|
const finalContent = JSON.stringify(npmextraJson, null, 2);
|
||||||
|
await this.modifyFile(change.path, finalContent);
|
||||||
|
logger.log('info', 'Updated npmextra.json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,213 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatPackageJson from '../format.packagejson.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import * as paths from '../../paths.js';
|
||||||
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class PackageJsonFormatter extends LegacyFormatter {
|
/**
|
||||||
constructor(context: any, project: any) {
|
* Ensures a certain dependency exists or is excluded
|
||||||
super(context, project, 'packagejson', formatPackageJson);
|
*/
|
||||||
|
const ensureDependency = async (
|
||||||
|
packageJsonObject: any,
|
||||||
|
position: 'dep' | 'devDep' | 'everywhere',
|
||||||
|
constraint: 'exclude' | 'include' | 'latest',
|
||||||
|
dependencyArg: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
// Parse package name and version, handling scoped packages like @scope/name@version
|
||||||
|
const isScoped = dependencyArg.startsWith('@');
|
||||||
|
const lastAtIndex = dependencyArg.lastIndexOf('@');
|
||||||
|
|
||||||
|
// For scoped packages, the version @ must come after the /
|
||||||
|
// For unscoped packages, any @ indicates a version
|
||||||
|
const hasVersion = isScoped
|
||||||
|
? lastAtIndex > dependencyArg.indexOf('/')
|
||||||
|
: lastAtIndex >= 0;
|
||||||
|
|
||||||
|
const packageName = hasVersion ? dependencyArg.slice(0, lastAtIndex) : dependencyArg;
|
||||||
|
const version = hasVersion ? dependencyArg.slice(lastAtIndex + 1) : 'latest';
|
||||||
|
|
||||||
|
const targetSections: string[] = [];
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case 'dep':
|
||||||
|
targetSections.push('dependencies');
|
||||||
|
break;
|
||||||
|
case 'devDep':
|
||||||
|
targetSections.push('devDependencies');
|
||||||
|
break;
|
||||||
|
case 'everywhere':
|
||||||
|
targetSections.push('dependencies', 'devDependencies');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const section of targetSections) {
|
||||||
|
if (!packageJsonObject[section]) {
|
||||||
|
packageJsonObject[section] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (constraint) {
|
||||||
|
case 'exclude':
|
||||||
|
delete packageJsonObject[section][packageName];
|
||||||
|
break;
|
||||||
|
case 'include':
|
||||||
|
if (!packageJsonObject[section][packageName]) {
|
||||||
|
packageJsonObject[section][packageName] =
|
||||||
|
version === 'latest' ? '^1.0.0' : version;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'latest':
|
||||||
|
try {
|
||||||
|
const registry = new plugins.smartnpm.NpmRegistry();
|
||||||
|
const packageInfo = await registry.getPackageInfo(packageName);
|
||||||
|
const latestVersion = packageInfo['dist-tags'].latest;
|
||||||
|
packageJsonObject[section][packageName] = `^${latestVersion}`;
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(
|
||||||
|
`Could not fetch latest version for ${packageName}, using existing or default`,
|
||||||
|
);
|
||||||
|
if (!packageJsonObject[section][packageName]) {
|
||||||
|
packageJsonObject[section][packageName] =
|
||||||
|
version === 'latest' ? '^1.0.0' : version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class PackageJsonFormatter extends BaseFormatter {
|
||||||
|
get name(): string {
|
||||||
|
return 'packagejson';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const packageJsonPath = 'package.json';
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
const exists = await plugins.smartfs.file(packageJsonPath).exists();
|
||||||
|
if (!exists) {
|
||||||
|
logVerbose('package.json does not exist, skipping');
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read current content
|
||||||
|
const currentContent = (await plugins.smartfs
|
||||||
|
.file(packageJsonPath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Parse and compute new content
|
||||||
|
const packageJson = JSON.parse(currentContent);
|
||||||
|
|
||||||
|
// Get gitzone config from npmextra
|
||||||
|
const npmextraConfig = new plugins.npmextra.Npmextra(paths.cwd);
|
||||||
|
const gitzoneData: any = npmextraConfig.dataFor('@git.zone/cli', {});
|
||||||
|
|
||||||
|
// Set metadata from gitzone config
|
||||||
|
if (gitzoneData.module) {
|
||||||
|
packageJson.repository = {
|
||||||
|
type: 'git',
|
||||||
|
url: `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}.git`,
|
||||||
|
};
|
||||||
|
packageJson.bugs = {
|
||||||
|
url: `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}/issues`,
|
||||||
|
};
|
||||||
|
packageJson.homepage = `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}#readme`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure module type
|
||||||
|
if (!packageJson.type) {
|
||||||
|
packageJson.type = 'module';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure private field exists
|
||||||
|
if (packageJson.private === undefined) {
|
||||||
|
packageJson.private = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure license field exists
|
||||||
|
if (!packageJson.license) {
|
||||||
|
packageJson.license = 'UNLICENSED';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure scripts object exists
|
||||||
|
if (!packageJson.scripts) {
|
||||||
|
packageJson.scripts = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure build script exists
|
||||||
|
if (!packageJson.scripts.build) {
|
||||||
|
packageJson.scripts.build = `echo "Not needed for now"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure buildDocs script exists
|
||||||
|
if (!packageJson.scripts.buildDocs) {
|
||||||
|
packageJson.scripts.buildDocs = `tsdoc`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set files array
|
||||||
|
packageJson.files = [
|
||||||
|
'ts/**/*',
|
||||||
|
'ts_web/**/*',
|
||||||
|
'dist/**/*',
|
||||||
|
'dist_*/**/*',
|
||||||
|
'dist_ts/**/*',
|
||||||
|
'dist_ts_web/**/*',
|
||||||
|
'assets/**/*',
|
||||||
|
'cli.js',
|
||||||
|
'npmextra.json',
|
||||||
|
'readme.md',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Handle dependencies
|
||||||
|
await ensureDependency(
|
||||||
|
packageJson,
|
||||||
|
'devDep',
|
||||||
|
'exclude',
|
||||||
|
'@push.rocks/tapbundle',
|
||||||
|
);
|
||||||
|
await ensureDependency(packageJson, 'devDep', 'latest', '@git.zone/tstest');
|
||||||
|
await ensureDependency(
|
||||||
|
packageJson,
|
||||||
|
'devDep',
|
||||||
|
'latest',
|
||||||
|
'@git.zone/tsbuild',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set pnpm overrides from assets
|
||||||
|
try {
|
||||||
|
const overridesContent = (await plugins.smartfs
|
||||||
|
.file(plugins.path.join(paths.assetsDir, 'overrides.json'))
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
const overrides = JSON.parse(overridesContent);
|
||||||
|
packageJson.pnpm = packageJson.pnpm || {};
|
||||||
|
packageJson.pnpm.overrides = overrides;
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Could not read overrides.json: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent = JSON.stringify(packageJson, null, 2);
|
||||||
|
|
||||||
|
// Only add change if content differs
|
||||||
|
if (newContent !== currentContent) {
|
||||||
|
changes.push({
|
||||||
|
type: 'modify',
|
||||||
|
path: packageJsonPath,
|
||||||
|
module: this.name,
|
||||||
|
description: 'Format package.json',
|
||||||
|
content: newContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (change.type !== 'modify' || !change.content) return;
|
||||||
|
|
||||||
|
await this.modifyFile(change.path, change.content);
|
||||||
|
logger.log('info', 'Updated package.json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { BaseFormatter } from '../classes.baseformatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import type { IPlannedChange } from '../interfaces.format.js';
|
import type { IPlannedChange, ICheckResult } from '../interfaces.format.js';
|
||||||
import * as plugins from '../mod.plugins.js';
|
import * as plugins from '../mod.plugins.js';
|
||||||
import { logger, logVerbose } from '../../gitzone.logging.js';
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
@@ -40,27 +40,40 @@ export class PrettierFormatter extends BaseFormatter {
|
|||||||
|
|
||||||
// Add files from TypeScript directories
|
// Add files from TypeScript directories
|
||||||
for (const dir of includeDirs) {
|
for (const dir of includeDirs) {
|
||||||
const globPattern = `${dir}/**/*.${extensions}`;
|
try {
|
||||||
const dirEntries = await plugins.smartfs
|
const globPattern = `${dir}/**/*.${extensions}`;
|
||||||
.directory('.')
|
const dirEntries = await plugins.smartfs
|
||||||
.recursive()
|
.directory('.')
|
||||||
.filter(globPattern)
|
.recursive()
|
||||||
.list();
|
.filter(globPattern)
|
||||||
const dirFiles = dirEntries.map((entry) => entry.path);
|
.list();
|
||||||
allFiles.push(...dirFiles);
|
const dirFiles = dirEntries.map((entry) => entry.path);
|
||||||
|
// Filter out files in excluded directories
|
||||||
|
const filteredFiles = dirFiles.filter((f) =>
|
||||||
|
!f.includes('node_modules/') &&
|
||||||
|
!f.includes('.nogit/') &&
|
||||||
|
!f.includes('.git/')
|
||||||
|
);
|
||||||
|
allFiles.push(...filteredFiles);
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Skipping directory ${dir}: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add root config files
|
// Add root config files (only check root level, no recursive needed)
|
||||||
for (const pattern of rootConfigFiles) {
|
for (const pattern of rootConfigFiles) {
|
||||||
const rootEntries = await plugins.smartfs
|
try {
|
||||||
.directory('.')
|
const rootEntries = await plugins.smartfs
|
||||||
.recursive()
|
.directory('.')
|
||||||
.filter(pattern)
|
.filter(pattern)
|
||||||
.list();
|
.list();
|
||||||
const rootFiles = rootEntries.map((entry) => entry.path);
|
const rootFiles = rootEntries.map((entry) => entry.path);
|
||||||
// Only include files at root level (no slashes in path)
|
// Only include files at root level (no slashes in path)
|
||||||
const rootLevelFiles = rootFiles.filter((f) => !f.includes('/'));
|
const rootLevelFiles = rootFiles.filter((f) => !f.includes('/'));
|
||||||
allFiles.push(...rootLevelFiles);
|
allFiles.push(...rootLevelFiles);
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Skipping pattern ${pattern}: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove duplicates
|
// Remove duplicates
|
||||||
@@ -230,4 +243,53 @@ export class PrettierFormatter extends BaseFormatter {
|
|||||||
arrowParens: 'always',
|
arrowParens: 'always',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override check() to compute diffs on-the-fly by running prettier
|
||||||
|
*/
|
||||||
|
async check(): Promise<ICheckResult> {
|
||||||
|
const changes = await this.analyze();
|
||||||
|
const diffs: ICheckResult['diffs'] = [];
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
if (change.type !== 'modify') continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read current content
|
||||||
|
const currentContent = (await plugins.smartfs
|
||||||
|
.file(change.path)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Skip files without extension (prettier can't infer parser)
|
||||||
|
const fileExt = plugins.path.extname(change.path).toLowerCase();
|
||||||
|
if (!fileExt) continue;
|
||||||
|
|
||||||
|
// Format with prettier to get what it would produce
|
||||||
|
const prettier = await import('prettier');
|
||||||
|
const formatted = await prettier.format(currentContent, {
|
||||||
|
filepath: change.path,
|
||||||
|
...(await this.getPrettierConfig()),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only add to diffs if content differs
|
||||||
|
if (formatted !== currentContent) {
|
||||||
|
diffs.push({
|
||||||
|
path: change.path,
|
||||||
|
type: 'modify',
|
||||||
|
before: currentContent,
|
||||||
|
after: formatted,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Skip files that can't be processed
|
||||||
|
logVerbose(`Skipping diff for ${change.path}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasDiff: diffs.length > 0,
|
||||||
|
diffs,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import { BaseFormatter } from '../classes.baseformatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import type { IPlannedChange } from '../interfaces.format.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
import * as formatReadme from '../format.readme.js';
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import { logger } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
|
const DEFAULT_README_CONTENT = `# Project Readme
|
||||||
|
|
||||||
|
This is the initial readme file.`;
|
||||||
|
|
||||||
|
const DEFAULT_README_HINTS_CONTENT = `# Project Readme Hints
|
||||||
|
|
||||||
|
This is the initial readme hints file.`;
|
||||||
|
|
||||||
export class ReadmeFormatter extends BaseFormatter {
|
export class ReadmeFormatter extends BaseFormatter {
|
||||||
get name(): string {
|
get name(): string {
|
||||||
@@ -8,17 +17,39 @@ export class ReadmeFormatter extends BaseFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async analyze(): Promise<IPlannedChange[]> {
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
return [
|
const changes: IPlannedChange[] = [];
|
||||||
{
|
|
||||||
type: 'modify',
|
// Check readme.md
|
||||||
|
const readmeExists = await plugins.smartfs.file('readme.md').exists();
|
||||||
|
if (!readmeExists) {
|
||||||
|
changes.push({
|
||||||
|
type: 'create',
|
||||||
path: 'readme.md',
|
path: 'readme.md',
|
||||||
module: this.name,
|
module: this.name,
|
||||||
description: 'Ensure readme files exist',
|
description: 'Create readme.md',
|
||||||
},
|
content: DEFAULT_README_CONTENT,
|
||||||
];
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check readme.hints.md
|
||||||
|
const hintsExists = await plugins.smartfs.file('readme.hints.md').exists();
|
||||||
|
if (!hintsExists) {
|
||||||
|
changes.push({
|
||||||
|
type: 'create',
|
||||||
|
path: 'readme.hints.md',
|
||||||
|
module: this.name,
|
||||||
|
description: 'Create readme.hints.md',
|
||||||
|
content: DEFAULT_README_HINTS_CONTENT,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
async applyChange(change: IPlannedChange): Promise<void> {
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
await formatReadme.run();
|
if (change.type !== 'create' || !change.content) return;
|
||||||
|
|
||||||
|
await this.createFile(change.path, change.content);
|
||||||
|
logger.log('info', `Created ${change.path}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,155 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatTemplates from '../format.templates.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import * as paths from '../../paths.js';
|
||||||
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class TemplatesFormatter extends LegacyFormatter {
|
export class TemplatesFormatter extends BaseFormatter {
|
||||||
constructor(context: any, project: any) {
|
get name(): string {
|
||||||
super(context, project, 'templates', formatTemplates);
|
return 'templates';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const project = this.project;
|
||||||
|
const projectType = project.gitzoneConfig?.data?.projectType;
|
||||||
|
|
||||||
|
// VSCode template - for all projects
|
||||||
|
const vscodeChanges = await this.analyzeTemplate('vscode', [
|
||||||
|
{ templatePath: '.vscode/settings.json', destPath: '.vscode/settings.json' },
|
||||||
|
{ templatePath: '.vscode/launch.json', destPath: '.vscode/launch.json' },
|
||||||
|
]);
|
||||||
|
changes.push(...vscodeChanges);
|
||||||
|
|
||||||
|
// CI and other templates based on projectType
|
||||||
|
switch (projectType) {
|
||||||
|
case 'npm':
|
||||||
|
case 'wcc':
|
||||||
|
const accessLevel = project.gitzoneConfig?.data?.npmciOptions?.npmAccessLevel;
|
||||||
|
const ciTemplate = accessLevel === 'public' ? 'ci_default' : 'ci_default_private';
|
||||||
|
const ciChanges = await this.analyzeTemplate(ciTemplate, [
|
||||||
|
{ templatePath: '.gitea/workflows/default_nottags.yaml', destPath: '.gitea/workflows/default_nottags.yaml' },
|
||||||
|
{ templatePath: '.gitea/workflows/default_tags.yaml', destPath: '.gitea/workflows/default_tags.yaml' },
|
||||||
|
]);
|
||||||
|
changes.push(...ciChanges);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'service':
|
||||||
|
case 'website':
|
||||||
|
const dockerCiChanges = await this.analyzeTemplate('ci_docker', [
|
||||||
|
{ templatePath: '.gitea/workflows/docker_nottags.yaml', destPath: '.gitea/workflows/docker_nottags.yaml' },
|
||||||
|
{ templatePath: '.gitea/workflows/docker_tags.yaml', destPath: '.gitea/workflows/docker_tags.yaml' },
|
||||||
|
]);
|
||||||
|
changes.push(...dockerCiChanges);
|
||||||
|
|
||||||
|
const dockerfileChanges = await this.analyzeTemplate('dockerfile_service', [
|
||||||
|
{ templatePath: 'Dockerfile', destPath: 'Dockerfile' },
|
||||||
|
{ templatePath: 'dockerignore', destPath: '.dockerignore' },
|
||||||
|
]);
|
||||||
|
changes.push(...dockerfileChanges);
|
||||||
|
|
||||||
|
const cliChanges = await this.analyzeTemplate('cli', [
|
||||||
|
{ templatePath: 'cli.js', destPath: 'cli.js' },
|
||||||
|
{ templatePath: 'cli.ts.js', destPath: 'cli.ts.js' },
|
||||||
|
]);
|
||||||
|
changes.push(...cliChanges);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update templates based on projectType
|
||||||
|
if (projectType === 'website') {
|
||||||
|
const websiteChanges = await this.analyzeTemplate('website_update', [
|
||||||
|
{ templatePath: 'html/index.html', destPath: 'html/index.html' },
|
||||||
|
]);
|
||||||
|
changes.push(...websiteChanges);
|
||||||
|
} else if (projectType === 'service') {
|
||||||
|
const serviceChanges = await this.analyzeTemplate('service_update', []);
|
||||||
|
changes.push(...serviceChanges);
|
||||||
|
} else if (projectType === 'wcc') {
|
||||||
|
const wccChanges = await this.analyzeTemplate('wcc_update', [
|
||||||
|
{ templatePath: 'html/index.html', destPath: 'html/index.html' },
|
||||||
|
{ templatePath: 'html/index.ts', destPath: 'html/index.ts' },
|
||||||
|
]);
|
||||||
|
changes.push(...wccChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async analyzeTemplate(
|
||||||
|
templateName: string,
|
||||||
|
files: Array<{ templatePath: string; destPath: string }>,
|
||||||
|
): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const templateDir = plugins.path.join(paths.templatesDir, templateName);
|
||||||
|
|
||||||
|
// Check if template exists
|
||||||
|
const templateExists = await plugins.smartfs.directory(templateDir).exists();
|
||||||
|
if (!templateExists) {
|
||||||
|
logVerbose(`Template ${templateName} not found`);
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const templateFilePath = plugins.path.join(templateDir, file.templatePath);
|
||||||
|
const destFilePath = file.destPath;
|
||||||
|
|
||||||
|
// Check if template file exists
|
||||||
|
const fileExists = await plugins.smartfs.file(templateFilePath).exists();
|
||||||
|
if (!fileExists) {
|
||||||
|
logVerbose(`Template file ${templateFilePath} not found`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read template content
|
||||||
|
const templateContent = (await plugins.smartfs
|
||||||
|
.file(templateFilePath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Check if destination file exists
|
||||||
|
const destExists = await plugins.smartfs.file(destFilePath).exists();
|
||||||
|
let currentContent = '';
|
||||||
|
if (destExists) {
|
||||||
|
currentContent = (await plugins.smartfs
|
||||||
|
.file(destFilePath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only add change if content differs
|
||||||
|
if (templateContent !== currentContent) {
|
||||||
|
changes.push({
|
||||||
|
type: destExists ? 'modify' : 'create',
|
||||||
|
path: destFilePath,
|
||||||
|
module: this.name,
|
||||||
|
description: `Apply template ${templateName}/${file.templatePath}`,
|
||||||
|
content: templateContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Failed to read template ${templateFilePath}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (!change.content) return;
|
||||||
|
|
||||||
|
// Ensure destination directory exists
|
||||||
|
const destDir = plugins.path.dirname(change.path);
|
||||||
|
if (destDir && destDir !== '.') {
|
||||||
|
await plugins.smartfs.directory(destDir).recursive().create();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.type === 'create') {
|
||||||
|
await this.createFile(change.path, change.content);
|
||||||
|
} else {
|
||||||
|
await this.modifyFile(change.path, change.content);
|
||||||
|
}
|
||||||
|
logger.log('info', `Applied template to ${change.path}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,73 @@
|
|||||||
import { LegacyFormatter } from './legacy.formatter.js';
|
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||||
import * as formatTsconfig from '../format.tsconfig.js';
|
import type { IPlannedChange } from '../interfaces.format.js';
|
||||||
|
import * as plugins from '../mod.plugins.js';
|
||||||
|
import * as paths from '../../paths.js';
|
||||||
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||||
|
|
||||||
export class TsconfigFormatter extends LegacyFormatter {
|
export class TsconfigFormatter extends BaseFormatter {
|
||||||
constructor(context: any, project: any) {
|
get name(): string {
|
||||||
super(context, project, 'tsconfig', formatTsconfig);
|
return 'tsconfig';
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyze(): Promise<IPlannedChange[]> {
|
||||||
|
const changes: IPlannedChange[] = [];
|
||||||
|
const tsconfigPath = 'tsconfig.json';
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
const exists = await plugins.smartfs.file(tsconfigPath).exists();
|
||||||
|
if (!exists) {
|
||||||
|
logVerbose('tsconfig.json does not exist, skipping');
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read current content
|
||||||
|
const currentContent = (await plugins.smartfs
|
||||||
|
.file(tsconfigPath)
|
||||||
|
.encoding('utf8')
|
||||||
|
.read()) as string;
|
||||||
|
|
||||||
|
// Parse and compute new content
|
||||||
|
const tsconfigObject = JSON.parse(currentContent);
|
||||||
|
tsconfigObject.compilerOptions = tsconfigObject.compilerOptions || {};
|
||||||
|
tsconfigObject.compilerOptions.baseUrl = '.';
|
||||||
|
tsconfigObject.compilerOptions.paths = {};
|
||||||
|
|
||||||
|
// Get module paths from tspublish
|
||||||
|
try {
|
||||||
|
const tsPublishMod = await import('@git.zone/tspublish');
|
||||||
|
const tsPublishInstance = new tsPublishMod.TsPublish();
|
||||||
|
const publishModules = await tsPublishInstance.getModuleSubDirs(paths.cwd);
|
||||||
|
|
||||||
|
for (const publishModule of Object.keys(publishModules)) {
|
||||||
|
const publishConfig = publishModules[publishModule];
|
||||||
|
tsconfigObject.compilerOptions.paths[`${publishConfig.name}`] = [
|
||||||
|
`./${publishModule}/index.js`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logVerbose(`Could not get tspublish modules: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent = JSON.stringify(tsconfigObject, null, 2);
|
||||||
|
|
||||||
|
// Only add change if content differs
|
||||||
|
if (newContent !== currentContent) {
|
||||||
|
changes.push({
|
||||||
|
type: 'modify',
|
||||||
|
path: tsconfigPath,
|
||||||
|
module: this.name,
|
||||||
|
description: 'Format tsconfig.json with path mappings',
|
||||||
|
content: newContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async applyChange(change: IPlannedChange): Promise<void> {
|
||||||
|
if (change.type !== 'modify' || !change.content) return;
|
||||||
|
|
||||||
|
await this.modifyFile(change.path, change.content);
|
||||||
|
logger.log('info', 'Updated tsconfig.json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export let run = async (
|
|||||||
interactive?: boolean;
|
interactive?: boolean;
|
||||||
parallel?: boolean;
|
parallel?: boolean;
|
||||||
verbose?: boolean;
|
verbose?: boolean;
|
||||||
|
diff?: boolean; // Show file diffs
|
||||||
} = {},
|
} = {},
|
||||||
): Promise<any> => {
|
): Promise<any> => {
|
||||||
// Set verbose mode if requested
|
// Set verbose mode if requested
|
||||||
@@ -132,6 +133,21 @@ export let run = async (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show diffs if requested (works in both dry-run and write modes)
|
||||||
|
if (options.diff) {
|
||||||
|
logger.log('info', 'Showing file diffs:');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
for (const formatter of activeFormatters) {
|
||||||
|
const checkResult = await formatter.check();
|
||||||
|
if (checkResult.hasDiff) {
|
||||||
|
logger.log('info', `[${formatter.name}]`);
|
||||||
|
formatter.displayAllDiffs(checkResult);
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dry-run mode (default behavior)
|
// Dry-run mode (default behavior)
|
||||||
if (!shouldWrite) {
|
if (!shouldWrite) {
|
||||||
logger.log('info', 'Dry-run mode - use --write (-w) to apply changes');
|
logger.log('info', 'Dry-run mode - use --write (-w) to apply changes');
|
||||||
|
|||||||
Reference in New Issue
Block a user