Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 27f2d265de | |||
| af3e15e922 | |||
| b44624f2e7 | |||
| 847e679e92 |
@@ -17,12 +17,10 @@ fileName: package.json
|
|||||||
"buildDocs": "(tsdoc)"
|
"buildDocs": "(tsdoc)"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.25",
|
"@git.zone/tsbuild": "^3.1.2",
|
||||||
"@git.zone/tsbundle": "^2.0.5",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tsrun": "^1.2.46",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@git.zone/tstest": "^1.0.44",
|
"@types/node": "^24.10.1"
|
||||||
"@push.rocks/tapbundle": "^5.0.15",
|
|
||||||
"@types/node": "^20.8.7"
|
|
||||||
},
|
},
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
import * as {{module.name}} from '../ts/index.js'
|
import * as {{module.name}} from '../ts/index.js'
|
||||||
|
|
||||||
tap.test('first test', async () => {
|
tap.test('first test', async () => {
|
||||||
console.log({{module.name}})
|
console.log({{module.name}})
|
||||||
})
|
})
|
||||||
|
|
||||||
tap.start()
|
export default tap.start()
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ fileName: package.json
|
|||||||
"build": "(tsbuild --web --allowimplicitany)"
|
"build": "(tsbuild --web --allowimplicitany)"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.17",
|
"@git.zone/tsbuild": "^3.1.2",
|
||||||
"@git.zone/tsrun": "^1.2.8",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tstest": "^1.0.28",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@git.zone/tswatch": "^2.0.1",
|
"@git.zone/tswatch": "^2.0.1",
|
||||||
"@push.rocks/tapbundle": "^5.5.4"
|
"@types/node": "^24.10.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedserver": "^3.0.53",
|
"@api.global/typedserver": "^3.0.53",
|
||||||
"@push.rocks/projectinfo": "^5.0.1",
|
"@push.rocks/projectinfo": "^5.0.2",
|
||||||
"@push.rocks/qenv": "^6.1.0",
|
"@push.rocks/qenv": "^6.1.0",
|
||||||
"@push.rocks/smartdata": "^5.0.7",
|
"@push.rocks/smartdata": "^5.0.7",
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"@push.rocks/smartstate": "^2.0.0"
|
"@push.rocks/smartstate": "^2.0.0"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
changelog.md
19
changelog.md
@@ -1,5 +1,24 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
- services: Add robust ServiceConfiguration (creates .nogit/env.json with sane defaults, syncs ports from existing Docker containers, validates and can reconfigure ports)
|
||||||
|
- services CLI: improved start/stop/restart flows, better logging/help output and enhanced global commands (list/status/stop/cleanup)
|
||||||
|
- templates/tests: replace @push.rocks/tapbundle with @git.zone/tstest and update template test.ts to export default tap.start()
|
||||||
|
- format: stop auto-updating tslint template and mark @push.rocks/tapbundle as deprecated in package formatting logic
|
||||||
|
- dependencies: bump @git.zone/tsbuild, @git.zone/tsrun, @git.zone/tstest, @git.zone/tsdoc, @push.rocks/projectinfo, @push.rocks/smartpath, @push.rocks/smartfs, prettier and other dev deps
|
||||||
|
- 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)
|
||||||
|
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)
|
||||||
|
- Add global CLI mode for services (use -g/--global) with commands: list, status, stop, cleanup (ts/mod_services/index.ts)
|
||||||
|
- ServiceManager now registers the current project with the global registry when starting services and unregisters when all containers are removed (ts/mod_services/classes.servicemanager.ts)
|
||||||
|
- Global handlers to list projects, show aggregated status, stop containers across projects and cleanup stale entries
|
||||||
|
- 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
|
||||||
|
|
||||||
|
|||||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@git.zone/cli",
|
"name": "@git.zone/cli",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "2.0.0",
|
"version": "2.2.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.",
|
||||||
"main": "dist_ts/index.ts",
|
"main": "dist_ts/index.ts",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/gitzone/private/gitzone#readme",
|
"homepage": "https://gitlab.com/gitzone/private/gitzone#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^3.1.0",
|
"@git.zone/tsbuild": "^3.1.2",
|
||||||
"@git.zone/tsrun": "^2.0.0",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tstest": "^3.1.3",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@push.rocks/smartdelay": "^3.0.5",
|
"@push.rocks/smartdelay": "^3.0.5",
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"@types/node": "^24.10.1"
|
"@types/node": "^24.10.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@git.zone/tsdoc": "^1.9.2",
|
"@git.zone/tsdoc": "^1.10.0",
|
||||||
"@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",
|
||||||
@@ -75,11 +75,10 @@
|
|||||||
"@push.rocks/lik": "^6.2.2",
|
"@push.rocks/lik": "^6.2.2",
|
||||||
"@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/smartchok": "^1.1.1",
|
|
||||||
"@push.rocks/smartcli": "^4.0.19",
|
"@push.rocks/smartcli": "^4.0.19",
|
||||||
"@push.rocks/smartdiff": "^1.0.3",
|
"@push.rocks/smartdiff": "^1.0.3",
|
||||||
"@push.rocks/smartfile": "^13.0.1",
|
"@push.rocks/smartfile": "^13.1.0",
|
||||||
"@push.rocks/smartfs": "^1.1.0",
|
"@push.rocks/smartfs": "^1.2.0",
|
||||||
"@push.rocks/smartgulp": "^3.0.4",
|
"@push.rocks/smartgulp": "^3.0.4",
|
||||||
"@push.rocks/smartjson": "^5.2.0",
|
"@push.rocks/smartjson": "^5.2.0",
|
||||||
"@push.rocks/smartlegal": "^1.0.27",
|
"@push.rocks/smartlegal": "^1.0.27",
|
||||||
@@ -96,7 +95,7 @@
|
|||||||
"@push.rocks/smartunique": "^3.0.9",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@push.rocks/smartupdate": "^2.0.6",
|
"@push.rocks/smartupdate": "^2.0.6",
|
||||||
"@types/through2": "^2.0.41",
|
"@types/through2": "^2.0.41",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.7.3",
|
||||||
"through2": "^4.0.2"
|
"through2": "^4.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
62
pnpm-lock.yaml
generated
62
pnpm-lock.yaml
generated
@@ -9,8 +9,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@git.zone/tsdoc':
|
'@git.zone/tsdoc':
|
||||||
specifier: ^1.9.2
|
specifier: ^1.10.0
|
||||||
version: 1.9.2(ws@8.18.3)(zod@3.25.76)
|
version: 1.10.0(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
|
||||||
@@ -32,9 +32,6 @@ importers:
|
|||||||
'@push.rocks/projectinfo':
|
'@push.rocks/projectinfo':
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.2
|
||||||
version: 5.0.2
|
version: 5.0.2
|
||||||
'@push.rocks/smartchok':
|
|
||||||
specifier: ^1.1.1
|
|
||||||
version: 1.1.1
|
|
||||||
'@push.rocks/smartcli':
|
'@push.rocks/smartcli':
|
||||||
specifier: ^4.0.19
|
specifier: ^4.0.19
|
||||||
version: 4.0.19
|
version: 4.0.19
|
||||||
@@ -42,11 +39,11 @@ importers:
|
|||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
'@push.rocks/smartfile':
|
'@push.rocks/smartfile':
|
||||||
specifier: ^13.0.1
|
specifier: ^13.1.0
|
||||||
version: 13.0.1(@push.rocks/smartfs@1.1.0)
|
version: 13.1.0
|
||||||
'@push.rocks/smartfs':
|
'@push.rocks/smartfs':
|
||||||
specifier: ^1.1.0
|
specifier: ^1.2.0
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
'@push.rocks/smartgulp':
|
'@push.rocks/smartgulp':
|
||||||
specifier: ^3.0.4
|
specifier: ^3.0.4
|
||||||
version: 3.0.4
|
version: 3.0.4
|
||||||
@@ -96,15 +93,15 @@ importers:
|
|||||||
specifier: ^2.0.41
|
specifier: ^2.0.41
|
||||||
version: 2.0.41
|
version: 2.0.41
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.6.2
|
specifier: ^3.7.3
|
||||||
version: 3.6.2
|
version: 3.7.3
|
||||||
through2:
|
through2:
|
||||||
specifier: ^4.0.2
|
specifier: ^4.0.2
|
||||||
version: 4.0.2
|
version: 4.0.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@git.zone/tsbuild':
|
'@git.zone/tsbuild':
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.2
|
||||||
version: 3.1.0
|
version: 3.1.2
|
||||||
'@git.zone/tsrun':
|
'@git.zone/tsrun':
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
@@ -634,16 +631,16 @@ packages:
|
|||||||
'@gerrit0/mini-shiki@3.14.0':
|
'@gerrit0/mini-shiki@3.14.0':
|
||||||
resolution: {integrity: sha512-c5X8fwPLOtUS8TVdqhynz9iV0GlOtFUT1ppXYzUUlEXe4kbZ/mvMT8wXoT8kCwUka+zsiloq7sD3pZ3+QVTuNQ==}
|
resolution: {integrity: sha512-c5X8fwPLOtUS8TVdqhynz9iV0GlOtFUT1ppXYzUUlEXe4kbZ/mvMT8wXoT8kCwUka+zsiloq7sD3pZ3+QVTuNQ==}
|
||||||
|
|
||||||
'@git.zone/tsbuild@3.1.0':
|
'@git.zone/tsbuild@3.1.2':
|
||||||
resolution: {integrity: sha512-j8lMd84pmzWiU6NG3e+pyu0o41oo6mQVfcZv8kDsCrQwZMhoQV9Jp87MlU0i/XI5IZkqDjelG8Kx1QhOmbK+iQ==}
|
resolution: {integrity: sha512-K0u840Qo0WEhvcpAtktvdBX6KEXjelU32o820WzcK7dMA7dd2YV+mPOEYfbmWLcdtFJkrjkigQq5fpLhTN4oKQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@git.zone/tsbundle@2.5.2':
|
'@git.zone/tsbundle@2.5.2':
|
||||||
resolution: {integrity: sha512-EYTCfunqoxhxkowREZ+cJnww6eDh9cL18HJbHbSZ+vxzNeyS9x8mT9aqRlWkI7zgpvgDlGIYlyRUlUISXkQO6Q==}
|
resolution: {integrity: sha512-EYTCfunqoxhxkowREZ+cJnww6eDh9cL18HJbHbSZ+vxzNeyS9x8mT9aqRlWkI7zgpvgDlGIYlyRUlUISXkQO6Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@git.zone/tsdoc@1.9.2':
|
'@git.zone/tsdoc@1.10.0':
|
||||||
resolution: {integrity: sha512-ibkQ9VD9kli9uSPJLHzfPLVOoqvIMZwh49CwGkgx1ISOpDzJuWpriCvaZJrH57gaovWiKUYnpgVe2vDFF8Ru8A==}
|
resolution: {integrity: sha512-sRssjKlEzTCVXvEa6wABHqey3IwQCOW273oXcam3GNgefh3rKatUVQhq+gQI0IXISE4ignR9cIIWFtSqgQVXnA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@git.zone/tspublish@1.10.3':
|
'@git.zone/tspublish@1.10.3':
|
||||||
@@ -1132,6 +1129,7 @@ packages:
|
|||||||
|
|
||||||
'@push.rocks/smartchok@1.1.1':
|
'@push.rocks/smartchok@1.1.1':
|
||||||
resolution: {integrity: sha512-WmNigGmn1muBJMANVuJb4F8x3TzgYrnn6YZm6ixTsG+0WFbYevivEwp+J4S7npobLHsR7ynf+Ky8LxRYmsL50A==}
|
resolution: {integrity: sha512-WmNigGmn1muBJMANVuJb4F8x3TzgYrnn6YZm6ixTsG+0WFbYevivEwp+J4S7npobLHsR7ynf+Ky8LxRYmsL50A==}
|
||||||
|
deprecated: This package has been renamed. Please use @push.rocks/smartwatch instead.
|
||||||
|
|
||||||
'@push.rocks/smartcli@4.0.19':
|
'@push.rocks/smartcli@4.0.19':
|
||||||
resolution: {integrity: sha512-s1jZSgDZWi/az26AY4TJ2HPuG1qZzGC5R9fKWaECLmwnSpk6y9JXL5dnJAUohcdu50kdXCWEcRmLfYxOt81vEA==}
|
resolution: {integrity: sha512-s1jZSgDZWi/az26AY4TJ2HPuG1qZzGC5R9fKWaECLmwnSpk6y9JXL5dnJAUohcdu50kdXCWEcRmLfYxOt81vEA==}
|
||||||
@@ -1184,19 +1182,14 @@ packages:
|
|||||||
'@push.rocks/smartfile@11.2.7':
|
'@push.rocks/smartfile@11.2.7':
|
||||||
resolution: {integrity: sha512-8Yp7/sAgPpWJBHohV92ogHWKzRomI5MEbSG6b5W2n18tqwfAmjMed0rQvsvGrSBlnEWCKgoOrYIIZbLO61+J0Q==}
|
resolution: {integrity: sha512-8Yp7/sAgPpWJBHohV92ogHWKzRomI5MEbSG6b5W2n18tqwfAmjMed0rQvsvGrSBlnEWCKgoOrYIIZbLO61+J0Q==}
|
||||||
|
|
||||||
'@push.rocks/smartfile@13.0.1':
|
'@push.rocks/smartfile@13.1.0':
|
||||||
resolution: {integrity: sha512-phtryDFtBYHo7R2H9V3Y7VeiYQU9YzKL140gKD3bTicBgXoIYrJ6+b3mbZunSO2yQt1Vy1AxCxYXrFE/K+4grw==}
|
resolution: {integrity: sha512-bSjH9vHl6l1nbe/gcSi4PcutFcTHUCVkMuQGGTVtn1cOgCuOXIHV04uhOXrZoKvlcSxxoiq8THolFt65lqn7cg==}
|
||||||
peerDependencies:
|
|
||||||
'@push.rocks/smartfs': ^1.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@push.rocks/smartfs':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@push.rocks/smartfm@2.2.2':
|
'@push.rocks/smartfm@2.2.2':
|
||||||
resolution: {integrity: sha512-kLrBv/vWXJmB558LI5C79fWXLKOnno998vnp3opfB+uyznT2E6LkcpKsxdjwe1V/r+Z5GlhXPOWmGgHPCzUR6w==}
|
resolution: {integrity: sha512-kLrBv/vWXJmB558LI5C79fWXLKOnno998vnp3opfB+uyznT2E6LkcpKsxdjwe1V/r+Z5GlhXPOWmGgHPCzUR6w==}
|
||||||
|
|
||||||
'@push.rocks/smartfs@1.1.0':
|
'@push.rocks/smartfs@1.2.0':
|
||||||
resolution: {integrity: sha512-fg8JIjFUPPX5laRoBpTaGwhMfZ3Y8mFT4fUaW54Y4J/BfOBa/y0+rIFgvgvqcOZgkQlyZU+FIfL8Z6zezqxyTg==}
|
resolution: {integrity: sha512-1R47jJZwX869z7DYgKeAZKTU1SbGnM7W/ZmgsI7AkQQhiascNqY3/gF4V5kIprmuf1WhpRbCbZyum8s7J1LDdg==}
|
||||||
|
|
||||||
'@push.rocks/smartgit@3.3.1':
|
'@push.rocks/smartgit@3.3.1':
|
||||||
resolution: {integrity: sha512-fnyF9Fr5y0ClSFiw/yMAWXlxvteWK2eXJ5i8/wsJcAyWqwTZ9KvMkVe33ofiZ/ZPuQ5JG9CXmoE0MST++5Xv6g==}
|
resolution: {integrity: sha512-fnyF9Fr5y0ClSFiw/yMAWXlxvteWK2eXJ5i8/wsJcAyWqwTZ9KvMkVe33ofiZ/ZPuQ5JG9CXmoE0MST++5Xv6g==}
|
||||||
@@ -3934,8 +3927,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
prettier@3.6.2:
|
prettier@3.7.3:
|
||||||
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
|
resolution: {integrity: sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -5811,7 +5804,7 @@ snapshots:
|
|||||||
'@shikijs/types': 3.14.0
|
'@shikijs/types': 3.14.0
|
||||||
'@shikijs/vscode-textmate': 10.0.2
|
'@shikijs/vscode-textmate': 10.0.2
|
||||||
|
|
||||||
'@git.zone/tsbuild@3.1.0':
|
'@git.zone/tsbuild@3.1.2':
|
||||||
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
|
||||||
@@ -5847,7 +5840,7 @@ snapshots:
|
|||||||
- '@swc/helpers'
|
- '@swc/helpers'
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@git.zone/tsdoc@1.9.2(ws@8.18.3)(zod@3.25.76)':
|
'@git.zone/tsdoc@1.10.0(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
|
||||||
@@ -6878,11 +6871,12 @@ snapshots:
|
|||||||
glob: 11.0.3
|
glob: 11.0.3
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
|
|
||||||
'@push.rocks/smartfile@13.0.1(@push.rocks/smartfs@1.1.0)':
|
'@push.rocks/smartfile@13.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
'@push.rocks/smartfile-interfaces': 1.0.7
|
'@push.rocks/smartfile-interfaces': 1.0.7
|
||||||
|
'@push.rocks/smartfs': 1.2.0
|
||||||
'@push.rocks/smarthash': 3.2.6
|
'@push.rocks/smarthash': 3.2.6
|
||||||
'@push.rocks/smartjson': 5.2.0
|
'@push.rocks/smartjson': 5.2.0
|
||||||
'@push.rocks/smartmime': 2.0.4
|
'@push.rocks/smartmime': 2.0.4
|
||||||
@@ -6893,14 +6887,12 @@ snapshots:
|
|||||||
'@types/js-yaml': 4.0.9
|
'@types/js-yaml': 4.0.9
|
||||||
glob: 11.0.3
|
glob: 11.0.3
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
optionalDependencies:
|
|
||||||
'@push.rocks/smartfs': 1.1.0
|
|
||||||
|
|
||||||
'@push.rocks/smartfm@2.2.2':
|
'@push.rocks/smartfm@2.2.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
gray-matter: 4.0.3
|
gray-matter: 4.0.3
|
||||||
|
|
||||||
'@push.rocks/smartfs@1.1.0':
|
'@push.rocks/smartfs@1.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartpath': 6.0.0
|
'@push.rocks/smartpath': 6.0.0
|
||||||
|
|
||||||
@@ -10517,7 +10509,7 @@ snapshots:
|
|||||||
|
|
||||||
possible-typed-array-names@1.1.0: {}
|
possible-typed-array-names@1.1.0: {}
|
||||||
|
|
||||||
prettier@3.6.2: {}
|
prettier@3.7.3: {}
|
||||||
|
|
||||||
pretty-ms@8.0.0:
|
pretty-ms@8.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
39
readme.md
39
readme.md
@@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
gitzone is a powerful command-line interface that supercharges your development workflow with automated project management, intelligent code formatting, seamless version control, and development service orchestration. Whether you're bootstrapping a new TypeScript project, maintaining code quality, managing complex multi-repository setups, or spinning up local development databases, gitzone has got you covered.
|
gitzone is a powerful command-line interface that supercharges your development workflow with automated project management, intelligent code formatting, seamless version control, and development service orchestration. Whether you're bootstrapping a new TypeScript project, maintaining code quality, managing complex multi-repository setups, or spinning up local development databases, gitzone has got you covered.
|
||||||
|
|
||||||
|
## Issue Reporting and Security
|
||||||
|
|
||||||
|
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
||||||
|
|
||||||
## 🏃♂️ Quick Start
|
## 🏃♂️ Quick Start
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
@@ -35,13 +39,13 @@ gitzone format
|
|||||||
# Start local MongoDB and MinIO services
|
# Start local MongoDB and MinIO services
|
||||||
gitzone services start
|
gitzone services start
|
||||||
|
|
||||||
# Create a semantic commit
|
# Create a semantic commit with AI-powered suggestions
|
||||||
gitzone commit
|
gitzone commit
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🛠️ Core Features
|
## 🛠️ Core Features
|
||||||
|
|
||||||
### 🐳 Development Services Management (NEW!)
|
### 🐳 Development Services Management
|
||||||
|
|
||||||
Effortlessly manage local MongoDB and MinIO (S3-compatible) services for your development environment:
|
Effortlessly manage local MongoDB and MinIO (S3-compatible) services for your development environment:
|
||||||
|
|
||||||
@@ -110,7 +114,7 @@ gitzone template [template-name]
|
|||||||
Each template comes pre-configured with:
|
Each template comes pre-configured with:
|
||||||
|
|
||||||
- ✅ TypeScript with modern configurations
|
- ✅ TypeScript with modern configurations
|
||||||
- ✅ Automated testing setup
|
- ✅ Automated testing setup with `@git.zone/tstest`
|
||||||
- ✅ CI/CD pipelines (GitLab/GitHub)
|
- ✅ CI/CD pipelines (GitLab/GitHub)
|
||||||
- ✅ Code formatting and linting
|
- ✅ Code formatting and linting
|
||||||
- ✅ Documentation structure
|
- ✅ Documentation structure
|
||||||
@@ -170,18 +174,27 @@ gitzone format --clean-backups
|
|||||||
- **Gitignore** - Repository ignore rules
|
- **Gitignore** - Repository ignore rules
|
||||||
- **Templates** - Project template updates
|
- **Templates** - Project template updates
|
||||||
- **Npmextra** - Extended npm configurations
|
- **Npmextra** - Extended npm configurations
|
||||||
|
- **Cleanup** - Removes obsolete files (yarn.lock, package-lock.json, tslint.json, etc.)
|
||||||
|
|
||||||
### 🔀 Semantic Commits & Versioning
|
### 🔀 Semantic Commits & Versioning
|
||||||
|
|
||||||
Create standardized commits that automatically handle versioning:
|
Create standardized commits with AI-powered suggestions that automatically handle versioning:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Interactive commit with AI recommendations
|
||||||
gitzone commit
|
gitzone commit
|
||||||
|
|
||||||
|
# Auto-accept AI recommendations
|
||||||
|
gitzone commit -y
|
||||||
|
|
||||||
|
# Auto-accept and push
|
||||||
|
gitzone commit -y -p
|
||||||
```
|
```
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
- 📝 Interactive commit message builder
|
- 🤖 **AI-powered analysis** - Analyzes your changes and suggests commit type, scope, and message
|
||||||
|
- 📝 Interactive commit message builder with smart defaults
|
||||||
- 🏷️ Automatic version bumping (major/minor/patch)
|
- 🏷️ Automatic version bumping (major/minor/patch)
|
||||||
- 📜 Changelog generation
|
- 📜 Changelog generation
|
||||||
- 🚀 Optional auto-push to origin
|
- 🚀 Optional auto-push to origin
|
||||||
@@ -189,11 +202,10 @@ Features:
|
|||||||
|
|
||||||
The commit wizard guides you through:
|
The commit wizard guides you through:
|
||||||
|
|
||||||
1. **Type selection** (feat/fix/docs/style/refactor/perf/test/chore)
|
1. **Type selection** (fix/feat/BREAKING CHANGE) with AI recommendation
|
||||||
2. **Scope definition** (component/module affected)
|
2. **Scope definition** (component/module affected)
|
||||||
3. **Description crafting**
|
3. **Description crafting**
|
||||||
4. **Breaking change detection**
|
4. **Version bump determination**
|
||||||
5. **Version bump determination**
|
|
||||||
|
|
||||||
### 🏗️ Meta Repository Management
|
### 🏗️ Meta Repository Management
|
||||||
|
|
||||||
@@ -443,7 +455,6 @@ gitzone services clean # ⚠️ Warning: deletes data
|
|||||||
|
|
||||||
- **TypeScript** - First-class support
|
- **TypeScript** - First-class support
|
||||||
- **Prettier** - Code formatting
|
- **Prettier** - Code formatting
|
||||||
- **ESLint** - Linting (via format modules)
|
|
||||||
- **npm/pnpm** - Package management
|
- **npm/pnpm** - Package management
|
||||||
- **MongoDB** - Local database service
|
- **MongoDB** - Local database service
|
||||||
- **MinIO** - S3-compatible object storage
|
- **MinIO** - S3-compatible object storage
|
||||||
@@ -522,19 +533,21 @@ gitzone is optimized for speed:
|
|||||||
|
|
||||||
## License and Legal Information
|
## License and Legal Information
|
||||||
|
|
||||||
This 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.
|
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
### Trademarks
|
### Trademarks
|
||||||
|
|
||||||
This 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.
|
This 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 or third parties, 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 or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
||||||
|
|
||||||
### Company Information
|
### Company Information
|
||||||
|
|
||||||
Task Venture Capital GmbH
|
Task Venture Capital GmbH
|
||||||
Registered at District court Bremen HRB 35230 HB, Germany
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||||
|
|
||||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
||||||
|
|
||||||
By 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.
|
By 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.
|
||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/cli',
|
name: '@git.zone/cli',
|
||||||
version: '2.0.0',
|
version: '2.2.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.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,10 +154,11 @@ export const run = async (projectArg: Project) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// check for dependencies
|
// check for dependencies
|
||||||
|
// Note: @push.rocks/tapbundle is deprecated - use @git.zone/tstest/tapbundle instead
|
||||||
await ensureDependency(
|
await ensureDependency(
|
||||||
packageJson,
|
packageJson,
|
||||||
'devDep',
|
'devDep',
|
||||||
'latest',
|
'exclude',
|
||||||
'@push.rocks/tapbundle',
|
'@push.rocks/tapbundle',
|
||||||
);
|
);
|
||||||
await ensureDependency(
|
await ensureDependency(
|
||||||
|
|||||||
@@ -10,12 +10,6 @@ import { Project } from '../classes.project.js';
|
|||||||
export const run = async (project: Project) => {
|
export const run = async (project: Project) => {
|
||||||
const templateModule = await import('../mod_template/index.js');
|
const templateModule = await import('../mod_template/index.js');
|
||||||
|
|
||||||
// update tslint
|
|
||||||
// getting template
|
|
||||||
const tslintTemplate = await templateModule.getTemplate('tslint');
|
|
||||||
await tslintTemplate.writeToDisk(paths.cwd);
|
|
||||||
logger.log('info', 'Updated tslint.json!');
|
|
||||||
|
|
||||||
// update vscode
|
// update vscode
|
||||||
const vscodeTemplate = await templateModule.getTemplate('vscode');
|
const vscodeTemplate = await templateModule.getTemplate('vscode');
|
||||||
await vscodeTemplate.writeToDisk(paths.cwd);
|
await vscodeTemplate.writeToDisk(paths.cwd);
|
||||||
|
|||||||
190
ts/mod_services/classes.globalregistry.ts
Normal file
190
ts/mod_services/classes.globalregistry.ts
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import { DockerContainer } from './classes.dockercontainer.js';
|
||||||
|
import { logger } from '../gitzone.logging.js';
|
||||||
|
|
||||||
|
export interface IRegisteredProject {
|
||||||
|
projectPath: string;
|
||||||
|
projectName: string;
|
||||||
|
containers: {
|
||||||
|
mongo?: string;
|
||||||
|
minio?: string;
|
||||||
|
elasticsearch?: string;
|
||||||
|
};
|
||||||
|
ports: {
|
||||||
|
mongo?: number;
|
||||||
|
s3?: number;
|
||||||
|
s3Console?: number;
|
||||||
|
elasticsearch?: number;
|
||||||
|
};
|
||||||
|
enabledServices: string[];
|
||||||
|
lastActive: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGlobalRegistryData {
|
||||||
|
projects: { [projectPath: string]: IRegisteredProject };
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GlobalRegistry {
|
||||||
|
private static instance: GlobalRegistry | null = null;
|
||||||
|
private kvStore: plugins.npmextra.KeyValueStore<IGlobalRegistryData>;
|
||||||
|
private docker: DockerContainer;
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
this.kvStore = new plugins.npmextra.KeyValueStore({
|
||||||
|
typeArg: 'userHomeDir',
|
||||||
|
identityArg: 'gitzone-services',
|
||||||
|
});
|
||||||
|
this.docker = new DockerContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the singleton instance
|
||||||
|
*/
|
||||||
|
public static getInstance(): GlobalRegistry {
|
||||||
|
if (!GlobalRegistry.instance) {
|
||||||
|
GlobalRegistry.instance = new GlobalRegistry();
|
||||||
|
}
|
||||||
|
return GlobalRegistry.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register or update a project in the global registry
|
||||||
|
*/
|
||||||
|
public async registerProject(data: Omit<IRegisteredProject, 'lastActive'>): Promise<void> {
|
||||||
|
const allData = await this.kvStore.readAll();
|
||||||
|
const projects = allData.projects || {};
|
||||||
|
|
||||||
|
projects[data.projectPath] = {
|
||||||
|
...data,
|
||||||
|
lastActive: Date.now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.kvStore.writeKey('projects', projects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a project from the registry
|
||||||
|
*/
|
||||||
|
public async unregisterProject(projectPath: string): Promise<void> {
|
||||||
|
const allData = await this.kvStore.readAll();
|
||||||
|
const projects = allData.projects || {};
|
||||||
|
|
||||||
|
if (projects[projectPath]) {
|
||||||
|
delete projects[projectPath];
|
||||||
|
await this.kvStore.writeKey('projects', projects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the lastActive timestamp for a project
|
||||||
|
*/
|
||||||
|
public async touchProject(projectPath: string): Promise<void> {
|
||||||
|
const allData = await this.kvStore.readAll();
|
||||||
|
const projects = allData.projects || {};
|
||||||
|
|
||||||
|
if (projects[projectPath]) {
|
||||||
|
projects[projectPath].lastActive = Date.now();
|
||||||
|
await this.kvStore.writeKey('projects', projects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered projects
|
||||||
|
*/
|
||||||
|
public async getAllProjects(): Promise<{ [path: string]: IRegisteredProject }> {
|
||||||
|
const allData = await this.kvStore.readAll();
|
||||||
|
return allData.projects || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a project is registered
|
||||||
|
*/
|
||||||
|
public async isRegistered(projectPath: string): Promise<boolean> {
|
||||||
|
const projects = await this.getAllProjects();
|
||||||
|
return !!projects[projectPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get status of all containers across all registered projects
|
||||||
|
*/
|
||||||
|
public async getGlobalStatus(): Promise<
|
||||||
|
Array<{
|
||||||
|
projectPath: string;
|
||||||
|
projectName: string;
|
||||||
|
containers: Array<{ name: string; status: string }>;
|
||||||
|
lastActive: number;
|
||||||
|
}>
|
||||||
|
> {
|
||||||
|
const projects = await this.getAllProjects();
|
||||||
|
const result: Array<{
|
||||||
|
projectPath: string;
|
||||||
|
projectName: string;
|
||||||
|
containers: Array<{ name: string; status: string }>;
|
||||||
|
lastActive: number;
|
||||||
|
}> = [];
|
||||||
|
|
||||||
|
for (const [path, project] of Object.entries(projects)) {
|
||||||
|
const containerStatuses: Array<{ name: string; status: string }> = [];
|
||||||
|
|
||||||
|
for (const containerName of Object.values(project.containers)) {
|
||||||
|
if (containerName) {
|
||||||
|
const status = await this.docker.getStatus(containerName);
|
||||||
|
containerStatuses.push({ name: containerName, status });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push({
|
||||||
|
projectPath: path,
|
||||||
|
projectName: project.projectName,
|
||||||
|
containers: containerStatuses,
|
||||||
|
lastActive: project.lastActive,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop all containers across all registered projects
|
||||||
|
*/
|
||||||
|
public async stopAll(): Promise<{ stopped: string[]; failed: string[] }> {
|
||||||
|
const projects = await this.getAllProjects();
|
||||||
|
const stopped: string[] = [];
|
||||||
|
const failed: string[] = [];
|
||||||
|
|
||||||
|
for (const project of Object.values(projects)) {
|
||||||
|
for (const containerName of Object.values(project.containers)) {
|
||||||
|
if (containerName) {
|
||||||
|
const status = await this.docker.getStatus(containerName);
|
||||||
|
if (status === 'running') {
|
||||||
|
if (await this.docker.stop(containerName)) {
|
||||||
|
stopped.push(containerName);
|
||||||
|
} else {
|
||||||
|
failed.push(containerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { stopped, failed };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove stale registry entries (projects that no longer exist on disk)
|
||||||
|
*/
|
||||||
|
public async cleanup(): Promise<string[]> {
|
||||||
|
const projects = await this.getAllProjects();
|
||||||
|
const removed: string[] = [];
|
||||||
|
|
||||||
|
for (const projectPath of Object.keys(projects)) {
|
||||||
|
const exists = await plugins.smartfs.directory(projectPath).exists();
|
||||||
|
if (!exists) {
|
||||||
|
await this.unregisterProject(projectPath);
|
||||||
|
removed.push(projectPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,16 +2,19 @@ import * as plugins from './mod.plugins.js';
|
|||||||
import * as helpers from './helpers.js';
|
import * as helpers from './helpers.js';
|
||||||
import { ServiceConfiguration } from './classes.serviceconfiguration.js';
|
import { ServiceConfiguration } from './classes.serviceconfiguration.js';
|
||||||
import { DockerContainer } from './classes.dockercontainer.js';
|
import { DockerContainer } from './classes.dockercontainer.js';
|
||||||
|
import { GlobalRegistry } from './classes.globalregistry.js';
|
||||||
import { logger } from '../gitzone.logging.js';
|
import { logger } from '../gitzone.logging.js';
|
||||||
|
|
||||||
export class ServiceManager {
|
export class ServiceManager {
|
||||||
private config: ServiceConfiguration;
|
private config: ServiceConfiguration;
|
||||||
private docker: DockerContainer;
|
private docker: DockerContainer;
|
||||||
private enabledServices: string[] | null = null;
|
private enabledServices: string[] | null = null;
|
||||||
|
private globalRegistry: GlobalRegistry;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.config = new ServiceConfiguration();
|
this.config = new ServiceConfiguration();
|
||||||
this.docker = new DockerContainer();
|
this.docker = new DockerContainer();
|
||||||
|
this.globalRegistry = GlobalRegistry.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,6 +110,31 @@ export class ServiceManager {
|
|||||||
return this.enabledServices.includes(service);
|
return this.enabledServices.includes(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register this project with the global registry
|
||||||
|
*/
|
||||||
|
private async registerWithGlobalRegistry(): Promise<void> {
|
||||||
|
const config = this.config.getConfig();
|
||||||
|
const containers = this.config.getContainerNames();
|
||||||
|
|
||||||
|
await this.globalRegistry.registerProject({
|
||||||
|
projectPath: process.cwd(),
|
||||||
|
projectName: config.PROJECT_NAME,
|
||||||
|
containers: {
|
||||||
|
mongo: containers.mongo,
|
||||||
|
minio: containers.minio,
|
||||||
|
elasticsearch: containers.elasticsearch,
|
||||||
|
},
|
||||||
|
ports: {
|
||||||
|
mongo: parseInt(config.MONGODB_PORT),
|
||||||
|
s3: parseInt(config.S3_PORT),
|
||||||
|
s3Console: parseInt(config.S3_CONSOLE_PORT),
|
||||||
|
elasticsearch: parseInt(config.ELASTICSEARCH_PORT),
|
||||||
|
},
|
||||||
|
enabledServices: this.enabledServices || ['mongodb', 'minio', 'elasticsearch'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start all enabled services
|
* Start all enabled services
|
||||||
*/
|
*/
|
||||||
@@ -127,6 +155,9 @@ export class ServiceManager {
|
|||||||
await this.startElasticsearch();
|
await this.startElasticsearch();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register with global registry
|
||||||
|
await this.registerWithGlobalRegistry();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -808,6 +839,15 @@ export class ServiceManager {
|
|||||||
if (!removed) {
|
if (!removed) {
|
||||||
logger.log('note', ' No containers to remove');
|
logger.log('note', ' No containers to remove');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if all containers are gone, then unregister from global registry
|
||||||
|
const mongoExists = await this.docker.exists(containers.mongo);
|
||||||
|
const minioExists = await this.docker.exists(containers.minio);
|
||||||
|
const esExists = await this.docker.exists(containers.elasticsearch);
|
||||||
|
|
||||||
|
if (!mongoExists && !minioExists && !esExists) {
|
||||||
|
await this.globalRegistry.unregisterProject(process.cwd());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.js';
|
||||||
import * as helpers from './helpers.js';
|
import * as helpers from './helpers.js';
|
||||||
import { ServiceManager } from './classes.servicemanager.js';
|
import { ServiceManager } from './classes.servicemanager.js';
|
||||||
|
import { GlobalRegistry } from './classes.globalregistry.js';
|
||||||
import { logger } from '../gitzone.logging.js';
|
import { logger } from '../gitzone.logging.js';
|
||||||
|
|
||||||
export const run = async (argvArg: any) => {
|
export const run = async (argvArg: any) => {
|
||||||
|
const isGlobal = argvArg.g || argvArg.global;
|
||||||
|
const command = argvArg._[1] || 'help';
|
||||||
|
|
||||||
|
// Handle global commands first
|
||||||
|
if (isGlobal) {
|
||||||
|
await handleGlobalCommand(command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local project commands
|
||||||
const serviceManager = new ServiceManager();
|
const serviceManager = new ServiceManager();
|
||||||
await serviceManager.init();
|
await serviceManager.init();
|
||||||
|
|
||||||
const command = argvArg._[1] || 'help';
|
|
||||||
const service = argvArg._[2] || 'all';
|
const service = argvArg._[2] || 'all';
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
@@ -249,4 +259,175 @@ function showHelp() {
|
|||||||
logger.log('info', ' gitzone services config # Show configuration');
|
logger.log('info', ' gitzone services config # Show configuration');
|
||||||
logger.log('info', ' gitzone services compass # Get MongoDB Compass connection');
|
logger.log('info', ' gitzone services compass # Get MongoDB Compass connection');
|
||||||
logger.log('info', ' gitzone services logs elasticsearch # Show Elasticsearch logs');
|
logger.log('info', ' gitzone services logs elasticsearch # Show Elasticsearch logs');
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
logger.log('note', 'Global Commands (-g/--global):');
|
||||||
|
logger.log('info', ' list -g List all registered projects');
|
||||||
|
logger.log('info', ' status -g Show status across all projects');
|
||||||
|
logger.log('info', ' stop -g Stop all containers across all projects');
|
||||||
|
logger.log('info', ' cleanup -g Remove stale registry entries');
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
logger.log('note', 'Global Examples:');
|
||||||
|
logger.log('info', ' gitzone services list -g # List all registered projects');
|
||||||
|
logger.log('info', ' gitzone services status -g # Show global container status');
|
||||||
|
logger.log('info', ' gitzone services stop -g # Stop all (prompts for confirmation)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Global Command Handlers ====================
|
||||||
|
|
||||||
|
async function handleGlobalCommand(command: string) {
|
||||||
|
const globalRegistry = GlobalRegistry.getInstance();
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case 'list':
|
||||||
|
await handleGlobalList(globalRegistry);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'status':
|
||||||
|
await handleGlobalStatus(globalRegistry);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'stop':
|
||||||
|
await handleGlobalStop(globalRegistry);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'cleanup':
|
||||||
|
await handleGlobalCleanup(globalRegistry);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'help':
|
||||||
|
default:
|
||||||
|
showHelp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleGlobalList(globalRegistry: GlobalRegistry) {
|
||||||
|
helpers.printHeader('Registered Projects (Global)');
|
||||||
|
|
||||||
|
const projects = await globalRegistry.getAllProjects();
|
||||||
|
const projectPaths = Object.keys(projects);
|
||||||
|
|
||||||
|
if (projectPaths.length === 0) {
|
||||||
|
logger.log('note', 'No projects registered');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const path of projectPaths) {
|
||||||
|
const project = projects[path];
|
||||||
|
const lastActive = new Date(project.lastActive).toLocaleString();
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
logger.log('ok', `📁 ${project.projectName}`);
|
||||||
|
logger.log('info', ` Path: ${project.projectPath}`);
|
||||||
|
logger.log('info', ` Services: ${project.enabledServices.join(', ')}`);
|
||||||
|
logger.log('info', ` Last Active: ${lastActive}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleGlobalStatus(globalRegistry: GlobalRegistry) {
|
||||||
|
helpers.printHeader('Global Service Status');
|
||||||
|
|
||||||
|
const statuses = await globalRegistry.getGlobalStatus();
|
||||||
|
|
||||||
|
if (statuses.length === 0) {
|
||||||
|
logger.log('note', 'No projects registered');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let runningCount = 0;
|
||||||
|
let totalContainers = 0;
|
||||||
|
|
||||||
|
for (const project of statuses) {
|
||||||
|
console.log();
|
||||||
|
logger.log('ok', `📁 ${project.projectName}`);
|
||||||
|
logger.log('info', ` Path: ${project.projectPath}`);
|
||||||
|
|
||||||
|
if (project.containers.length === 0) {
|
||||||
|
logger.log('note', ' No containers configured');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const container of project.containers) {
|
||||||
|
totalContainers++;
|
||||||
|
const statusIcon = container.status === 'running' ? '🟢' : container.status === 'exited' ? '🟡' : '⚪';
|
||||||
|
if (container.status === 'running') runningCount++;
|
||||||
|
logger.log('info', ` ${statusIcon} ${container.name}: ${container.status}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
logger.log('note', `Summary: ${runningCount}/${totalContainers} containers running across ${statuses.length} project(s)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleGlobalStop(globalRegistry: GlobalRegistry) {
|
||||||
|
helpers.printHeader('Stop All Containers (Global)');
|
||||||
|
|
||||||
|
const statuses = await globalRegistry.getGlobalStatus();
|
||||||
|
|
||||||
|
// Count running containers
|
||||||
|
let runningCount = 0;
|
||||||
|
for (const project of statuses) {
|
||||||
|
for (const container of project.containers) {
|
||||||
|
if (container.status === 'running') runningCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runningCount === 0) {
|
||||||
|
logger.log('note', 'No running containers found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log('note', `Found ${runningCount} running container(s) across ${statuses.length} project(s)`);
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
// Show what will be stopped
|
||||||
|
for (const project of statuses) {
|
||||||
|
const runningContainers = project.containers.filter(c => c.status === 'running');
|
||||||
|
if (runningContainers.length > 0) {
|
||||||
|
logger.log('info', `${project.projectName}:`);
|
||||||
|
for (const container of runningContainers) {
|
||||||
|
logger.log('info', ` • ${container.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
const shouldContinue = await plugins.smartinteract.SmartInteract.getCliConfirmation(
|
||||||
|
'Stop all containers?',
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!shouldContinue) {
|
||||||
|
logger.log('note', 'Cancelled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log('note', 'Stopping all containers...');
|
||||||
|
const result = await globalRegistry.stopAll();
|
||||||
|
|
||||||
|
if (result.stopped.length > 0) {
|
||||||
|
logger.log('ok', `Stopped: ${result.stopped.join(', ')}`);
|
||||||
|
}
|
||||||
|
if (result.failed.length > 0) {
|
||||||
|
logger.log('error', `Failed to stop: ${result.failed.join(', ')}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleGlobalCleanup(globalRegistry: GlobalRegistry) {
|
||||||
|
helpers.printHeader('Cleanup Registry (Global)');
|
||||||
|
|
||||||
|
logger.log('note', 'Checking for stale registry entries...');
|
||||||
|
const removed = await globalRegistry.cleanup();
|
||||||
|
|
||||||
|
if (removed.length === 0) {
|
||||||
|
logger.log('ok', 'No stale entries found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log('ok', `Removed ${removed.length} stale entr${removed.length === 1 ? 'y' : 'ies'}:`);
|
||||||
|
for (const path of removed) {
|
||||||
|
logger.log('info', ` • ${path}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user