Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8507e54a56 | |||
| 0fe92d1438 | |||
| b2c926e9ae | |||
| 8add9a3dde | |||
| 79f9967db6 | |||
| 72de264b0d | |||
| 703cb25e2a | |||
| 65906f7e5f | |||
| 57e4d1c043 | |||
| f495f85bdb | |||
| d53e8fec6d | |||
| 00fef1ae06 | |||
| 4c1608cf94 | |||
| e0c4cf2983 | |||
| e3eb0af434 | |||
| 8d25d28b54 | |||
| 4237e49f14 | |||
| 019f7e2d88 | |||
| abaeb7be6c | |||
| ab714377ba | |||
| 450b3ba379 | |||
| 0daae0bd07 | |||
| 826f3a6c63 | |||
| c1a4671ce1 | |||
| 73a6d5bc31 | |||
| e15a569391 | |||
| 74809bd8d4 | |||
| 5b852d9602 | |||
| f68254eea7 | |||
| 5935c67f2e | |||
| 98f5353744 | |||
| 1372a2bb7e | |||
| fa16aaa2c1 | |||
| c3892096b6 | |||
| 4e6646b133 | |||
| da6739be6a | |||
| f72217250d | |||
| 4c36174b0d | |||
| 5f34bc8042 | |||
| 6d354a10d0 | |||
| 8208ba2970 | |||
| 3c2b51d47e | |||
| 12fab84daa | |||
| 4b5b683fff | |||
| ec1958d882 | |||
| 1f59cd4ba1 | |||
| 74c0d537cc | |||
| c4706e96cb | |||
| 628b86cf3d | |||
| d0c6ebb0df | |||
| dd8c30e7cf | |||
| 8f861d86c9 | |||
| fe2581b533 | |||
| db906cea1a |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -3,7 +3,6 @@
|
|||||||
# artifacts
|
# artifacts
|
||||||
coverage/
|
coverage/
|
||||||
public/
|
public/
|
||||||
pages/
|
|
||||||
|
|
||||||
# installs
|
# installs
|
||||||
node_modules/
|
node_modules/
|
||||||
@@ -15,8 +14,10 @@ node_modules/
|
|||||||
|
|
||||||
# builds
|
# builds
|
||||||
dist/
|
dist/
|
||||||
dist_web/
|
dist_*/
|
||||||
dist_serve/
|
|
||||||
dist_ts_web/
|
|
||||||
|
|
||||||
# custom
|
# AI
|
||||||
|
.claude/
|
||||||
|
.serena/
|
||||||
|
|
||||||
|
#------# custom
|
||||||
105
.gitlab-ci.yml
105
.gitlab-ci.yml
@@ -1,105 +0,0 @@
|
|||||||
# gitzone ci_default
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .npmci_cache/
|
|
||||||
key: "$CI_BUILD_STAGE"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- security
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- metadata
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
mirror:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci git mirror
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
snyk:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci command npm install -g snyk
|
|
||||||
- npmci command npm install --ignore-scripts
|
|
||||||
- npmci command snyk test
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# test stage
|
|
||||||
# ====================
|
|
||||||
|
|
||||||
testLTS:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci node install lts
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# metadata stage
|
|
||||||
# ====================
|
|
||||||
codequality:
|
|
||||||
stage: metadata
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g tslint typescript
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- priv
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
pages:
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g @gitzone/tsdoc
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command tsdoc
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
allow_failure: true
|
|
||||||
22
.snyk
22
.snyk
@@ -1,22 +0,0 @@
|
|||||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
|
||||||
version: v1.12.0
|
|
||||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
|
||||||
ignore:
|
|
||||||
'npm:lodash:20180130':
|
|
||||||
- smartenv > beautylog > cli-table2 > lodash:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-07-07T20:45:00.571Z'
|
|
||||||
- smartenv > smartenv > beautylog > cli-table2 > lodash:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-07-07T20:45:00.571Z'
|
|
||||||
- smartenv > smartparam > beautylog > cli-table2 > lodash:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-07-07T20:45:00.571Z'
|
|
||||||
- smartenv > smartparam > beautylog > smartenv > beautylog > cli-table2 > lodash:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-07-07T20:45:00.571Z'
|
|
||||||
'npm:shelljs:20140723':
|
|
||||||
- smartshell > shelljs:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-07-07T20:45:00.571Z'
|
|
||||||
patch: {}
|
|
||||||
29
.vscode/launch.json
vendored
Normal file
29
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "current file",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"${relativeFile}"
|
||||||
|
],
|
||||||
|
"runtimeArgs": ["-r", "@git.zone/tsrun"],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"protocol": "inspector",
|
||||||
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "test.ts",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"test/test.ts"
|
||||||
|
],
|
||||||
|
"runtimeArgs": ["-r", "@git.zone/tsrun"],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"protocol": "inspector",
|
||||||
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["/npmextra.json"],
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"npmci": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for npmci"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for gitzone",
|
||||||
|
"properties": {
|
||||||
|
"projectType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2016 Lossless GmbH
|
Copyright (c) 2016 Task Venture Capital GmbH
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -1,28 +0,0 @@
|
|||||||
# @gitzone/tools
|
|
||||||
setup your environment with the most important tools and update them easily.
|
|
||||||
|
|
||||||
## Availabililty and Links
|
|
||||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@gitzone/tools)
|
|
||||||
* [gitlab.com (source)](https://gitlab.com/gitzone/tools)
|
|
||||||
* [github.com (source mirror)](https://github.com/gitzone/tools)
|
|
||||||
* [docs (typedoc)](https://gitzone.gitlab.io/tools/)
|
|
||||||
|
|
||||||
## Status for master
|
|
||||||
[](https://gitlab.com/gitzone/tools/commits/master)
|
|
||||||
[](https://gitlab.com/gitzone/tools/commits/master)
|
|
||||||
[](https://www.npmjs.com/package/@gitzone/tools)
|
|
||||||
[](https://snyk.io/test/npm/@gitzone/tools)
|
|
||||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
|
||||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
|
||||||
[](https://prettier.io/)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Use TypeScript for best in class instellisense.
|
|
||||||
|
|
||||||
For further information read the linked docs at the top of this readme.
|
|
||||||
|
|
||||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
|
||||||
|
|
||||||
[](https://maintainedby.lossless.com)
|
|
||||||
159
changelog.md
Normal file
159
changelog.md
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-02-09 - 3.5.0 - feat(install)
|
||||||
|
add interactive install command and module to detect and install missing @git.zone packages
|
||||||
|
|
||||||
|
- Add ts/mod_install/index.ts: implements interactive/non-interactive flow to detect package managers, collect installed @git.zone packages, prompt user (via smartinteract) and install selected packages via PackageManagerUtil.
|
||||||
|
- Add ts/mod_install/mod.plugins.ts: re-export smartinteract and smartshell for the installer.
|
||||||
|
- Update ts/tools.cli.ts: register new 'install' command and add help text for install flags.
|
||||||
|
- Update ts/mod_update/index.ts: export GITZONE_PACKAGES and print a summary of managed packages that are not installed with latest versions and a suggestion to run 'gtools install'.
|
||||||
|
|
||||||
|
## 2026-02-09 - 3.4.1 - fix(tools)
|
||||||
|
no changes to commit
|
||||||
|
|
||||||
|
- No files changed in this diff
|
||||||
|
- Current package version is 3.4.0 — no version bump required
|
||||||
|
|
||||||
|
## 2026-02-09 - 3.4.0 - feat(mod_update)
|
||||||
|
add @git.zone/tsrust to supported modules list
|
||||||
|
|
||||||
|
- ts/mod_update/index.ts: added '@git.zone/tsrust' to the modules array
|
||||||
|
|
||||||
|
## 2026-02-06 - 3.3.0 - feat(mod_update)
|
||||||
|
add self-update flow, package name parser, dynamic CLI version, and tests
|
||||||
|
|
||||||
|
- Add a self-update check in mod_update to detect and optionally update @git.zone/tools (prompts the user or uses --yes).
|
||||||
|
- Introduce PackageManagerUtil.parseYarnPackageName to correctly parse scoped and unscoped yarn package strings and use it when collecting installed packages.
|
||||||
|
- Add comprehensive unit tests for PackageManagerUtil.isNewerVersion and parseYarnPackageName.
|
||||||
|
- Use commitinfo.version for CLI reported version instead of a hardcoded value.
|
||||||
|
- Remove automatic invocation of runCli() from ts/index.ts to avoid immediate execution on import.
|
||||||
|
|
||||||
|
## 2026-02-05 - 3.2.0 - feat(update)
|
||||||
|
enhance package manager detection, version reporting, and add verbose option
|
||||||
|
|
||||||
|
- Add IPackageManagerInfo interface and detectPackageManager() to robustly detect npm/yarn/pnpm via 'which' and '--version' fallbacks
|
||||||
|
- Make isAvailable() delegate to detectPackageManager() and return structured detection info
|
||||||
|
- Add getPackageManagerVersion() to obtain current and latest versions (parses local --version and queries npm registry)
|
||||||
|
- Update run() to support a verbose flag, show a package-manager status table, and collect detectedPMs with version/update status
|
||||||
|
- Update CLI help and command handling to accept --verbose/-v and pass it through to mod_update.run()
|
||||||
|
|
||||||
|
## 2026-02-03 - 3.1.3 - fix(mod_update)
|
||||||
|
try private registry (verdaccio.lossless.digital) first when fetching package versions; fall back to public npm; handle unknown latest versions gracefully in output
|
||||||
|
|
||||||
|
- getLatestVersion now attempts a direct API request to https://verdaccio.lossless.digital/<encoded-package> and parses dist-tags.latest
|
||||||
|
- Falls back to npm view when the private registry request fails
|
||||||
|
- Scoped package names are URL-encoded (replaces '/' with '%2f') before querying the private registry
|
||||||
|
- Packages with no resolvable latest version are included with latestVersion set to 'unknown' and displayed as '? Version unknown'
|
||||||
|
- needsUpdate is set to false when latest version is unknown
|
||||||
|
|
||||||
|
## 2026-02-03 - 3.1.2 - fix(scripts)
|
||||||
|
make test script output verbose by using --verbose instead of --web
|
||||||
|
|
||||||
|
- package.json: change npm "test" script from "(tstest test/ --web)" to "(tstest test/ --verbose)" to enable verbose test output
|
||||||
|
|
||||||
|
## 2026-02-03 - 3.1.1 - fix(tools)
|
||||||
|
no changes detected
|
||||||
|
|
||||||
|
- No files were modified in this diff
|
||||||
|
- No code or documentation changes to include in a commit message
|
||||||
|
|
||||||
|
## 2026-02-03 - 3.1.0 - feat(cli)
|
||||||
|
add update command to check and update globally installed @git.zone packages
|
||||||
|
|
||||||
|
- Adds a new mod_update module and PackageManagerUtil to detect installed @git.zone packages and fetch latest versions
|
||||||
|
- Supports npm, yarn and pnpm: detection, listing, version comparison and executing updates
|
||||||
|
- Interactive confirmation via @push.rocks/smartinteract with a -y flag to skip prompt
|
||||||
|
- Uses @push.rocks/smartshell to run shell commands for listing and updating packages
|
||||||
|
- Wires the new 'update' command into the CLI (tools.cli) and updates CLI version to 3.0.0
|
||||||
|
- Adds CLI helper files (cli.child.js, adjusts cli.js and cli.ts.js) to run TypeScript CLI via tsrun/runPath
|
||||||
|
- Updates package.json to include new dependencies and npmextra.json with release registries and @git.zone/cli metadata
|
||||||
|
- Updates .gitignore to exclude local AI tool dirs (.claude, .serena)
|
||||||
|
|
||||||
|
## 2026-02-03 - 3.0.0 - BREAKING CHANGE(tools)
|
||||||
|
replace install functionality with a minimal placeholder CLI; remove installer, logging, path utilities, and related assets
|
||||||
|
|
||||||
|
- Removed installer implementation (ts/tools.install.ts) and package library asset (assets/package_library.json).
|
||||||
|
- Removed logging and path utilities (ts/tools.logging.ts, ts/tools.paths.ts) and simplified plugins (ts/tools.plugins.ts) to only export smartcli.
|
||||||
|
- Reworked CLI (ts/tools.cli.ts) to a placeholder standard command that prints messages instead of running installs; internal CLI version set to 2.0.22.
|
||||||
|
- Module export/behavior changed: ts/index.ts now exports runCli and no longer auto-runs; tests updated to expect runCli.
|
||||||
|
- package.json updated: description changed, several dependencies removed (e.g. @push.rocks/smartlog, @push.rocks/smartshell), @types/node bumped to ^22.0.0, and assets removed from packaged files list.
|
||||||
|
- Removed project policy and metadata files: .snyk deleted and readme.md added with usage and legal information.
|
||||||
|
|
||||||
|
## 2026-02-03 - 2.0.22 - core
|
||||||
|
Core maintenance release.
|
||||||
|
|
||||||
|
- fix(core): update — minor core fixes and maintenance improvements.
|
||||||
|
|
||||||
|
## 2026-02-03 - 2.0.23 - release tag
|
||||||
|
Release tag only — no recorded changelog details.
|
||||||
|
|
||||||
|
- 2.0.23: release tag with no additional commit message.
|
||||||
|
|
||||||
|
## 2020-10-05 - 2.0.3 - 2.0.21 - core (maintenance)
|
||||||
|
Series of maintenance releases containing repeated small core fixes.
|
||||||
|
|
||||||
|
- Multiple commits "fix(core): update" applied across 2.0.3 through 2.0.21 addressing minor bugs and stability improvements.
|
||||||
|
- These releases are maintenance-focused; no user-facing feature additions recorded.
|
||||||
|
|
||||||
|
## 2019-06-17 - 2.0.2 - core
|
||||||
|
Maintenance update to core.
|
||||||
|
|
||||||
|
- fix(core): update — continued minor fixes and upkeep.
|
||||||
|
|
||||||
|
## 2018-06-07 - 2.0.0 - 2.0.1 - policy/package fixes
|
||||||
|
Initial 2.0.x releases with policy and package fixes.
|
||||||
|
|
||||||
|
- 2.0.0: fix(snyk policy): update — update to Snyk policy.
|
||||||
|
- 2.0.1: fix(package.json): fix private property — corrected package.json property.
|
||||||
|
- 2.0.2: release tag (later maintenance continued in subsequent 2.0.x).
|
||||||
|
|
||||||
|
## 2018-06-07 - 1.0.9 - core (feature)
|
||||||
|
New core scope added.
|
||||||
|
|
||||||
|
- feat(core): new tools scope — introduces a "tools" scope in core.
|
||||||
|
|
||||||
|
## 2017-06-04 - 1.0.8 - release tag
|
||||||
|
Release tag only — no recorded changelog details.
|
||||||
|
|
||||||
|
- 1.0.8: release tag with no additional commit message.
|
||||||
|
|
||||||
|
## 2017-06-04 - 1.0.7 - cli
|
||||||
|
CLI update.
|
||||||
|
|
||||||
|
- update cli — improvements/updates to the command-line interface.
|
||||||
|
|
||||||
|
## 2017-05-28 - 1.0.6 / 1.0.5 - docs & CLI
|
||||||
|
Documentation and CLI additions.
|
||||||
|
|
||||||
|
- 1.0.6: update README — documentation updates.
|
||||||
|
- 1.0.5: add cli.js — adds CLI entry point.
|
||||||
|
|
||||||
|
## 2017-05-28 - 1.0.4 - maintenance and cleanups
|
||||||
|
Collection of maintenance, cleanup, and packaging updates for 1.0.4 over several commits.
|
||||||
|
|
||||||
|
- update / cleanup — general code cleanups.
|
||||||
|
- Update packageLibrary.json — package metadata adjusted.
|
||||||
|
- added cli.js, added .npmignore — packaging and CLI support added.
|
||||||
|
- Consolidated multiple 1.0.4 changes across 2016–2017 into this release.
|
||||||
|
|
||||||
|
## 2016-03-03 - 1.0.3 - tests
|
||||||
|
Test fix.
|
||||||
|
|
||||||
|
- fix test.ts — test suite correction.
|
||||||
|
|
||||||
|
## 2016-03-03 - 1.0.2 - CI
|
||||||
|
Continuous integration fix.
|
||||||
|
|
||||||
|
- fix Travis — adjusts CI configuration.
|
||||||
|
|
||||||
|
## 2016-03-02 - 1.0.1 - install/tests
|
||||||
|
Installer and tests improvements.
|
||||||
|
|
||||||
|
- now installing things correctly — fixes installation behavior.
|
||||||
|
- create test / update — test additions and miscellaneous updates.
|
||||||
|
|
||||||
|
## 2016-03-02 - 1.0.0 - initial release
|
||||||
|
Project initial structure and first release.
|
||||||
|
|
||||||
|
- add structure / set up initial structure / cleanup — initial project layout and housekeeping.
|
||||||
|
- initial (2016-02-29 and 2016-02-24) — first commits establishing the repository.
|
||||||
4
cli.child.ts
Normal file
4
cli.child.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
process.env.CLI_CALL = 'true';
|
||||||
|
import * as cliTool from './ts/index.js';
|
||||||
|
cliTool.runCli();
|
||||||
3
cli.js
3
cli.js
@@ -1,3 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
process.env.CLI_CALL = 'true';
|
process.env.CLI_CALL = 'true';
|
||||||
require('./dist/index');
|
const cliTool = await import('./dist_ts/index.js');
|
||||||
|
cliTool.runCli();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
process.env.CLI_CALL = 'true';
|
process.env.CLI_CALL = 'true';
|
||||||
require('@gitzone/tsrun');
|
|
||||||
require('./ts/index');
|
import * as tsrun from '@git.zone/tsrun';
|
||||||
|
tsrun.runPath('./cli.child.js', import.meta.url);
|
||||||
|
|||||||
@@ -2,20 +2,28 @@
|
|||||||
"npmts": {
|
"npmts": {
|
||||||
"cli": true
|
"cli": true
|
||||||
},
|
},
|
||||||
"npmci": {
|
"@git.zone/cli": {
|
||||||
"globalNpmTools": [
|
"projectType": "npm",
|
||||||
"npmts"
|
|
||||||
],
|
|
||||||
"npmAccessLevel": "public"
|
|
||||||
},
|
|
||||||
"gitzone": {
|
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "gitzone",
|
"gitscope": "gitzone",
|
||||||
"gitrepo": "tools",
|
"gitrepo": "tools",
|
||||||
"shortDescription": "setup your environment with the most important tools and update them easily.",
|
"shortDescription": "setup your environment with the most important tools and update them easily.",
|
||||||
"npmPackagename": "@gitzone/tools",
|
"npmPackagename": "@git.zone/tools",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"description": "manage git.zone tools"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"registries": [
|
||||||
|
"https://verdaccio.lossless.digital",
|
||||||
|
"https://registry.npmjs.org"
|
||||||
|
],
|
||||||
|
"accessLevel": "public"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"@ship.zone/szci": {
|
||||||
|
"globalNpmTools": [
|
||||||
|
"npmts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10903
package-lock.json
generated
10903
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
47
package.json
47
package.json
@@ -1,13 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "@gitzone/tools",
|
"name": "@git.zone/tools",
|
||||||
"version": "2.0.6",
|
"version": "3.5.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "setup your environment with the most important tools and update them easily.",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"description": "A CLI tool placeholder for development utilities.",
|
||||||
"typings": "dist/index.d.ts",
|
"main": "dist_ts/index.js",
|
||||||
|
"typings": "dist_ts/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tstest test/",
|
"test": "(tstest test/ --verbose)",
|
||||||
"build": "tsbuild"
|
"build": "(tsbuild --web)"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"gtools": "cli.js"
|
"gtools": "cli.js"
|
||||||
@@ -29,28 +30,28 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/GitZoneTools/npmg#readme",
|
"homepage": "https://github.com/GitZoneTools/npmg#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tstest": "^1.0.24",
|
"@git.zone/tsbuild": "^4.1.2",
|
||||||
"@pushrocks/tapbundle": "^3.0.9",
|
"@git.zone/tstest": "^3.1.8"
|
||||||
"tslint": "^5.17.0",
|
|
||||||
"tslint-config-prettier": "^1.18.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitzone/tsrun": "^1.2.6",
|
"@git.zone/tsrun": "^2.0.1",
|
||||||
"@pushrocks/smartcli": "^3.0.7",
|
"@push.rocks/smartcli": "^4.0.20",
|
||||||
"@pushrocks/smartfile": "^7.0.2",
|
"@push.rocks/smartinteract": "^2.0.16",
|
||||||
"@pushrocks/smartlog": "^2.0.19",
|
"@push.rocks/smartshell": "^3.3.0",
|
||||||
"@pushrocks/smartlog-destination-local": "^8.0.2",
|
"@types/node": "^22.0.0"
|
||||||
"@pushrocks/smartshell": "^2.0.23",
|
|
||||||
"@types/node": "^12.0.8"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/*",
|
"ts/**/*",
|
||||||
"ts_web/*",
|
"ts_web/**/*",
|
||||||
"dist/*",
|
"dist/**/*",
|
||||||
"dist_web/*",
|
"dist_*/**/*",
|
||||||
"assets/*",
|
"dist_ts/**/*",
|
||||||
|
"dist_ts_web/**/*",
|
||||||
"cli.js",
|
"cli.js",
|
||||||
"npmextra.json",
|
"npmextra.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"default":[
|
|
||||||
"@gitzone_private/gitzone",
|
|
||||||
"typescript",
|
|
||||||
"tslint",
|
|
||||||
"@gitzone/tsrun",
|
|
||||||
"@gitzone/tsdocker",
|
|
||||||
"snyk",
|
|
||||||
"npm-check"
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
8365
pnpm-lock.yaml
generated
Normal file
8365
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
readme.md
Normal file
42
readme.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# @git.zone/tools 🛠️
|
||||||
|
|
||||||
|
A CLI tool placeholder for development utilities.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## Installation 📦
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g @git.zone/tools
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage 🚀
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gtools
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently a placeholder CLI with no commands implemented yet.
|
||||||
|
|
||||||
|
## License and Legal Information
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### 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 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
|
||||||
|
|
||||||
|
Task Venture Capital GmbH
|
||||||
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||||
|
|
||||||
|
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.
|
||||||
93
test/test.node.ts
Normal file
93
test/test.node.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
|
|
||||||
|
import * as tools from '../ts/index.js';
|
||||||
|
import { PackageManagerUtil } from '../ts/mod_update/classes.packagemanager.js';
|
||||||
|
|
||||||
|
tap.test('should export runCli function', async () => {
|
||||||
|
expect(typeof tools.runCli).toEqual('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// isNewerVersion tests
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should detect newer major version', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.0', '2.0.0')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should detect newer minor version', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.0', '1.1.0')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should detect newer patch version', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.0', '1.0.1')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should return false for equal versions', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.0', '1.0.0')).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should return false when current is newer', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('2.0.0', '1.0.0')).toBeFalse();
|
||||||
|
expect(pmUtil.isNewerVersion('1.1.0', '1.0.0')).toBeFalse();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.1', '1.0.0')).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should handle v-prefixed versions', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('v1.0.0', 'v2.0.0')).toBeTrue();
|
||||||
|
expect(pmUtil.isNewerVersion('v2.0.0', 'v1.0.0')).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should handle mixed prefixed and non-prefixed', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('v1.0.0', '2.0.0')).toBeTrue();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.0', 'v2.0.0')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('isNewerVersion: should handle versions with different segment counts', async () => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0', '1.0.1')).toBeTrue();
|
||||||
|
expect(pmUtil.isNewerVersion('1.0.1', '1.0')).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// parseYarnPackageName tests
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
tap.test('parseYarnPackageName: should parse scoped package correctly', async () => {
|
||||||
|
const result = PackageManagerUtil.parseYarnPackageName('@git.zone/cli@1.2.3');
|
||||||
|
expect(result.name).toEqual('@git.zone/cli');
|
||||||
|
expect(result.version).toEqual('1.2.3');
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('parseYarnPackageName: should parse unscoped package correctly', async () => {
|
||||||
|
const result = PackageManagerUtil.parseYarnPackageName('typescript@5.3.2');
|
||||||
|
expect(result.name).toEqual('typescript');
|
||||||
|
expect(result.version).toEqual('5.3.2');
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('parseYarnPackageName: should handle empty string', async () => {
|
||||||
|
const result = PackageManagerUtil.parseYarnPackageName('');
|
||||||
|
expect(result.name).toEqual('');
|
||||||
|
expect(result.version).toEqual('unknown');
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('parseYarnPackageName: should handle name with no version', async () => {
|
||||||
|
const result = PackageManagerUtil.parseYarnPackageName('@git.zone/cli');
|
||||||
|
expect(result.name).toEqual('@git.zone/cli');
|
||||||
|
expect(result.version).toEqual('unknown');
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('parseYarnPackageName: should handle unscoped name with no version', async () => {
|
||||||
|
const result = PackageManagerUtil.parseYarnPackageName('typescript');
|
||||||
|
expect(result.name).toEqual('typescript');
|
||||||
|
expect(result.version).toEqual('unknown');
|
||||||
|
});
|
||||||
|
|
||||||
|
export default tap.start();
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { expect, tap } from '@pushrocks/tapbundle';
|
|
||||||
|
|
||||||
import * as tools from '../ts/tools.install';
|
|
||||||
|
|
||||||
tap.test("should install default list globally when parsed 'default' as argument", async () => {
|
|
||||||
await tools.install('default');
|
|
||||||
});
|
|
||||||
|
|
||||||
tap.start();
|
|
||||||
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@git.zone/tools',
|
||||||
|
version: '3.5.0',
|
||||||
|
description: 'A CLI tool placeholder for development utilities.'
|
||||||
|
}
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
import plugins = require('./tools.plugins');
|
import * as cli from './tools.cli.js';
|
||||||
import * as cli from './tools.cli';
|
|
||||||
|
export const runCli = async () => {
|
||||||
|
await cli.run();
|
||||||
|
};
|
||||||
|
|||||||
151
ts/mod_install/index.ts
Normal file
151
ts/mod_install/index.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import { PackageManagerUtil, type TPackageManager, type IPackageManagerInfo, type IInstalledPackage } from '../mod_update/classes.packagemanager.js';
|
||||||
|
import { GITZONE_PACKAGES } from '../mod_update/index.js';
|
||||||
|
|
||||||
|
export interface IInstallOptions {
|
||||||
|
yes?: boolean;
|
||||||
|
verbose?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const run = async (options: IInstallOptions = {}): Promise<void> => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
const verbose = options.verbose === true;
|
||||||
|
|
||||||
|
console.log('Scanning for missing @git.zone packages...\n');
|
||||||
|
|
||||||
|
// 1. Detect available package managers
|
||||||
|
const detectedPMs: IPackageManagerInfo[] = [];
|
||||||
|
for (const pm of ['npm', 'yarn', 'pnpm'] as TPackageManager[]) {
|
||||||
|
const info = await pmUtil.detectPackageManager(pm, verbose);
|
||||||
|
if (info.available) {
|
||||||
|
detectedPMs.push(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectedPMs.length === 0) {
|
||||||
|
console.log('No package managers found (npm, yarn, pnpm).');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
console.log(`Detected package managers: ${detectedPMs.map(p => p.name).join(', ')}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Collect all globally installed @git.zone packages across all PMs
|
||||||
|
const installedByPm = new Map<TPackageManager, IInstalledPackage[]>();
|
||||||
|
const allInstalledNames = new Set<string>();
|
||||||
|
|
||||||
|
for (const pmInfo of detectedPMs) {
|
||||||
|
const installed = await pmUtil.getInstalledPackages(pmInfo.name);
|
||||||
|
installedByPm.set(pmInfo.name, installed);
|
||||||
|
for (const pkg of installed) {
|
||||||
|
if (GITZONE_PACKAGES.includes(pkg.name)) {
|
||||||
|
allInstalledNames.add(pkg.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Determine which managed packages are not installed
|
||||||
|
const notInstalled = GITZONE_PACKAGES.filter(name => !allInstalledNames.has(name));
|
||||||
|
|
||||||
|
if (notInstalled.length === 0) {
|
||||||
|
console.log('All managed @git.zone packages are already installed.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Found ${notInstalled.length} package(s) not installed.\n`);
|
||||||
|
|
||||||
|
// 4. Determine the best default PM (the one with most @git.zone packages)
|
||||||
|
let bestPm = detectedPMs[0].name;
|
||||||
|
let bestCount = 0;
|
||||||
|
for (const pmInfo of detectedPMs) {
|
||||||
|
const pkgs = installedByPm.get(pmInfo.name) || [];
|
||||||
|
const gitzoneCount = pkgs.filter(p => GITZONE_PACKAGES.includes(p.name)).length;
|
||||||
|
if (gitzoneCount > bestCount) {
|
||||||
|
bestCount = gitzoneCount;
|
||||||
|
bestPm = pmInfo.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedPm: TPackageManager;
|
||||||
|
let selectedPackages: string[];
|
||||||
|
|
||||||
|
if (options.yes === true) {
|
||||||
|
// Non-interactive: use best PM, install all missing
|
||||||
|
selectedPm = bestPm;
|
||||||
|
selectedPackages = notInstalled;
|
||||||
|
console.log(`Using ${selectedPm} (auto-detected).\n`);
|
||||||
|
} else {
|
||||||
|
// 5. Ask which PM to use
|
||||||
|
const smartinteractInstance = new plugins.smartinteract.SmartInteract();
|
||||||
|
|
||||||
|
if (detectedPMs.length === 1) {
|
||||||
|
selectedPm = detectedPMs[0].name;
|
||||||
|
console.log(`Using ${selectedPm} (only available PM).\n`);
|
||||||
|
} else {
|
||||||
|
const pmAnswer = await smartinteractInstance.askQuestion({
|
||||||
|
name: 'packageManager',
|
||||||
|
type: 'list',
|
||||||
|
message: 'Which package manager should be used for installation?',
|
||||||
|
default: bestPm,
|
||||||
|
choices: detectedPMs.map(pm => ({
|
||||||
|
name: `${pm.name}${pm.name === bestPm ? ' (recommended — most @git.zone packages)' : ''}`,
|
||||||
|
value: pm.name,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
selectedPm = pmAnswer.value as TPackageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Ask which packages to install
|
||||||
|
// Fetch latest versions for display
|
||||||
|
const choicesWithVersions: Array<{ name: string; value: string }> = [];
|
||||||
|
for (const pkgName of notInstalled) {
|
||||||
|
const latest = await pmUtil.getLatestVersion(pkgName);
|
||||||
|
const versionLabel = latest ? `@${latest}` : '';
|
||||||
|
choicesWithVersions.push({
|
||||||
|
name: `${pkgName}${versionLabel}`,
|
||||||
|
value: pkgName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const pkgAnswer = await smartinteractInstance.askQuestion({
|
||||||
|
name: 'packages',
|
||||||
|
type: 'checkbox',
|
||||||
|
message: 'Select packages to install:',
|
||||||
|
default: notInstalled, // all pre-checked
|
||||||
|
choices: choicesWithVersions,
|
||||||
|
});
|
||||||
|
|
||||||
|
selectedPackages = pkgAnswer.value as string[];
|
||||||
|
|
||||||
|
if (selectedPackages.length === 0) {
|
||||||
|
console.log('No packages selected. Nothing to install.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Install selected packages
|
||||||
|
console.log(`Installing ${selectedPackages.length} package(s) via ${selectedPm}...\n`);
|
||||||
|
|
||||||
|
let successCount = 0;
|
||||||
|
let failCount = 0;
|
||||||
|
|
||||||
|
for (const pkgName of selectedPackages) {
|
||||||
|
const success = await pmUtil.executeUpdate(selectedPm, pkgName);
|
||||||
|
if (success) {
|
||||||
|
console.log(` ✓ ${pkgName} installed successfully`);
|
||||||
|
successCount++;
|
||||||
|
} else {
|
||||||
|
console.log(` ✗ ${pkgName} installation failed`);
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. Summary
|
||||||
|
console.log('');
|
||||||
|
if (failCount === 0) {
|
||||||
|
console.log(`All ${successCount} package(s) installed successfully!`);
|
||||||
|
} else {
|
||||||
|
console.log(`Installed ${successCount} package(s), ${failCount} failed.`);
|
||||||
|
}
|
||||||
|
};
|
||||||
4
ts/mod_install/mod.plugins.ts
Normal file
4
ts/mod_install/mod.plugins.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import * as smartinteract from '@push.rocks/smartinteract';
|
||||||
|
import * as smartshell from '@push.rocks/smartshell';
|
||||||
|
|
||||||
|
export { smartinteract, smartshell };
|
||||||
320
ts/mod_update/classes.packagemanager.ts
Normal file
320
ts/mod_update/classes.packagemanager.ts
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
|
||||||
|
export type TPackageManager = 'npm' | 'yarn' | 'pnpm';
|
||||||
|
|
||||||
|
export interface IInstalledPackage {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
packageManager: TPackageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPackageUpdateInfo {
|
||||||
|
name: string;
|
||||||
|
currentVersion: string;
|
||||||
|
latestVersion: string;
|
||||||
|
packageManager: TPackageManager;
|
||||||
|
needsUpdate: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPackageManagerInfo {
|
||||||
|
name: TPackageManager;
|
||||||
|
available: boolean;
|
||||||
|
detectionMethod?: 'which' | 'version-command';
|
||||||
|
path?: string;
|
||||||
|
currentVersion?: string;
|
||||||
|
latestVersion?: string | null;
|
||||||
|
needsUpdate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PackageManagerUtil {
|
||||||
|
private shell = new plugins.smartshell.Smartshell({
|
||||||
|
executor: 'bash',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a package manager is available on the system
|
||||||
|
* Uses multiple detection methods for robustness across different shell contexts
|
||||||
|
*/
|
||||||
|
public async isAvailable(pm: TPackageManager, verbose = false): Promise<boolean> {
|
||||||
|
const info = await this.detectPackageManager(pm, verbose);
|
||||||
|
return info.available;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect a package manager and return detailed info
|
||||||
|
*/
|
||||||
|
public async detectPackageManager(pm: TPackageManager, verbose = false): Promise<IPackageManagerInfo> {
|
||||||
|
const info: IPackageManagerInfo = { name: pm, available: false };
|
||||||
|
|
||||||
|
// Primary method: try 'which' command
|
||||||
|
try {
|
||||||
|
const whichResult = await this.shell.execSilent(`which ${pm} 2>/dev/null`);
|
||||||
|
if (whichResult.exitCode === 0 && whichResult.stdout.trim()) {
|
||||||
|
info.available = true;
|
||||||
|
info.detectionMethod = 'which';
|
||||||
|
info.path = whichResult.stdout.trim();
|
||||||
|
if (verbose) {
|
||||||
|
console.log(` Checking ${pm}... found via 'which' at ${info.path}`);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Continue to fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback method: try running pm --version directly
|
||||||
|
// This can find PMs that are available but not in PATH for 'which'
|
||||||
|
try {
|
||||||
|
const versionResult = await this.shell.execSilent(`${pm} --version 2>/dev/null`);
|
||||||
|
if (versionResult.exitCode === 0 && versionResult.stdout.trim()) {
|
||||||
|
info.available = true;
|
||||||
|
info.detectionMethod = 'version-command';
|
||||||
|
if (verbose) {
|
||||||
|
console.log(` Checking ${pm}... found via '--version' (which failed)`);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Not available
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
console.log(` Checking ${pm}... not found`);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current and latest version of a package manager
|
||||||
|
*/
|
||||||
|
public async getPackageManagerVersion(pm: TPackageManager): Promise<{ current: string; latest: string | null }> {
|
||||||
|
let current = 'unknown';
|
||||||
|
let latest: string | null = null;
|
||||||
|
|
||||||
|
// Get current version
|
||||||
|
try {
|
||||||
|
const result = await this.shell.execSilent(`${pm} --version 2>/dev/null`);
|
||||||
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
||||||
|
// Parse version from output - handle different formats
|
||||||
|
const output = result.stdout.trim();
|
||||||
|
// npm: "10.2.0", pnpm: "8.15.0", yarn: "1.22.19"
|
||||||
|
// Some may include prefix like "v1.22.19"
|
||||||
|
const versionMatch = output.match(/(\d+\.\d+\.\d+)/);
|
||||||
|
if (versionMatch) {
|
||||||
|
current = versionMatch[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Keep as unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get latest version from npm registry
|
||||||
|
try {
|
||||||
|
const result = await this.shell.execSilent(`npm view ${pm} version 2>/dev/null`);
|
||||||
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
||||||
|
latest = result.stdout.trim();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Keep as null
|
||||||
|
}
|
||||||
|
|
||||||
|
return { current, latest };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all globally installed @git.zone packages for a package manager
|
||||||
|
*/
|
||||||
|
public async getInstalledPackages(pm: TPackageManager): Promise<IInstalledPackage[]> {
|
||||||
|
const packages: IInstalledPackage[] = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
let result;
|
||||||
|
switch (pm) {
|
||||||
|
case 'npm':
|
||||||
|
result = await this.shell.execSilent('npm list -g --depth=0 --json 2>/dev/null || true');
|
||||||
|
break;
|
||||||
|
case 'yarn':
|
||||||
|
result = await this.shell.execSilent('yarn global list --depth=0 --json 2>/dev/null || true');
|
||||||
|
break;
|
||||||
|
case 'pnpm':
|
||||||
|
result = await this.shell.execSilent('pnpm list -g --depth=0 --json 2>/dev/null || true');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = result.stdout.trim();
|
||||||
|
if (!output) {
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pm === 'npm') {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(output);
|
||||||
|
const deps = data.dependencies || {};
|
||||||
|
for (const [name, info] of Object.entries(deps)) {
|
||||||
|
if (name.startsWith('@git.zone/')) {
|
||||||
|
packages.push({
|
||||||
|
name,
|
||||||
|
version: (info as any).version || 'unknown',
|
||||||
|
packageManager: pm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// JSON parse failed
|
||||||
|
}
|
||||||
|
} else if (pm === 'pnpm') {
|
||||||
|
// pnpm returns an array of objects
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(output);
|
||||||
|
// Handle array format from pnpm
|
||||||
|
const dataArray = Array.isArray(data) ? data : [data];
|
||||||
|
for (const item of dataArray) {
|
||||||
|
const deps = item.dependencies || {};
|
||||||
|
for (const [name, info] of Object.entries(deps)) {
|
||||||
|
if (name.startsWith('@git.zone/')) {
|
||||||
|
packages.push({
|
||||||
|
name,
|
||||||
|
version: (info as any).version || 'unknown',
|
||||||
|
packageManager: pm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// JSON parse failed
|
||||||
|
}
|
||||||
|
} else if (pm === 'yarn') {
|
||||||
|
// Yarn global list --json outputs multiple JSON lines
|
||||||
|
const lines = output.split('\n').filter(l => l.trim());
|
||||||
|
for (const line of lines) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(line);
|
||||||
|
if (data.type === 'tree' && data.data && data.data.trees) {
|
||||||
|
for (const tree of data.data.trees) {
|
||||||
|
const parsed = PackageManagerUtil.parseYarnPackageName(tree.name || '');
|
||||||
|
if (parsed.name.startsWith('@git.zone/')) {
|
||||||
|
packages.push({
|
||||||
|
name: parsed.name,
|
||||||
|
version: parsed.version,
|
||||||
|
packageManager: pm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Skip invalid JSON lines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Command failed, return empty array
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest version of a package from npm registry
|
||||||
|
* Tries private registry (verdaccio.lossless.digital) first via API, then falls back to public npm
|
||||||
|
*/
|
||||||
|
public async getLatestVersion(packageName: string): Promise<string | null> {
|
||||||
|
// URL-encode the package name for scoped packages (@scope/name -> @scope%2fname)
|
||||||
|
const encodedName = packageName.replace('/', '%2f');
|
||||||
|
|
||||||
|
// Try private registry first via direct API call (npm view doesn't work reliably)
|
||||||
|
try {
|
||||||
|
const result = await this.shell.execSilent(
|
||||||
|
`curl -sf "https://verdaccio.lossless.digital/${encodedName}" 2>/dev/null`
|
||||||
|
);
|
||||||
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
||||||
|
const data = JSON.parse(result.stdout.trim());
|
||||||
|
if (data['dist-tags']?.latest) {
|
||||||
|
return data['dist-tags'].latest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Continue to public registry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to public npm
|
||||||
|
try {
|
||||||
|
const result = await this.shell.execSilent(`npm view ${packageName} version 2>/dev/null`);
|
||||||
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
||||||
|
return result.stdout.trim();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Command failed
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an update for a package using the specified package manager
|
||||||
|
*/
|
||||||
|
public async executeUpdate(pm: TPackageManager, packageName: string): Promise<boolean> {
|
||||||
|
let command: string;
|
||||||
|
|
||||||
|
switch (pm) {
|
||||||
|
case 'npm':
|
||||||
|
command = `npm install -g ${packageName}@latest`;
|
||||||
|
break;
|
||||||
|
case 'yarn':
|
||||||
|
command = `yarn global add ${packageName}@latest`;
|
||||||
|
break;
|
||||||
|
case 'pnpm':
|
||||||
|
command = `pnpm add -g ${packageName}@latest`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(` Updating ${packageName} via ${pm}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await this.shell.exec(command);
|
||||||
|
return result.exitCode === 0;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a yarn package name string like "@git.zone/cli@1.0.0" into name and version.
|
||||||
|
* Handles scoped packages correctly by splitting on the last '@' (version separator).
|
||||||
|
*/
|
||||||
|
public static parseYarnPackageName(fullName: string): { name: string; version: string } {
|
||||||
|
if (!fullName) {
|
||||||
|
return { name: '', version: 'unknown' };
|
||||||
|
}
|
||||||
|
const lastAtIndex = fullName.lastIndexOf('@');
|
||||||
|
// If lastAtIndex is 0, the string is just "@something" with no version
|
||||||
|
// If lastAtIndex is -1, there's no '@' at all
|
||||||
|
if (lastAtIndex <= 0) {
|
||||||
|
return { name: fullName, version: 'unknown' };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: fullName.substring(0, lastAtIndex),
|
||||||
|
version: fullName.substring(lastAtIndex + 1) || 'unknown',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two semver versions
|
||||||
|
* Returns true if latest > current
|
||||||
|
*/
|
||||||
|
public isNewerVersion(current: string, latest: string): boolean {
|
||||||
|
const cleanVersion = (v: string) => v.replace(/^[^\d]*/, '');
|
||||||
|
const currentClean = cleanVersion(current);
|
||||||
|
const latestClean = cleanVersion(latest);
|
||||||
|
|
||||||
|
const currentParts = currentClean.split('.').map(n => parseInt(n, 10) || 0);
|
||||||
|
const latestParts = latestClean.split('.').map(n => parseInt(n, 10) || 0);
|
||||||
|
|
||||||
|
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
||||||
|
const curr = currentParts[i] || 0;
|
||||||
|
const lat = latestParts[i] || 0;
|
||||||
|
if (lat > curr) return true;
|
||||||
|
if (lat < curr) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
244
ts/mod_update/index.ts
Normal file
244
ts/mod_update/index.ts
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import { PackageManagerUtil, type TPackageManager, type IPackageUpdateInfo, type IPackageManagerInfo } from './classes.packagemanager.js';
|
||||||
|
import { commitinfo } from '../00_commitinfo_data.js';
|
||||||
|
|
||||||
|
// Curated list of known @git.zone CLI tools to track for updates.
|
||||||
|
// This list is intentionally hardcoded to only track official tools.
|
||||||
|
// Add new entries here when new @git.zone packages are published.
|
||||||
|
export const GITZONE_PACKAGES = [
|
||||||
|
'@git.zone/cli',
|
||||||
|
'@git.zone/tsdoc',
|
||||||
|
'@git.zone/tsbuild',
|
||||||
|
'@git.zone/tstest',
|
||||||
|
'@git.zone/tspublish',
|
||||||
|
'@git.zone/tsbundle',
|
||||||
|
'@git.zone/tsdocker',
|
||||||
|
'@git.zone/tsview',
|
||||||
|
'@git.zone/tswatch',
|
||||||
|
'@git.zone/tsrust',
|
||||||
|
];
|
||||||
|
|
||||||
|
export interface IUpdateOptions {
|
||||||
|
yes?: boolean;
|
||||||
|
verbose?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const run = async (options: IUpdateOptions = {}): Promise<void> => {
|
||||||
|
const pmUtil = new PackageManagerUtil();
|
||||||
|
const verbose = options.verbose === true;
|
||||||
|
|
||||||
|
console.log('Scanning for installed @git.zone packages...\n');
|
||||||
|
|
||||||
|
// Check which package managers are available
|
||||||
|
if (verbose) {
|
||||||
|
console.log('Detecting package managers:');
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectedPMs: IPackageManagerInfo[] = [];
|
||||||
|
for (const pm of ['npm', 'yarn', 'pnpm'] as TPackageManager[]) {
|
||||||
|
const info = await pmUtil.detectPackageManager(pm, verbose);
|
||||||
|
if (info.available) {
|
||||||
|
detectedPMs.push(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectedPMs.length === 0) {
|
||||||
|
console.log('No package managers found (npm, yarn, pnpm).');
|
||||||
|
console.log('Tried detection via \'which\' command and direct version check.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get version info for each PM and display status table
|
||||||
|
console.log('Package managers:\n');
|
||||||
|
console.log(' Name Current Latest Status');
|
||||||
|
console.log(' ──────────────────────────────────────────────');
|
||||||
|
|
||||||
|
for (const pmInfo of detectedPMs) {
|
||||||
|
const versionInfo = await pmUtil.getPackageManagerVersion(pmInfo.name);
|
||||||
|
pmInfo.currentVersion = versionInfo.current;
|
||||||
|
pmInfo.latestVersion = versionInfo.latest;
|
||||||
|
pmInfo.needsUpdate = versionInfo.latest
|
||||||
|
? pmUtil.isNewerVersion(versionInfo.current, versionInfo.latest)
|
||||||
|
: false;
|
||||||
|
|
||||||
|
const name = pmInfo.name.padEnd(9);
|
||||||
|
const current = versionInfo.current.padEnd(12);
|
||||||
|
const latest = (versionInfo.latest || 'unknown').padEnd(12);
|
||||||
|
const status = versionInfo.latest === null
|
||||||
|
? '? Version unknown'
|
||||||
|
: pmInfo.needsUpdate
|
||||||
|
? '⬆️ Update available'
|
||||||
|
: '✓ Up to date';
|
||||||
|
console.log(` ${name}${current}${latest}${status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// === Self-update check ===
|
||||||
|
console.log('Checking for gtools self-update...\n');
|
||||||
|
const selfVersion = commitinfo.version;
|
||||||
|
const selfLatest = await pmUtil.getLatestVersion('@git.zone/tools');
|
||||||
|
|
||||||
|
if (selfLatest && pmUtil.isNewerVersion(selfVersion, selfLatest)) {
|
||||||
|
console.log(` @git.zone/tools ${selfVersion} → ${selfLatest} ⬆️ Update available\n`);
|
||||||
|
|
||||||
|
// Find which PM has it installed globally
|
||||||
|
let selfPm: TPackageManager | null = null;
|
||||||
|
for (const pmInfo of detectedPMs) {
|
||||||
|
const installed = await pmUtil.getInstalledPackages(pmInfo.name);
|
||||||
|
if (installed.some(p => p.name === '@git.zone/tools')) {
|
||||||
|
selfPm = pmInfo.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selfPm) {
|
||||||
|
// Fallback: use first available PM
|
||||||
|
selfPm = detectedPMs[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldSelfUpdate = options.yes === true;
|
||||||
|
if (!shouldSelfUpdate) {
|
||||||
|
const smartinteractInstance = new plugins.smartinteract.SmartInteract();
|
||||||
|
const answer = await smartinteractInstance.askQuestion({
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'confirmSelfUpdate',
|
||||||
|
message: 'Do you want to update gtools itself first?',
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
shouldSelfUpdate = answer.value === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSelfUpdate) {
|
||||||
|
const success = await pmUtil.executeUpdate(selfPm, '@git.zone/tools');
|
||||||
|
if (success) {
|
||||||
|
console.log('\ngtools has been updated. Please re-run "gtools update" to check remaining packages.');
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log('\ngtools self-update failed. Continuing with current version...\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(` @git.zone/tools ${selfVersion} ✓ Up to date\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all installed @git.zone packages from all package managers
|
||||||
|
const allPackages: IPackageUpdateInfo[] = [];
|
||||||
|
|
||||||
|
for (const pmInfo of detectedPMs) {
|
||||||
|
const installed = await pmUtil.getInstalledPackages(pmInfo.name);
|
||||||
|
for (const pkg of installed) {
|
||||||
|
// Only include packages from our predefined list
|
||||||
|
if (GITZONE_PACKAGES.includes(pkg.name)) {
|
||||||
|
const latestVersion = await pmUtil.getLatestVersion(pkg.name);
|
||||||
|
allPackages.push({
|
||||||
|
name: pkg.name,
|
||||||
|
currentVersion: pkg.version,
|
||||||
|
latestVersion: latestVersion || 'unknown',
|
||||||
|
packageManager: pmInfo.name,
|
||||||
|
needsUpdate: latestVersion ? pmUtil.isNewerVersion(pkg.version, latestVersion) : false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPackages.length === 0) {
|
||||||
|
console.log('No @git.zone packages found installed globally.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display package table
|
||||||
|
console.log('Installed @git.zone packages:\n');
|
||||||
|
console.log(' Package Current Latest PM Status');
|
||||||
|
console.log(' ─────────────────────────────────────────────────────────────────────');
|
||||||
|
|
||||||
|
for (const pkg of allPackages) {
|
||||||
|
const name = pkg.name.padEnd(28);
|
||||||
|
const current = pkg.currentVersion.padEnd(12);
|
||||||
|
const latest = pkg.latestVersion.padEnd(12);
|
||||||
|
const pm = pkg.packageManager.padEnd(8);
|
||||||
|
const status = pkg.latestVersion === 'unknown'
|
||||||
|
? '? Version unknown'
|
||||||
|
: pkg.needsUpdate
|
||||||
|
? '⬆️ Update available'
|
||||||
|
: '✓ Up to date';
|
||||||
|
console.log(` ${name}${current}${latest}${pm}${status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// Show managed packages that are not installed anywhere
|
||||||
|
const installedNames = new Set(allPackages.map(p => p.name));
|
||||||
|
const notInstalled = GITZONE_PACKAGES.filter(name => !installedNames.has(name));
|
||||||
|
|
||||||
|
if (notInstalled.length > 0) {
|
||||||
|
console.log('Not installed (managed @git.zone packages):\n');
|
||||||
|
console.log(' Package Latest');
|
||||||
|
console.log(' ─────────────────────────────────────────');
|
||||||
|
for (const pkgName of notInstalled) {
|
||||||
|
const latest = await pmUtil.getLatestVersion(pkgName);
|
||||||
|
const name = pkgName.padEnd(28);
|
||||||
|
const version = latest || 'unknown';
|
||||||
|
console.log(` ${name} ${version}`);
|
||||||
|
}
|
||||||
|
console.log('');
|
||||||
|
console.log(' Run "gtools install" to install missing packages.\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter packages that need updates
|
||||||
|
const packagesToUpdate = allPackages.filter(p => p.needsUpdate);
|
||||||
|
|
||||||
|
if (packagesToUpdate.length === 0) {
|
||||||
|
console.log('All packages are up to date!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Found ${packagesToUpdate.length} package(s) with available updates.\n`);
|
||||||
|
|
||||||
|
// Ask for confirmation unless -y flag is provided
|
||||||
|
let shouldUpdate = options.yes === true;
|
||||||
|
|
||||||
|
if (!shouldUpdate) {
|
||||||
|
const smartinteractInstance = new plugins.smartinteract.SmartInteract();
|
||||||
|
const answer = await smartinteractInstance.askQuestion({
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'confirmUpdate',
|
||||||
|
message: 'Do you want to update these packages?',
|
||||||
|
default: true,
|
||||||
|
});
|
||||||
|
shouldUpdate = answer.value === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldUpdate) {
|
||||||
|
console.log('Update cancelled.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute updates
|
||||||
|
console.log('\nUpdating packages...\n');
|
||||||
|
|
||||||
|
let successCount = 0;
|
||||||
|
let failCount = 0;
|
||||||
|
|
||||||
|
for (const pkg of packagesToUpdate) {
|
||||||
|
const success = await pmUtil.executeUpdate(pkg.packageManager, pkg.name);
|
||||||
|
if (success) {
|
||||||
|
console.log(` ✓ ${pkg.name} updated successfully`);
|
||||||
|
successCount++;
|
||||||
|
} else {
|
||||||
|
console.log(` ✗ ${pkg.name} update failed`);
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
if (failCount === 0) {
|
||||||
|
console.log(`All ${successCount} package(s) updated successfully!`);
|
||||||
|
} else {
|
||||||
|
console.log(`Updated ${successCount} package(s), ${failCount} failed.`);
|
||||||
|
}
|
||||||
|
};
|
||||||
4
ts/mod_update/mod.plugins.ts
Normal file
4
ts/mod_update/mod.plugins.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import * as smartinteract from '@push.rocks/smartinteract';
|
||||||
|
import * as smartshell from '@push.rocks/smartshell';
|
||||||
|
|
||||||
|
export { smartinteract, smartshell };
|
||||||
@@ -1,11 +1,36 @@
|
|||||||
import * as plugins from './tools.plugins';
|
import * as plugins from './tools.plugins.js';
|
||||||
import * as toolsInstall from './tools.install';
|
import * as modUpdate from './mod_update/index.js';
|
||||||
|
import * as modInstall from './mod_install/index.js';
|
||||||
|
import { commitinfo } from './00_commitinfo_data.js';
|
||||||
|
|
||||||
const toolsCli = new plugins.smartcli.Smartcli();
|
export const run = async () => {
|
||||||
|
const toolsCli = new plugins.smartcli.Smartcli();
|
||||||
|
|
||||||
toolsCli.addCommand('install').subscribe(async argvArg => {
|
toolsCli.standardCommand().subscribe(async (argvArg) => {
|
||||||
toolsInstall.install('default');
|
console.log('@git.zone/tools - CLI utility for managing @git.zone packages\n');
|
||||||
});
|
console.log('Commands:');
|
||||||
|
console.log(' update Check and update globally installed @git.zone packages');
|
||||||
|
console.log(' update -y Update without confirmation prompt');
|
||||||
|
console.log(' update --verbose Show detection diagnostics');
|
||||||
|
console.log(' install Interactively install missing @git.zone packages');
|
||||||
|
console.log(' install -y Install all missing packages without prompts');
|
||||||
|
console.log(' install --verbose Show detection diagnostics');
|
||||||
|
console.log('');
|
||||||
|
console.log('Use "gtools <command> --help" for more information about a command.');
|
||||||
|
});
|
||||||
|
|
||||||
toolsCli.addVersion('no version set');
|
toolsCli.addCommand('update').subscribe(async (argvArg) => {
|
||||||
toolsCli.startParse();
|
const yesFlag = argvArg.y === true || argvArg.yes === true;
|
||||||
|
const verboseFlag = argvArg.v === true || argvArg.verbose === true;
|
||||||
|
await modUpdate.run({ yes: yesFlag, verbose: verboseFlag });
|
||||||
|
});
|
||||||
|
|
||||||
|
toolsCli.addCommand('install').subscribe(async (argvArg) => {
|
||||||
|
const yesFlag = argvArg.y === true || argvArg.yes === true;
|
||||||
|
const verboseFlag = argvArg.v === true || argvArg.verbose === true;
|
||||||
|
await modInstall.run({ yes: yesFlag, verbose: verboseFlag });
|
||||||
|
});
|
||||||
|
|
||||||
|
toolsCli.addVersion(commitinfo.version);
|
||||||
|
toolsCli.startParse();
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import plugins = require('./tools.plugins');
|
|
||||||
import paths = require('./tools.paths');
|
|
||||||
import { logger } from './tools.logging';
|
|
||||||
|
|
||||||
const installExec = async (packageNames: string[]) => {
|
|
||||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
||||||
executor: 'bash'
|
|
||||||
});
|
|
||||||
|
|
||||||
let installString = '';
|
|
||||||
for (const packageName of packageNames) {
|
|
||||||
logger.log('info', `Found ${packageName}!`);
|
|
||||||
installString = installString + `${packageName} `;
|
|
||||||
}
|
|
||||||
// lets remove old packages
|
|
||||||
const uninstallCommand = `npm uninstall -g ${installString}`;
|
|
||||||
const installCommand = `npm install -g ${installString}`;
|
|
||||||
logger.log('info', `uninstalling old packages with "${uninstallCommand}"`);
|
|
||||||
await smartshellInstance.exec(uninstallCommand);
|
|
||||||
logger.log('info', `installing tools with ${installCommand}`);
|
|
||||||
await smartshellInstance.exec(installCommand);
|
|
||||||
logger.log('ok', `installed tools successfully!`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const packageLibrary = plugins.smartfile.fs.toObjectSync(
|
|
||||||
plugins.path.join(paths.packageBase, 'package_library.json')
|
|
||||||
);
|
|
||||||
|
|
||||||
export const install = async (packageSetArg: string) => {
|
|
||||||
switch (packageSetArg) {
|
|
||||||
case 'default':
|
|
||||||
await installExec(packageLibrary.default);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logger.log('warn', 'no set has been specified');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import * as plugins from './tools.plugins';
|
|
||||||
|
|
||||||
export const logger = new plugins.smartlog.Smartlog({
|
|
||||||
logContext: {
|
|
||||||
company: 'Some Company',
|
|
||||||
companyunit: 'Some CompanyUnit',
|
|
||||||
containerName: 'Some Containername',
|
|
||||||
environment: 'local',
|
|
||||||
runtime: 'node',
|
|
||||||
zone: 'gitzone'
|
|
||||||
},
|
|
||||||
minimumLogLevel: 'silly'
|
|
||||||
});
|
|
||||||
|
|
||||||
logger.addLogDestination(new plugins.smartlogDestinationLocal.DestinationLocal());
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import plugins = require('./tools.plugins');
|
|
||||||
|
|
||||||
export let packageBase = plugins.path.join('__dirname', '../');
|
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
// node native
|
// push.rocks scope
|
||||||
import * as path from 'path';
|
import * as smartcli from '@push.rocks/smartcli';
|
||||||
|
import * as smartinteract from '@push.rocks/smartinteract';
|
||||||
|
import * as smartshell from '@push.rocks/smartshell';
|
||||||
|
|
||||||
// pushrocks scope
|
export { smartcli, smartinteract, smartshell };
|
||||||
import * as smartlog from '@pushrocks/smartlog';
|
|
||||||
import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local';
|
|
||||||
import * as smartcli from '@pushrocks/smartcli';
|
|
||||||
import * as smartfile from '@pushrocks/smartfile';
|
|
||||||
import * as smartshell from '@pushrocks/smartshell';
|
|
||||||
|
|
||||||
export { smartlog, smartlogDestinationLocal, path, smartcli, smartfile, smartshell };
|
|
||||||
|
|||||||
17
tslint.json
17
tslint.json
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
|
||||||
"rules": {
|
|
||||||
"semicolon": [true, "always"],
|
|
||||||
"no-console": false,
|
|
||||||
"ordered-imports": false,
|
|
||||||
"object-literal-sort-keys": false,
|
|
||||||
"member-ordering": {
|
|
||||||
"options":{
|
|
||||||
"order": [
|
|
||||||
"static-method"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultSeverity": "warning"
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user