Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5fbeb3fc6 | |||
| 2ecdeff3dc | |||
| 5a663ae767 | |||
| 218c84a39b | |||
| 27d5cdca35 | |||
| 3ebf072bfb | |||
| 08f56ae0a4 | |||
| b2d2684895 | |||
| 1b328c3045 | |||
| f444a04876 | |||
| 6bd2d35992 | |||
| d038b1d681 | |||
| d60de5cef7 | |||
| e1076a60ad | |||
| 6deba06443 | |||
| 00cd9dc8e7 |
55
changelog.md
55
changelog.md
@@ -1,5 +1,60 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
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.
|
||||||
|
- Extend runFormatter API with new options: write (use to apply changes), checkOnly (only check for diffs), and showDiff (display diffs). When checkOnly is used, runFormatter returns an ICheckResult.
|
||||||
|
- Change default formatting behavior to dry-run. Use --write / -w to actually apply changes. CLI format command updated to respect --write/-w.
|
||||||
|
- Add formatNpmextraWithDiff in mod_config to preview diffs for npmextra.json and prompt the user before applying changes; calls to add/remove/clear registries and set access level now use this preview flow.
|
||||||
|
- Project.fromCwd now accepts an options object ({ requireProjectType?: boolean }) so callers can skip the projectType requirement when appropriate; runFormatter no longer requires projectType for certain formatters.
|
||||||
|
- Introduce a list of formatters that don't require projectType: npmextra, prettier, cleanup, packagejson.
|
||||||
|
- Export the ICheckResult type from the formatter module and update mod_format interfaces to include ICheckResult.
|
||||||
|
- Bump dependency @push.rocks/smartdiff to ^1.1.0.
|
||||||
|
|
||||||
|
## 2025-12-14 - 2.6.1 - fix(npmextra)
|
||||||
|
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
|
||||||
|
- Remove the misplaced "gitzone" object that previously contained the TSDoc legal block
|
||||||
|
- Reorder and properly nest the "@git.zone/cli" configuration to follow the new "tsdoc" section
|
||||||
|
- Pure configuration change (JSON structure) — no functional code changes
|
||||||
|
|
||||||
|
## 2025-12-14 - 2.6.0 - feat(mod_commit)
|
||||||
|
Add execution plan output to commit command
|
||||||
|
|
||||||
|
- Print an execution plan at the start of the commit flow (shows active options and planned steps)
|
||||||
|
- New printExecutionPlan(options) added to ts/mod_commit/mod.ui.ts
|
||||||
|
- Commit command now calls ui.printExecutionPlan(...) before running format or other steps
|
||||||
|
- 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)
|
||||||
|
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.
|
||||||
|
- Add routing to commands (commit, format, config, template, services, open, help) using dynamic imports.
|
||||||
|
- Add showHelp() helper to display usage and available commands.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
"npmAccessLevel": "private",
|
"npmAccessLevel": "private",
|
||||||
"npmRegistryUrl": "verdaccio.lossless.one"
|
"npmRegistryUrl": "verdaccio.lossless.one"
|
||||||
},
|
},
|
||||||
"gitzone": {
|
"tsdoc": {
|
||||||
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||||
|
},
|
||||||
|
"@git.zone/cli": {
|
||||||
"projectType": "npm",
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
@@ -31,15 +34,11 @@
|
|||||||
"Docker",
|
"Docker",
|
||||||
"CI/CD"
|
"CI/CD"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
},
|
|
||||||
"tsdoc": {
|
|
||||||
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
||||||
},
|
|
||||||
"@git.zone/cli": {
|
|
||||||
"release": {
|
"release": {
|
||||||
"registries": [
|
"registries": [
|
||||||
"https://verdaccio.lossless.digital"
|
"https://verdaccio.lossless.digital",
|
||||||
|
"https://registry.npmjs.org"
|
||||||
],
|
],
|
||||||
"accessLevel": "public"
|
"accessLevel": "public"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@git.zone/cli",
|
"name": "@git.zone/cli",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "2.4.0",
|
"version": "2.9.2",
|
||||||
"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",
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
"@push.rocks/npmextra": "^5.3.3",
|
"@push.rocks/npmextra": "^5.3.3",
|
||||||
"@push.rocks/projectinfo": "^5.0.2",
|
"@push.rocks/projectinfo": "^5.0.2",
|
||||||
"@push.rocks/smartcli": "^4.0.19",
|
"@push.rocks/smartcli": "^4.0.19",
|
||||||
"@push.rocks/smartdiff": "^1.0.3",
|
"@push.rocks/smartdiff": "^1.1.0",
|
||||||
"@push.rocks/smartfile": "^13.1.2",
|
"@push.rocks/smartfile": "^13.1.2",
|
||||||
"@push.rocks/smartfs": "^1.2.0",
|
"@push.rocks/smartfs": "^1.2.0",
|
||||||
"@push.rocks/smartgulp": "^3.0.4",
|
"@push.rocks/smartgulp": "^3.0.4",
|
||||||
|
|||||||
107
pnpm-lock.yaml
generated
107
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
|
||||||
@@ -36,8 +36,8 @@ importers:
|
|||||||
specifier: ^4.0.19
|
specifier: ^4.0.19
|
||||||
version: 4.0.19
|
version: 4.0.19
|
||||||
'@push.rocks/smartdiff':
|
'@push.rocks/smartdiff':
|
||||||
specifier: ^1.0.3
|
specifier: ^1.1.0
|
||||||
version: 1.0.3
|
version: 1.1.0
|
||||||
'@push.rocks/smartfile':
|
'@push.rocks/smartfile':
|
||||||
specifier: ^13.1.2
|
specifier: ^13.1.2
|
||||||
version: 13.1.2
|
version: 13.1.2
|
||||||
@@ -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,8 +1048,11 @@ packages:
|
|||||||
'@push.rocks/smartdelay@3.0.5':
|
'@push.rocks/smartdelay@3.0.5':
|
||||||
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
|
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
|
||||||
|
|
||||||
'@push.rocks/smartdiff@1.0.3':
|
'@push.rocks/smartdeno@1.2.0':
|
||||||
resolution: {integrity: sha512-cXUKj0KJBxnrZDN1Ztc2WiFRJM3vOTdQUdBfe6ar5NlKuXytSRMJqVL8IUbtWfMCSOx6HgWAUT7W68+/X2TG8w==}
|
resolution: {integrity: sha512-6S1plCaMUVOZiRSflfoz9Fqk9phACCuKmc7Z6SfTvfl+p9VcPUmewKgaa/0QiLOpiI6ksfxdfmkS5Rw5HpYeIA==}
|
||||||
|
|
||||||
|
'@push.rocks/smartdiff@1.1.0':
|
||||||
|
resolution: {integrity: sha512-AAz/unmko0C+g+60odOoK32PE3Ci3YLoB+zfg1LGLyVRCthcdzjqa1C2Km0MfG7IyJQKPdj8J5HPubtpm3ZeaQ==}
|
||||||
|
|
||||||
'@push.rocks/smartdns@7.6.1':
|
'@push.rocks/smartdns@7.6.1':
|
||||||
resolution: {integrity: sha512-nnP5+A2GOt0WsHrYhtKERmjdEHUchc+QbCCBEqlyeQTn+mNfx2WZvKVI1DFRJt8lamvzxP6Hr/BSe3WHdh4Snw==}
|
resolution: {integrity: sha512-nnP5+A2GOt0WsHrYhtKERmjdEHUchc+QbCCBEqlyeQTn+mNfx2WZvKVI1DFRJt8lamvzxP6Hr/BSe3WHdh4Snw==}
|
||||||
@@ -2536,9 +2545,6 @@ packages:
|
|||||||
fast-deep-equal@3.1.3:
|
fast-deep-equal@3.1.3:
|
||||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||||
|
|
||||||
fast-diff@1.3.0:
|
|
||||||
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
|
|
||||||
|
|
||||||
fast-fifo@1.3.2:
|
fast-fifo@1.3.2:
|
||||||
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
|
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
|
||||||
|
|
||||||
@@ -2707,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==}
|
||||||
|
|
||||||
@@ -2908,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
|
||||||
|
|
||||||
@@ -5063,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
|
||||||
@@ -5081,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:
|
||||||
@@ -5880,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)
|
||||||
@@ -5926,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)':
|
||||||
@@ -6049,9 +6096,21 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartpromise': 4.2.3
|
'@push.rocks/smartpromise': 4.2.3
|
||||||
|
|
||||||
'@push.rocks/smartdiff@1.0.3':
|
'@push.rocks/smartdeno@1.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-diff: 1.3.0
|
'@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':
|
||||||
|
dependencies:
|
||||||
|
diff: 8.0.2
|
||||||
|
|
||||||
'@push.rocks/smartdns@7.6.1':
|
'@push.rocks/smartdns@7.6.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6180,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':
|
||||||
@@ -8145,8 +8204,6 @@ snapshots:
|
|||||||
|
|
||||||
fast-deep-equal@3.1.3: {}
|
fast-deep-equal@3.1.3: {}
|
||||||
|
|
||||||
fast-diff@1.3.0: {}
|
|
||||||
|
|
||||||
fast-fifo@1.3.2: {}
|
fast-fifo@1.3.2: {}
|
||||||
|
|
||||||
fast-json-stable-stringify@2.1.0: {}
|
fast-json-stable-stringify@2.1.0: {}
|
||||||
@@ -8364,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: {}
|
||||||
@@ -8578,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
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/cli',
|
name: '@git.zone/cli',
|
||||||
version: '2.4.0',
|
version: '2.9.0',
|
||||||
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.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import type { TGitzoneProjectType } from './classes.gitzoneconfig.js';
|
|||||||
* the Project class is a tool to work with a gitzone project
|
* the Project class is a tool to work with a gitzone project
|
||||||
*/
|
*/
|
||||||
export class Project {
|
export class Project {
|
||||||
public static async fromCwd() {
|
public static async fromCwd(options: { requireProjectType?: boolean } = {}) {
|
||||||
const gitzoneConfig = await GitzoneConfig.fromCwd();
|
const gitzoneConfig = await GitzoneConfig.fromCwd();
|
||||||
const project = new Project(gitzoneConfig);
|
const project = new Project(gitzoneConfig);
|
||||||
if (!project.gitzoneConfig.data.projectType) {
|
const requireProjectType = options.requireProjectType ?? true;
|
||||||
|
if (requireProjectType && !project.gitzoneConfig.data.projectType) {
|
||||||
throw new Error('Please define a project type');
|
throw new Error('Please define a project type');
|
||||||
}
|
}
|
||||||
return project;
|
return project;
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ export let run = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle format with options
|
// Handle format with options
|
||||||
|
// Default is dry-mode, use --write/-w to apply changes
|
||||||
await modFormat.run({
|
await modFormat.run({
|
||||||
|
write: argvArg.write || argvArg.w,
|
||||||
dryRun: argvArg['dry-run'],
|
dryRun: argvArg['dry-run'],
|
||||||
yes: argvArg.yes,
|
yes: argvArg.yes,
|
||||||
planOnly: argvArg['plan-only'],
|
planOnly: argvArg['plan-only'],
|
||||||
@@ -90,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) {
|
||||||
@@ -24,11 +35,37 @@ export const run = async (argvArg: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print execution plan at the start
|
||||||
|
ui.printExecutionPlan({
|
||||||
|
autoAccept: !!(argvArg.y || argvArg.yes),
|
||||||
|
push: !!(argvArg.p || argvArg.push),
|
||||||
|
test: wantsTest,
|
||||||
|
build: wantsBuild,
|
||||||
|
release: wantsRelease,
|
||||||
|
format: !!argvArg.format,
|
||||||
|
registries: releaseConfig?.getRegistries(),
|
||||||
|
});
|
||||||
|
|
||||||
if (argvArg.format) {
|
if (argvArg.format) {
|
||||||
const formatMod = await import('../mod_format/index.js');
|
const formatMod = await import('../mod_format/index.js');
|
||||||
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();
|
||||||
@@ -151,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
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ interface ICommitSummary {
|
|||||||
releasedRegistries?: string[];
|
releasedRegistries?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IExecutionPlanOptions {
|
||||||
|
autoAccept: boolean;
|
||||||
|
push: boolean;
|
||||||
|
test: boolean;
|
||||||
|
build: boolean;
|
||||||
|
release: boolean;
|
||||||
|
format: boolean;
|
||||||
|
registries?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
interface IRecommendation {
|
interface IRecommendation {
|
||||||
recommendedNextVersion: string;
|
recommendedNextVersion: string;
|
||||||
recommendedNextVersionLevel: string;
|
recommendedNextVersionLevel: string;
|
||||||
@@ -41,6 +51,58 @@ export function printHeader(title: string): void {
|
|||||||
console.log('');
|
console.log('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print execution plan at the start of commit
|
||||||
|
*/
|
||||||
|
export function printExecutionPlan(options: IExecutionPlanOptions): void {
|
||||||
|
console.log('');
|
||||||
|
console.log('╭───────────────────────────────────────────────────────────────╮');
|
||||||
|
console.log('│ gitzone commit - Execution Plan │');
|
||||||
|
console.log('╰───────────────────────────────────────────────────────────────╯');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// Show active options
|
||||||
|
console.log(' Options:');
|
||||||
|
console.log(` Auto-accept ${options.autoAccept ? '✓ enabled (-y)' : '○ interactive mode'}`);
|
||||||
|
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(` Release to npm ${options.release ? '✓ enabled (-r)' : '○ disabled'}`);
|
||||||
|
if (options.format) {
|
||||||
|
console.log(` Format first ✓ enabled (--format)`);
|
||||||
|
}
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// Show steps
|
||||||
|
console.log(' Steps:');
|
||||||
|
let stepNum = 1;
|
||||||
|
if (options.format) {
|
||||||
|
console.log(` ${stepNum++}. Format project files`);
|
||||||
|
}
|
||||||
|
if (options.test) {
|
||||||
|
console.log(` ${stepNum++}. Run tests`);
|
||||||
|
}
|
||||||
|
console.log(` ${stepNum++}. Analyze repository changes`);
|
||||||
|
console.log(` ${stepNum++}. Bake commit info into code`);
|
||||||
|
console.log(` ${stepNum++}. Generate changelog.md`);
|
||||||
|
console.log(` ${stepNum++}. Stage and commit files`);
|
||||||
|
console.log(` ${stepNum++}. Bump version`);
|
||||||
|
if (options.build) {
|
||||||
|
console.log(` ${stepNum++}. Run build`);
|
||||||
|
console.log(` ${stepNum++}. Verify clean working tree`);
|
||||||
|
}
|
||||||
|
if (options.push) {
|
||||||
|
console.log(` ${stepNum++}. Push to remote`);
|
||||||
|
}
|
||||||
|
if (options.release) {
|
||||||
|
console.log(` ${stepNum++}. Publish to npm registries`);
|
||||||
|
if (options.registries && options.registries.length > 0) {
|
||||||
|
options.registries.forEach(r => console.log(` → ${r}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a section with a border
|
* Print a section with a border
|
||||||
*/
|
*/
|
||||||
|
|||||||
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,32 @@
|
|||||||
|
|
||||||
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 { runFormatter } from '../mod_format/index.js';
|
import { CommitConfig } from './classes.commitconfig.js';
|
||||||
|
import { runFormatter, type ICheckResult } from '../mod_format/index.js';
|
||||||
|
|
||||||
export { ReleaseConfig };
|
export { ReleaseConfig, CommitConfig };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format npmextra.json with diff preview
|
||||||
|
* Shows diff first, asks for confirmation, then applies
|
||||||
|
*/
|
||||||
|
async function formatNpmextraWithDiff(): Promise<void> {
|
||||||
|
// Check for diffs first
|
||||||
|
const checkResult = await runFormatter('npmextra', {
|
||||||
|
checkOnly: true,
|
||||||
|
showDiff: true,
|
||||||
|
}) as ICheckResult | void;
|
||||||
|
|
||||||
|
if (checkResult && checkResult.hasDiff) {
|
||||||
|
const shouldApply = await plugins.smartinteract.SmartInteract.getCliConfirmation(
|
||||||
|
'Apply formatting changes to npmextra.json?',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (shouldApply) {
|
||||||
|
await runFormatter('npmextra', { silent: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const run = async (argvArg: any) => {
|
export const run = async (argvArg: any) => {
|
||||||
const command = argvArg._?.[1];
|
const command = argvArg._?.[1];
|
||||||
@@ -33,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;
|
||||||
@@ -48,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('');
|
||||||
|
|
||||||
@@ -64,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' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -86,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;
|
||||||
@@ -149,8 +186,8 @@ async function handleAdd(url?: string): Promise<void> {
|
|||||||
|
|
||||||
if (added) {
|
if (added) {
|
||||||
await config.save();
|
await config.save();
|
||||||
await runFormatter('npmextra', { silent: true });
|
|
||||||
plugins.logger.log('success', `Added registry: ${url}`);
|
plugins.logger.log('success', `Added registry: ${url}`);
|
||||||
|
await formatNpmextraWithDiff();
|
||||||
} else {
|
} else {
|
||||||
plugins.logger.log('warn', `Registry already exists: ${url}`);
|
plugins.logger.log('warn', `Registry already exists: ${url}`);
|
||||||
}
|
}
|
||||||
@@ -185,8 +222,8 @@ async function handleRemove(url?: string): Promise<void> {
|
|||||||
|
|
||||||
if (removed) {
|
if (removed) {
|
||||||
await config.save();
|
await config.save();
|
||||||
await runFormatter('npmextra', { silent: true });
|
|
||||||
plugins.logger.log('success', `Removed registry: ${url}`);
|
plugins.logger.log('success', `Removed registry: ${url}`);
|
||||||
|
await formatNpmextraWithDiff();
|
||||||
} else {
|
} else {
|
||||||
plugins.logger.log('warn', `Registry not found: ${url}`);
|
plugins.logger.log('warn', `Registry not found: ${url}`);
|
||||||
}
|
}
|
||||||
@@ -212,8 +249,8 @@ async function handleClear(): Promise<void> {
|
|||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
config.clearRegistries();
|
config.clearRegistries();
|
||||||
await config.save();
|
await config.save();
|
||||||
await runFormatter('npmextra', { silent: true });
|
|
||||||
plugins.logger.log('success', 'All registries cleared.');
|
plugins.logger.log('success', 'All registries cleared.');
|
||||||
|
await formatNpmextraWithDiff();
|
||||||
} else {
|
} else {
|
||||||
plugins.logger.log('info', 'Operation cancelled.');
|
plugins.logger.log('info', 'Operation cancelled.');
|
||||||
}
|
}
|
||||||
@@ -252,8 +289,115 @@ async function handleAccessLevel(level?: string): Promise<void> {
|
|||||||
|
|
||||||
config.setAccessLevel(level as 'public' | 'private');
|
config.setAccessLevel(level as 'public' | 'private');
|
||||||
await config.save();
|
await config.save();
|
||||||
await runFormatter('npmextra', { silent: true });
|
|
||||||
plugins.logger.log('success', `Access level set to: ${level}`);
|
plugins.logger.log('success', `Access level set to: ${level}`);
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -269,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');
|
||||||
@@ -278,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('');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.js';
|
||||||
import { FormatContext } from './classes.formatcontext.js';
|
import { FormatContext } from './classes.formatcontext.js';
|
||||||
import type { IPlannedChange } from './interfaces.format.js';
|
import type { IPlannedChange, ICheckResult } from './interfaces.format.js';
|
||||||
import { Project } from '../classes.project.js';
|
import { Project } from '../classes.project.js';
|
||||||
|
|
||||||
export abstract class BaseFormatter {
|
export abstract class BaseFormatter {
|
||||||
@@ -79,4 +79,94 @@ export abstract class BaseFormatter {
|
|||||||
protected async shouldProcessFile(filepath: string): Promise<boolean> {
|
protected async shouldProcessFile(filepath: string): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for diffs without applying changes
|
||||||
|
* Returns information about what would change
|
||||||
|
*/
|
||||||
|
async check(): Promise<ICheckResult> {
|
||||||
|
const changes = await this.analyze();
|
||||||
|
const diffs: ICheckResult['diffs'] = [];
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
// Skip generic changes that don't have actual content
|
||||||
|
if (change.path === '<various files>') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.type === 'modify' || change.type === 'create') {
|
||||||
|
// Read current content if file exists
|
||||||
|
let currentContent: string | undefined;
|
||||||
|
try {
|
||||||
|
currentContent = await plugins.smartfs.file(change.path).encoding('utf8').read() as string;
|
||||||
|
} catch {
|
||||||
|
// File doesn't exist yet
|
||||||
|
currentContent = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent = change.content;
|
||||||
|
|
||||||
|
// Check if there's an actual diff
|
||||||
|
if (currentContent !== newContent && newContent !== undefined) {
|
||||||
|
diffs.push({
|
||||||
|
path: change.path,
|
||||||
|
type: change.type,
|
||||||
|
before: currentContent,
|
||||||
|
after: newContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (change.type === 'delete') {
|
||||||
|
// Check if file exists before marking for deletion
|
||||||
|
try {
|
||||||
|
const currentContent = await plugins.smartfs.file(change.path).encoding('utf8').read() as string;
|
||||||
|
diffs.push({
|
||||||
|
path: change.path,
|
||||||
|
type: 'delete',
|
||||||
|
before: currentContent,
|
||||||
|
after: undefined,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// File doesn't exist, nothing to delete
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasDiff: diffs.length > 0,
|
||||||
|
diffs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a single diff using smartdiff
|
||||||
|
*/
|
||||||
|
displayDiff(diff: ICheckResult['diffs'][0]): void {
|
||||||
|
console.log(`\n--- ${diff.path}`);
|
||||||
|
if (diff.before && diff.after) {
|
||||||
|
console.log(plugins.smartdiff.formatLineDiffForConsole(diff.before, diff.after));
|
||||||
|
} else if (diff.after && !diff.before) {
|
||||||
|
console.log(' (new file)');
|
||||||
|
// Show first few lines of new content
|
||||||
|
const lines = diff.after.split('\n').slice(0, 10);
|
||||||
|
lines.forEach(line => console.log(` + ${line}`));
|
||||||
|
if (diff.after.split('\n').length > 10) {
|
||||||
|
console.log(' ... (truncated)');
|
||||||
|
}
|
||||||
|
} else if (diff.before && !diff.after) {
|
||||||
|
console.log(' (file will be deleted)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display all diffs from a check result
|
||||||
|
*/
|
||||||
|
displayAllDiffs(result: ICheckResult): void {
|
||||||
|
if (!result.hasDiff) {
|
||||||
|
console.log(' No changes detected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const diff of result.diffs) {
|
||||||
|
this.displayDiff(diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import { CopyFormatter } from './formatters/copy.formatter.js';
|
|||||||
|
|
||||||
export let run = async (
|
export let run = async (
|
||||||
options: {
|
options: {
|
||||||
dryRun?: boolean;
|
write?: boolean; // Explicitly write changes (default: false, dry-mode)
|
||||||
|
dryRun?: boolean; // Deprecated, kept for compatibility
|
||||||
yes?: boolean;
|
yes?: boolean;
|
||||||
planOnly?: boolean;
|
planOnly?: boolean;
|
||||||
savePlan?: string;
|
savePlan?: string;
|
||||||
@@ -28,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
|
||||||
@@ -35,7 +37,11 @@ export let run = async (
|
|||||||
setVerboseMode(true);
|
setVerboseMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const project = await Project.fromCwd();
|
// Determine if we should write changes
|
||||||
|
// Default is dry-mode (no writing) unless --write/-w is specified
|
||||||
|
const shouldWrite = options.write ?? (options.dryRun === false);
|
||||||
|
|
||||||
|
const project = await Project.fromCwd({ requireProjectType: false });
|
||||||
const context = new FormatContext();
|
const context = new FormatContext();
|
||||||
// Cache system removed - no longer needed
|
// Cache system removed - no longer needed
|
||||||
const planner = new FormatPlanner();
|
const planner = new FormatPlanner();
|
||||||
@@ -127,9 +133,24 @@ export let run = async (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dry-run mode
|
// Show diffs if requested (works in both dry-run and write modes)
|
||||||
if (options.dryRun) {
|
if (options.diff) {
|
||||||
logger.log('info', 'Dry-run mode - no changes will be made');
|
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)
|
||||||
|
if (!shouldWrite) {
|
||||||
|
logger.log('info', 'Dry-run mode - use --write (-w) to apply changes');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,14 +218,27 @@ export const handleCleanBackups = async (): Promise<void> => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Import the ICheckResult type for external use
|
||||||
|
import type { ICheckResult } from './interfaces.format.js';
|
||||||
|
export type { ICheckResult };
|
||||||
|
|
||||||
|
// Formatters that don't require projectType to be set
|
||||||
|
const formattersNotRequiringProjectType = ['npmextra', 'prettier', 'cleanup', 'packagejson'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a single formatter by name (for use by other modules)
|
* Run a single formatter by name (for use by other modules)
|
||||||
*/
|
*/
|
||||||
export const runFormatter = async (
|
export const runFormatter = async (
|
||||||
formatterName: string,
|
formatterName: string,
|
||||||
options: { silent?: boolean } = {}
|
options: {
|
||||||
): Promise<void> => {
|
silent?: boolean;
|
||||||
const project = await Project.fromCwd();
|
checkOnly?: boolean; // Only check for diffs, don't apply
|
||||||
|
showDiff?: boolean; // Show the diff output
|
||||||
|
} = {}
|
||||||
|
): Promise<ICheckResult | void> => {
|
||||||
|
// Determine if this formatter requires projectType
|
||||||
|
const requireProjectType = !formattersNotRequiringProjectType.includes(formatterName);
|
||||||
|
const project = await Project.fromCwd({ requireProjectType });
|
||||||
const context = new FormatContext();
|
const context = new FormatContext();
|
||||||
|
|
||||||
// Map formatter names to classes
|
// Map formatter names to classes
|
||||||
@@ -227,6 +261,17 @@ export const runFormatter = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const formatter = new FormatterClass(context, project);
|
const formatter = new FormatterClass(context, project);
|
||||||
|
|
||||||
|
// Check-only mode: just check for diffs and optionally display them
|
||||||
|
if (options.checkOnly) {
|
||||||
|
const result = await formatter.check();
|
||||||
|
if (result.hasDiff && options.showDiff) {
|
||||||
|
formatter.displayAllDiffs(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal mode: analyze and apply changes
|
||||||
const changes = await formatter.analyze();
|
const changes = await formatter.analyze();
|
||||||
|
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
|
|||||||
@@ -39,7 +39,18 @@ export type IPlannedChange = {
|
|||||||
path: string;
|
path: string;
|
||||||
module: string;
|
module: string;
|
||||||
description: string;
|
description: string;
|
||||||
content?: string; // For create/modify operations
|
content?: string; // New content for create/modify operations
|
||||||
|
originalContent?: string; // Original content for comparison
|
||||||
diff?: string;
|
diff?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface ICheckResult {
|
||||||
|
hasDiff: boolean;
|
||||||
|
diffs: Array<{
|
||||||
|
path: string;
|
||||||
|
type: 'create' | 'modify' | 'delete';
|
||||||
|
before?: string;
|
||||||
|
after?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,38 +7,85 @@ import * as paths from '../paths.js';
|
|||||||
import { logger } from '../gitzone.logging.js';
|
import { logger } from '../gitzone.logging.js';
|
||||||
|
|
||||||
export let run = async () => {
|
export let run = async () => {
|
||||||
const done = plugins.smartpromise.defer();
|
console.log('');
|
||||||
logger.log('warn', 'no action specified');
|
console.log('╭─────────────────────────────────────────────────────────────╮');
|
||||||
|
console.log('│ gitzone - Development Workflow CLI │');
|
||||||
|
console.log('╰─────────────────────────────────────────────────────────────╯');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
const dirEntries = await plugins.smartfs.directory(paths.templatesDir).list();
|
const interactInstance = new plugins.smartinteract.SmartInteract();
|
||||||
const templates: string[] = [];
|
const response = await interactInstance.askQuestion({
|
||||||
for (const entry of dirEntries) {
|
type: 'list',
|
||||||
try {
|
name: 'action',
|
||||||
const stats = await plugins.smartfs
|
message: 'What would you like to do?',
|
||||||
.file(plugins.path.join(paths.templatesDir, entry.path))
|
default: 'commit',
|
||||||
.stat();
|
choices: [
|
||||||
if (stats.isDirectory) {
|
{ name: 'Commit changes (semantic versioning)', value: 'commit' },
|
||||||
templates.push(entry.name);
|
{ name: 'Format project files', value: 'format' },
|
||||||
}
|
{ name: 'Configure release settings', value: 'config' },
|
||||||
} catch {
|
{ name: 'Create from template', value: 'template' },
|
||||||
// Skip entries that can't be accessed
|
{ name: 'Manage dev services (MongoDB, S3)', value: 'services' },
|
||||||
|
{ name: 'Open project assets', value: 'open' },
|
||||||
|
{ name: 'Show help', value: 'help' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const action = (response as any).value;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'commit': {
|
||||||
|
const modCommit = await import('../mod_commit/index.js');
|
||||||
|
await modCommit.run({ _: ['commit'] });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case 'format': {
|
||||||
|
const modFormat = await import('../mod_format/index.js');
|
||||||
|
await modFormat.run({ interactive: true });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'config': {
|
||||||
|
const modConfig = await import('../mod_config/index.js');
|
||||||
|
await modConfig.run({ _: ['config'] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'template': {
|
||||||
|
const modTemplate = await import('../mod_template/index.js');
|
||||||
|
await modTemplate.run({ _: ['template'] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'services': {
|
||||||
|
const modServices = await import('../mod_services/index.js');
|
||||||
|
await modServices.run({ _: ['services'] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'open': {
|
||||||
|
const modOpen = await import('../mod_open/index.js');
|
||||||
|
await modOpen.run({ _: ['open'] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'help':
|
||||||
|
showHelp();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let projects = `\n`;
|
|
||||||
for (const template of templates) {
|
|
||||||
projects += ` - ${template}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(
|
|
||||||
'info',
|
|
||||||
`
|
|
||||||
You can do one of the following things:
|
|
||||||
* create a new project with 'gitzone template [template]'
|
|
||||||
the following templates exist: ${projects}
|
|
||||||
* format a project with 'gitzone format'
|
|
||||||
`,
|
|
||||||
);
|
|
||||||
done.resolve();
|
|
||||||
return done.promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function showHelp(): void {
|
||||||
|
console.log('');
|
||||||
|
console.log('Usage: gitzone <command> [options]');
|
||||||
|
console.log('');
|
||||||
|
console.log('Commands:');
|
||||||
|
console.log(' commit Create a semantic commit with versioning');
|
||||||
|
console.log(' format Format and standardize project files');
|
||||||
|
console.log(' config Manage release registry configuration');
|
||||||
|
console.log(' template Create a new project from template');
|
||||||
|
console.log(' services Manage dev services (MongoDB, S3/MinIO)');
|
||||||
|
console.log(' open Open project assets (GitLab, npm, etc.)');
|
||||||
|
console.log(' docker Docker-related operations');
|
||||||
|
console.log(' deprecate Deprecate a package on npm');
|
||||||
|
console.log(' meta Run meta commands');
|
||||||
|
console.log(' start Start working on a project');
|
||||||
|
console.log(' helpers Run helper utilities');
|
||||||
|
console.log('');
|
||||||
|
console.log('Run gitzone <command> --help for more information on a command.');
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user