Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
d32d47b706 | |||
fd90cfe895 | |||
c48f48fc8b | |||
e21e7f0850 | |||
5f561527f9 | |||
9f5f568c3f | |||
39a31a4304 | |||
b629a7d70b | |||
4003944139 | |||
83d374dffd | |||
49a5a66440 |
@@ -2,4 +2,3 @@ runafter:
|
||||
- git add -A && git commit -m initial
|
||||
- git push origin master
|
||||
- gitzone meta update
|
||||
|
44
changelog.md
44
changelog.md
@@ -1,5 +1,49 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-08-08 - 1.16.7 - fix(core)
|
||||
Improve formatting, logging, and rollback integrity in core modules
|
||||
|
||||
- Add .claude/settings.local.json with defined permissions for allowed commands
|
||||
- Standardize formatting in package.json, commit info, and configuration files
|
||||
- Refactor rollback manager to use atomic manifest writes and validate manifest structure
|
||||
- Enhance logging messages and overall code clarity in CLI and commit modules
|
||||
|
||||
## 2025-08-08 - 1.16.6 - fix(changecache)
|
||||
Improve cache manifest validation and atomic file writes; add local settings and overrides
|
||||
|
||||
- Add manifest structure validation and default fallback in getManifest
|
||||
- Implement atomic write in saveManifest using a temporary file and rename strategy
|
||||
- Enhance error handling and cleanup for corrupted manifest files
|
||||
- Introduce new .claude/settings.local.json for project-specific permission configuration
|
||||
- Add an empty assets/overrides.json file for future overrides
|
||||
|
||||
## 2025-08-08 - 1.16.5 - fix(prettier)
|
||||
Improve file selection in Prettier formatter, remove legacy package overrides, and update CI template indentation
|
||||
|
||||
- Added .claude/settings.local.json with updated permission settings for local commands
|
||||
- Removed unnecessary overrides from assets/overrides.json and cleared packageManager overrides in package.json
|
||||
- Adjusted CI template files (ci_default_gitlab, ci_default_private_gitlab, ci_docker_gitlab) for consistent indentation and formatting
|
||||
- Refined Prettier formatter logic by defining include directories, root config files, and filtering duplicates instead of manual exclusion
|
||||
|
||||
## 2025-08-08 - 1.16.4 - fix(prettier)
|
||||
Improve file exclusion in the Prettier formatter to skip unnecessary files and directories.
|
||||
|
||||
- Added exclusion patterns for node_modules, .git, dist, .nogit, coverage, .nyc_output, vendor, bower_components, jspm_packages, and minified files.
|
||||
- Optimized filtering logic to ensure only valid files are processed.
|
||||
|
||||
## 2025-08-08 - 1.16.3 - fix(changecache/prettier)
|
||||
Skip directories during file processing to prevent errors in changecache and prettier formatting
|
||||
|
||||
- Removed unnecessary await on synchronous file reads in changecache
|
||||
- Added directory checks in changecache to immediately skip directories
|
||||
- Filtered out directories in prettier formatter to avoid processing non-files
|
||||
|
||||
## 2025-08-07 - 1.16.2 - fix(format)
|
||||
Fix format command confirmation prompt to correctly check user response
|
||||
|
||||
- Fixed bug where format command always showed "cancelled" even when user confirmed
|
||||
- Changed response check from `response.proceed` to `response.value` for SmartInteract compatibility
|
||||
|
||||
## 2025-08-04 - 1.16.1 - fix(package/config)
|
||||
Move smartdiff dependency to runtime and add local bash permissions settings
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@git.zone/cli",
|
||||
"private": false,
|
||||
"version": "1.16.1",
|
||||
"version": "1.16.7",
|
||||
"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",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
@@ -113,9 +113,7 @@
|
||||
"last 1 chrome versions"
|
||||
],
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"peek-readable": "5.3.1"
|
||||
}
|
||||
"overrides": {}
|
||||
},
|
||||
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
|
||||
}
|
||||
|
419
readme.md
419
readme.md
@@ -1,155 +1,390 @@
|
||||
# @git.zone/cli
|
||||
# @git.zone/cli 🚀
|
||||
|
||||
A CLI toolbelt to streamline local development cycles by utilizing various gitzone utilities.
|
||||
**The ultimate CLI toolbelt for modern TypeScript development workflows**
|
||||
|
||||
## Install
|
||||
[](https://www.npmjs.com/package/@git.zone/cli)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
To begin using `@git.zone/cli`, ensure that Node.js and npm are installed on your system. Once they are set up, install the CLI tool globally with the following command:
|
||||
## 🎯 What is gitzone?
|
||||
|
||||
```shell
|
||||
gitzone is a powerful command-line interface that supercharges your development workflow with automated project management, intelligent code formatting, and seamless version control. Whether you're bootstrapping a new TypeScript project, maintaining code quality, or managing complex multi-repository setups, gitzone has got you covered.
|
||||
|
||||
## 🏃♂️ Quick Start
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Install globally via npm
|
||||
npm install -g @git.zone/cli
|
||||
|
||||
# Or with pnpm (recommended)
|
||||
pnpm add -g @git.zone/cli
|
||||
```
|
||||
|
||||
This command makes `gitzone` or `gzone` accessible from any directory on your system.
|
||||
Once installed, you can use either `gitzone` or the shorter `gzone` command from anywhere in your terminal.
|
||||
|
||||
## Usage
|
||||
### Your First Command
|
||||
|
||||
The `gitzone` CLI provides a comprehensive set of utilities to optimize and manage the development lifecycle of projects, ranging from project initialization to version control, code formatting, and deployment processes. This usage guide will walk you through the available commands, their use cases, and provide detailed examples.
|
||||
```bash
|
||||
# Create a new TypeScript npm package
|
||||
gitzone template npm
|
||||
|
||||
### Initializing a New Project
|
||||
# Format your entire codebase
|
||||
gitzone format
|
||||
|
||||
To bootstrap a new project aligned with modern TypeScript practices, use gitzone's template command. Choose from a range of templates tailored for different project types:
|
||||
|
||||
```shell
|
||||
gitzone template [templatename]
|
||||
```
|
||||
|
||||
Replace `[templatename]` with any of the following:
|
||||
- `npm`: Starts an npm module with TypeScript, complete with test and CI/CD integration.
|
||||
- `website`: Initializes a LitElement-based frontend application with features such as e2e testing and service worker setup.
|
||||
- `element`: Prepares a new standard setup for creating reusable web components with LitElement.
|
||||
|
||||
**Example: Starting a New npm Project**
|
||||
1. Navigate to your desired directory in the terminal.
|
||||
2. Execute:
|
||||
```shell
|
||||
gitzone template npm
|
||||
```
|
||||
3. Respond to the prompts to customize the project settings. This includes setting up essential metadata such as name and repository information.
|
||||
|
||||
### Committing Changes
|
||||
|
||||
Standardizing commit messages and versionning with gitzone:
|
||||
|
||||
```shell
|
||||
# Create a semantic commit
|
||||
gitzone commit
|
||||
```
|
||||
|
||||
This command provides an interactive prompt to create a conventional commit message, which will be automatically versioned based on the significance of the changes like `fix`, `feat`, or `BREAKING CHANGE`.
|
||||
## 🛠️ Core Features
|
||||
|
||||
### Handling Package Deprecation
|
||||
### 📦 Project Templates
|
||||
|
||||
Replace an outdated package with a new one for your team and users:
|
||||
Instantly scaffold production-ready projects with best practices built-in:
|
||||
|
||||
```shell
|
||||
gitzone deprecate
|
||||
```bash
|
||||
gitzone template [template-name]
|
||||
```
|
||||
|
||||
The utility collects information about old and new package names through interactive prompts, and proceeds with deprecation notices in npm, guiding users towards the updated package.
|
||||
**Available templates:**
|
||||
- **`npm`** - TypeScript npm package with testing, CI/CD, and full tooling
|
||||
- **`service`** - Microservice architecture with Docker support
|
||||
- **`website`** - Modern web application with LitElement and service workers
|
||||
- **`wcc`** - Web Component Collection for reusable UI components
|
||||
|
||||
### CI/CD Utilities
|
||||
Each template comes pre-configured with:
|
||||
- ✅ TypeScript with modern configurations
|
||||
- ✅ Automated testing setup
|
||||
- ✅ CI/CD pipelines (GitLab/GitHub)
|
||||
- ✅ Code formatting and linting
|
||||
- ✅ Documentation structure
|
||||
|
||||
Access your project’s CI/CD settings instantly:
|
||||
### 🎨 Intelligent Code Formatting
|
||||
|
||||
```shell
|
||||
gitzone open ci
|
||||
The most powerful feature of gitzone - automatically format and standardize your entire codebase:
|
||||
|
||||
```bash
|
||||
# Preview changes without applying them
|
||||
gitzone format --dry-run
|
||||
|
||||
# Format with automatic approval
|
||||
gitzone format --yes
|
||||
|
||||
# Save formatting plan for later execution
|
||||
gitzone format --save-plan format-plan.json
|
||||
|
||||
# Execute a saved plan
|
||||
gitzone format --from-plan format-plan.json
|
||||
|
||||
# Enable verbose output for debugging
|
||||
gitzone format --verbose
|
||||
```
|
||||
|
||||
This command opens the settings page of the repository’s CI/CD configuration directly from your CLI, thus swiftly transitioning from local tasks to cloud configurations.
|
||||
**Format features:**
|
||||
- 🔄 **Smart caching** - Only processes changed files
|
||||
- 🛡️ **Rollback support** - Undo formatting changes if needed
|
||||
- 📊 **Detailed reporting** - See exactly what changed
|
||||
- ⚡ **Parallel execution** - Format multiple files simultaneously
|
||||
- 🎯 **Module-specific formatting** - Target specific formatters
|
||||
|
||||
### Maintaining Project Cleanliness
|
||||
**Rollback capabilities:**
|
||||
```bash
|
||||
# List all available backups
|
||||
gitzone format --list-backups
|
||||
|
||||
For consistent code formatting across your project:
|
||||
# Rollback to the last operation
|
||||
gitzone format --rollback
|
||||
|
||||
```shell
|
||||
gitzone format
|
||||
# Rollback to a specific operation
|
||||
gitzone format --rollback [operation-id]
|
||||
|
||||
# Clean old backups
|
||||
gitzone format --clean-backups
|
||||
```
|
||||
|
||||
This command applies uniform formatting styles using Prettier, ensuring your JS/TS and markdown files align with the project's style guide.
|
||||
**Formatters included:**
|
||||
- **Prettier** - JavaScript/TypeScript code formatting
|
||||
- **License** - Ensure proper licensing
|
||||
- **Package.json** - Standardize package configurations
|
||||
- **Tsconfig** - TypeScript configuration optimization
|
||||
- **Readme** - Documentation formatting
|
||||
- **Gitignore** - Repository ignore rules
|
||||
- **Templates** - Project template updates
|
||||
- **Npmextra** - Extended npm configurations
|
||||
|
||||
### Lifecycle Management Commands
|
||||
### 🔀 Semantic Commits & Versioning
|
||||
|
||||
#### Clean Builds
|
||||
Create standardized commits that automatically handle versioning:
|
||||
|
||||
Remove generated files and prepare for a fresh build:
|
||||
|
||||
```shell
|
||||
gitzone clean
|
||||
```bash
|
||||
gitzone commit
|
||||
```
|
||||
|
||||
This utility cleans up build artifacts from your project directory so that you can run a fresh build without residual clutter affecting outcomes.
|
||||
Features:
|
||||
- 📝 Interactive commit message builder
|
||||
- 🏷️ Automatic version bumping (major/minor/patch)
|
||||
- 📜 Changelog generation
|
||||
- 🚀 Optional auto-push to origin
|
||||
- 🎯 Conventional commit compliance
|
||||
|
||||
#### Sync and meta Configuration
|
||||
The commit wizard guides you through:
|
||||
1. **Type selection** (feat/fix/docs/style/refactor/perf/test/chore)
|
||||
2. **Scope definition** (component/module affected)
|
||||
3. **Description crafting**
|
||||
4. **Breaking change detection**
|
||||
5. **Version bump determination**
|
||||
|
||||
To manage metadata that guides your project configurations and module syncing:
|
||||
### 🏗️ Meta Repository Management
|
||||
|
||||
```shell
|
||||
Manage multiple related repositories as a cohesive unit:
|
||||
|
||||
```bash
|
||||
# Initialize a meta repository
|
||||
gitzone meta init
|
||||
|
||||
# Add a sub-project
|
||||
gitzone meta add [name] [git-url]
|
||||
|
||||
# Update all sub-projects
|
||||
gitzone meta update
|
||||
|
||||
# Remove a sub-project
|
||||
gitzone meta remove [name]
|
||||
```
|
||||
|
||||
This initialization sets the groundwork for supporting gitzone projects by helping you create a `.meta.json` file that tracks subprojects.
|
||||
Perfect for:
|
||||
- Monorepo management
|
||||
- Multi-package projects
|
||||
- Coordinated deployments
|
||||
- Synchronized versioning
|
||||
|
||||
### Advanced Operations
|
||||
### 🐳 Docker Management
|
||||
|
||||
#### Cloud and Docker Integrations
|
||||
Streamline your Docker workflow:
|
||||
|
||||
For projects integrating cloud deployment or containerization:
|
||||
|
||||
```shell
|
||||
```bash
|
||||
# Clean up all Docker resources
|
||||
gitzone docker prune
|
||||
```
|
||||
|
||||
This utility manages Docker resources by cleaning stale volumes, containers, and images, ensuring efficient resource use.
|
||||
This command removes:
|
||||
- Stopped containers
|
||||
- Unused images
|
||||
- Dangling volumes
|
||||
- Unused networks
|
||||
|
||||
### Detailed Use Cases
|
||||
### 🔗 Quick CI/CD Access
|
||||
|
||||
#### **Project Setup and Template Management**
|
||||
Jump directly to your CI/CD configurations:
|
||||
|
||||
Whether creating an npm module or a web component, the command `gitzone template [templatename]` invokes smart scaffolding processes that automatically set up a robust project environment equipped with modern tooling like TypeScript, Prettier configurations, and testing frameworks.
|
||||
```bash
|
||||
# Open CI/CD settings
|
||||
gitzone open ci
|
||||
|
||||
#### **Commit Management**
|
||||
|
||||
The `gitzone commit` command assures that your commit messages complement semantic versioning practices. It proposes version bumps based on detected changes and helps maintain an accurate project change log.
|
||||
|
||||
- **Interactive Commit:** Users engage in dialogues to define commit type (`fix`, `feat`, `BREAKING CHANGE`), scope, and description, resulting in uniform and meaningful commit logs.
|
||||
- **Automatic Versioning:** After message crafting, the versioning is attended by bumps similar to npm’s `npm version` with stages such as `major`, `minor`, and `patch`.
|
||||
|
||||
#### **Formatting and Configurations**
|
||||
|
||||
A consistent format yields a professional and readable codebase:
|
||||
```shell
|
||||
gitzone format
|
||||
# Open pipelines view
|
||||
gitzone open pipelines
|
||||
```
|
||||
|
||||
- **Prettier Integration:** Formats not only TypeScript and JavaScript files but also documents such as `readme.md`, maintaining consistency in both code and documentation style.
|
||||
Works with GitLab repositories to provide instant access to your deployment configurations.
|
||||
|
||||
#### **Synced Meta Projects**
|
||||
### 📝 Package Deprecation
|
||||
|
||||
Effectively supervise interconnected repositories or module collections:
|
||||
- **Meta Initialization (`meta init`)**: Lay down a foundation for a meta repository that orchestrates multiple projects by overseeing them through a centralized metadata file.
|
||||
- **Subproject Operations:** Commands such as `meta update`, `meta add`, `meta remove` enable dynamic management of subprojects, ensuring they remain updated with current features and aligned to the meta repository's standards.
|
||||
Smoothly transition users from old to new packages:
|
||||
|
||||
#### **CI/CD Integration**
|
||||
```bash
|
||||
gitzone deprecate
|
||||
```
|
||||
|
||||
Directly linking your local development processes to continuous integration settings with `gitzone open ci` provides seamless switches between code and configuration in cloud-based environments.
|
||||
Interactive wizard for:
|
||||
- Setting deprecation notices
|
||||
- Guiding users to replacements
|
||||
- Updating registry metadata
|
||||
- Coordinating migration paths
|
||||
|
||||
#### **Real-time Docker Management**
|
||||
### 🚦 Project Initialization
|
||||
|
||||
For developers employing Docker for service deployments, `gitzone docker prune` offers a quick remedy to residual services, optimizing local/docker-storage for a more streamlined experience in container management.
|
||||
Prepare existing projects for development:
|
||||
|
||||
### Leveraging gitzone
|
||||
```bash
|
||||
gitzone start
|
||||
```
|
||||
|
||||
By mastering the `gitzone` CLI commands, you gain unparalleled efficiency in managing your projects from conception to deployment. Encompassing a wide gamut of functionalities, from initial project scaffolding to synchronization of modularized repositories and beyond, `gitzone` serves as a linchpin for developers intent on optimizing their workflow. Understanding and utilizing its full potential catalyzes development cycles, granting the freedom to focus on innovation, collaboration, and delivering outstanding software products.
|
||||
Automatically:
|
||||
- Checks out master branch
|
||||
- Pulls latest changes
|
||||
- Installs dependencies
|
||||
- Sets up development environment
|
||||
|
||||
### 🔧 Helper Utilities
|
||||
|
||||
Quick utilities for common tasks:
|
||||
|
||||
```bash
|
||||
# Generate a unique short ID
|
||||
gitzone helpers shortid
|
||||
```
|
||||
|
||||
## 📋 Configuration
|
||||
|
||||
### npmextra.json Configuration
|
||||
|
||||
Customize gitzone behavior through `npmextra.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"gitzone": {
|
||||
"format": {
|
||||
"interactive": true,
|
||||
"showDiffs": false,
|
||||
"autoApprove": false,
|
||||
"parallel": true,
|
||||
"rollback": {
|
||||
"enabled": true,
|
||||
"autoRollbackOnError": true,
|
||||
"backupRetentionDays": 7
|
||||
},
|
||||
"modules": {
|
||||
"skip": ["prettier"],
|
||||
"only": [],
|
||||
"order": []
|
||||
},
|
||||
"cache": {
|
||||
"enabled": true,
|
||||
"clean": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `CI` - Detect CI environment for automated workflows
|
||||
- `DEBUG` - Enable debug output
|
||||
- `GITZONE_FORMAT_PARALLEL` - Control parallel formatting
|
||||
|
||||
## 🏆 Best Practices
|
||||
|
||||
### For New Projects
|
||||
1. Start with a template: `gitzone template npm`
|
||||
2. Customize the generated structure
|
||||
3. Run initial format: `gitzone format`
|
||||
4. Set up CI/CD: `gitzone open ci`
|
||||
|
||||
### For Existing Projects
|
||||
1. Initialize: `gitzone start`
|
||||
2. Format codebase: `gitzone format --dry-run` (preview first!)
|
||||
3. Apply formatting: `gitzone format --yes`
|
||||
4. Commit changes: `gitzone commit`
|
||||
|
||||
### For Teams
|
||||
1. Document format preferences in `npmextra.json`
|
||||
2. Use `--save-plan` for reviewable format changes
|
||||
3. Enable rollback for safety
|
||||
4. Standardize commit conventions
|
||||
|
||||
## 🎯 Common Workflows
|
||||
|
||||
### Clean Development Cycle
|
||||
```bash
|
||||
# 1. Start fresh
|
||||
gitzone start
|
||||
|
||||
# 2. Make changes
|
||||
# ... your development work ...
|
||||
|
||||
# 3. Format code
|
||||
gitzone format
|
||||
|
||||
# 4. Commit with semantic versioning
|
||||
gitzone commit
|
||||
|
||||
# 5. Deploy (if CI/CD configured)
|
||||
# Automatic via git push
|
||||
```
|
||||
|
||||
### Multi-Repository Management
|
||||
```bash
|
||||
# 1. Set up meta repository
|
||||
gitzone meta init
|
||||
|
||||
# 2. Add all related projects
|
||||
gitzone meta add frontend https://github.com/org/frontend.git
|
||||
gitzone meta add backend https://github.com/org/backend.git
|
||||
gitzone meta add shared https://github.com/org/shared.git
|
||||
|
||||
# 3. Synchronize updates
|
||||
gitzone meta update
|
||||
```
|
||||
|
||||
### Safe Formatting with Rollback
|
||||
```bash
|
||||
# 1. Preview changes
|
||||
gitzone format --dry-run
|
||||
|
||||
# 2. Save plan for review
|
||||
gitzone format --save-plan format-changes.json
|
||||
|
||||
# 3. Apply formatting
|
||||
gitzone format --from-plan format-changes.json
|
||||
|
||||
# 4. If something goes wrong, rollback
|
||||
gitzone format --rollback
|
||||
```
|
||||
|
||||
## 🔌 Integrations
|
||||
|
||||
### CI/CD Platforms
|
||||
- **GitLab CI** - Full pipeline support with templates
|
||||
- **GitHub Actions** - Automated workflows
|
||||
- **Docker** - Container-based deployments
|
||||
|
||||
### Development Tools
|
||||
- **TypeScript** - First-class support
|
||||
- **Prettier** - Code formatting
|
||||
- **ESLint** - Linting (via format modules)
|
||||
- **npm/pnpm** - Package management
|
||||
|
||||
### Version Control
|
||||
- **Git** - Deep integration
|
||||
- **Semantic Versioning** - Automatic version bumping
|
||||
- **Conventional Commits** - Standardized commit messages
|
||||
|
||||
## 💡 Pro Tips
|
||||
|
||||
1. **Use aliases**: Add `alias gz='gitzone'` to your shell profile
|
||||
2. **Combine commands**: `gitzone format --yes && gitzone commit`
|
||||
3. **Leverage templates**: Start projects right with proven structures
|
||||
4. **Enable caching**: Dramatically speeds up formatting operations
|
||||
5. **Save format plans**: Review changes before applying in production
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Format Command Shows "Cancelled"
|
||||
If the format command shows cancelled even after confirming:
|
||||
- Check your `npmextra.json` configuration
|
||||
- Try with `--yes` flag to skip confirmation
|
||||
- Use `--verbose` for detailed output
|
||||
|
||||
### Docker Commands Fail
|
||||
Ensure Docker daemon is running:
|
||||
```bash
|
||||
docker info
|
||||
```
|
||||
|
||||
### Template Creation Issues
|
||||
Verify npm/pnpm is properly configured:
|
||||
```bash
|
||||
npm config get registry
|
||||
```
|
||||
|
||||
## 📈 Performance
|
||||
|
||||
gitzone is optimized for speed:
|
||||
- **Parallel processing** for format operations
|
||||
- **Smart caching** to avoid redundant work
|
||||
- **Incremental updates** for meta repositories
|
||||
- **Minimal dependencies** for fast installation
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
|
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@git.zone/cli',
|
||||
version: '1.16.1',
|
||||
version: '1.16.7',
|
||||
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.'
|
||||
}
|
||||
|
@@ -40,7 +40,9 @@ export class GitzoneConfig {
|
||||
public async readConfigFromCwd() {
|
||||
const npmextraInstance = new plugins.npmextra.Npmextra(paths.cwd);
|
||||
this.data = npmextraInstance.dataFor<IGitzoneConfigData>('gitzone', {});
|
||||
this.data.npmciOptions = npmextraInstance.dataFor<IGitzoneConfigData['npmciOptions']>('npmci', {
|
||||
this.data.npmciOptions = npmextraInstance.dataFor<
|
||||
IGitzoneConfigData['npmciOptions']
|
||||
>('npmci', {
|
||||
npmAccessLevel: 'public',
|
||||
});
|
||||
}
|
||||
|
@@ -89,7 +89,7 @@ export let run = async () => {
|
||||
detailed: argvArg.detailed,
|
||||
interactive: argvArg.interactive !== false,
|
||||
parallel: argvArg.parallel !== false,
|
||||
verbose: argvArg.verbose
|
||||
verbose: argvArg.verbose,
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -5,7 +5,8 @@ import * as plugins from './plugins.js';
|
||||
export const logger = plugins.smartlog.Smartlog.createForCommitinfo(commitinfo);
|
||||
|
||||
// Add console destination
|
||||
const consoleDestination = new plugins.smartlogDestinationLocal.DestinationLocal();
|
||||
const consoleDestination =
|
||||
new plugins.smartlogDestinationLocal.DestinationLocal();
|
||||
logger.addLogDestination(consoleDestination);
|
||||
|
||||
// Verbose logging helper
|
||||
|
@@ -10,20 +10,22 @@ export const run = async (argvArg: any) => {
|
||||
await formatMod.run();
|
||||
}
|
||||
|
||||
|
||||
logger.log('info', `gathering facts...`);
|
||||
const aidoc = new plugins.tsdoc.AiDoc();
|
||||
await aidoc.start();
|
||||
|
||||
const nextCommitObject = await aidoc.buildNextCommitObject(paths.cwd);
|
||||
|
||||
logger.log('info', `---------
|
||||
logger.log(
|
||||
'info',
|
||||
`---------
|
||||
Next recommended commit would be:
|
||||
===========
|
||||
-> ${nextCommitObject.recommendedNextVersion}:
|
||||
-> ${nextCommitObject.recommendedNextVersionLevel}(${nextCommitObject.recommendedNextVersionScope}): ${nextCommitObject.recommendedNextVersionMessage}
|
||||
===========
|
||||
`);
|
||||
`,
|
||||
);
|
||||
const commitInteract = new plugins.smartinteract.SmartInteract();
|
||||
commitInteract.addQuestions([
|
||||
{
|
||||
@@ -72,32 +74,55 @@ export const run = async (argvArg: any) => {
|
||||
});
|
||||
|
||||
logger.log('info', `Baking commitinfo into code ...`);
|
||||
const commitInfo = new plugins.commitinfo.CommitInfo(paths.cwd, commitVersionType);
|
||||
const commitInfo = new plugins.commitinfo.CommitInfo(
|
||||
paths.cwd,
|
||||
commitVersionType,
|
||||
);
|
||||
await commitInfo.writeIntoPotentialDirs();
|
||||
|
||||
logger.log('info', `Writing changelog.md ...`);
|
||||
let changelog = nextCommitObject.changelog;
|
||||
changelog = changelog.replaceAll('{{nextVersion}}', (await commitInfo.getNextPlannedVersion()).versionString);
|
||||
changelog = changelog.replaceAll('{{nextVersionScope}}', `${await answerBucket.getAnswerFor('commitType')}(${await answerBucket.getAnswerFor('commitScope')})`);
|
||||
changelog = changelog.replaceAll('{{nextVersionMessage}}', nextCommitObject.recommendedNextVersionMessage);
|
||||
changelog = changelog.replaceAll(
|
||||
'{{nextVersion}}',
|
||||
(await commitInfo.getNextPlannedVersion()).versionString,
|
||||
);
|
||||
changelog = changelog.replaceAll(
|
||||
'{{nextVersionScope}}',
|
||||
`${await answerBucket.getAnswerFor('commitType')}(${await answerBucket.getAnswerFor('commitScope')})`,
|
||||
);
|
||||
changelog = changelog.replaceAll(
|
||||
'{{nextVersionMessage}}',
|
||||
nextCommitObject.recommendedNextVersionMessage,
|
||||
);
|
||||
if (nextCommitObject.recommendedNextVersionDetails?.length > 0) {
|
||||
changelog = changelog.replaceAll('{{nextVersionDetails}}', '- ' + nextCommitObject.recommendedNextVersionDetails.join('\n- '));
|
||||
changelog = changelog.replaceAll(
|
||||
'{{nextVersionDetails}}',
|
||||
'- ' + nextCommitObject.recommendedNextVersionDetails.join('\n- '),
|
||||
);
|
||||
} else {
|
||||
changelog = changelog.replaceAll('\n{{nextVersionDetails}}', '');
|
||||
}
|
||||
|
||||
await plugins.smartfile.memory.toFs(changelog, plugins.path.join(paths.cwd, `changelog.md`));
|
||||
await plugins.smartfile.memory.toFs(
|
||||
changelog,
|
||||
plugins.path.join(paths.cwd, `changelog.md`),
|
||||
);
|
||||
|
||||
logger.log('info', `Staging files for commit:`);
|
||||
await smartshellInstance.exec(`git add -A`);
|
||||
await smartshellInstance.exec(`git commit -m "${commitString}"`);
|
||||
await smartshellInstance.exec(`npm version ${commitVersionType}`);
|
||||
if (answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true')) {
|
||||
if (
|
||||
answerBucket.getAnswerFor('pushToOrigin') &&
|
||||
!(process.env.CI === 'true')
|
||||
) {
|
||||
await smartshellInstance.exec(`git push origin master --follow-tags`);
|
||||
}
|
||||
};
|
||||
|
||||
const createCommitStringFromAnswerBucket = (answerBucket: plugins.smartinteract.AnswerBucket) => {
|
||||
const createCommitStringFromAnswerBucket = (
|
||||
answerBucket: plugins.smartinteract.AnswerBucket,
|
||||
) => {
|
||||
const commitType = answerBucket.getAnswerFor('commitType');
|
||||
const commitScope = answerBucket.getAnswerFor('commitScope');
|
||||
const commitDescription = answerBucket.getAnswerFor('commitDescription');
|
||||
|
@@ -36,7 +36,10 @@ export const run = async () => {
|
||||
const registryUrls = answerBucket.getAnswerFor(`registryUrls`).split(',');
|
||||
const oldPackageName = answerBucket.getAnswerFor(`oldPackageName`);
|
||||
const newPackageName = answerBucket.getAnswerFor(`newPackageName`);
|
||||
logger.log('info', `Deprecating package ${oldPackageName} in favour of ${newPackageName}`);
|
||||
logger.log(
|
||||
'info',
|
||||
`Deprecating package ${oldPackageName} in favour of ${newPackageName}`,
|
||||
);
|
||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
});
|
||||
|
@@ -29,21 +29,67 @@ export class ChangeCache {
|
||||
}
|
||||
|
||||
async getManifest(): Promise<ICacheManifest> {
|
||||
const exists = await plugins.smartfile.fs.fileExists(this.manifestPath);
|
||||
if (!exists) {
|
||||
return {
|
||||
const defaultManifest: ICacheManifest = {
|
||||
version: this.cacheVersion,
|
||||
lastFormat: 0,
|
||||
files: []
|
||||
};
|
||||
|
||||
const exists = await plugins.smartfile.fs.fileExists(this.manifestPath);
|
||||
if (!exists) {
|
||||
return defaultManifest;
|
||||
}
|
||||
|
||||
const content = await plugins.smartfile.fs.toStringSync(this.manifestPath);
|
||||
return JSON.parse(content);
|
||||
try {
|
||||
const content = plugins.smartfile.fs.toStringSync(this.manifestPath);
|
||||
const manifest = JSON.parse(content);
|
||||
|
||||
// Validate the manifest structure
|
||||
if (this.isValidManifest(manifest)) {
|
||||
return manifest;
|
||||
} else {
|
||||
console.warn('Invalid manifest structure, returning default manifest');
|
||||
return defaultManifest;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to read cache manifest: ${error.message}, returning default manifest`);
|
||||
// Try to delete the corrupted file
|
||||
try {
|
||||
await plugins.smartfile.fs.remove(this.manifestPath);
|
||||
} catch (removeError) {
|
||||
// Ignore removal errors
|
||||
}
|
||||
return defaultManifest;
|
||||
}
|
||||
}
|
||||
|
||||
async saveManifest(manifest: ICacheManifest): Promise<void> {
|
||||
await plugins.smartfile.memory.toFs(JSON.stringify(manifest, null, 2), this.manifestPath);
|
||||
// Validate before saving
|
||||
if (!this.isValidManifest(manifest)) {
|
||||
throw new Error('Invalid manifest structure, cannot save');
|
||||
}
|
||||
|
||||
// Use atomic write: write to temp file, then move it
|
||||
const tempPath = `${this.manifestPath}.tmp`;
|
||||
|
||||
try {
|
||||
// Write to temporary file
|
||||
const jsonContent = JSON.stringify(manifest, null, 2);
|
||||
await plugins.smartfile.memory.toFs(jsonContent, tempPath);
|
||||
|
||||
// Move temp file to actual manifest (atomic-like operation)
|
||||
// Since smartfile doesn't have rename, we copy and delete
|
||||
await plugins.smartfile.fs.copy(tempPath, this.manifestPath);
|
||||
await plugins.smartfile.fs.remove(tempPath);
|
||||
} catch (error) {
|
||||
// Clean up temp file if it exists
|
||||
try {
|
||||
await plugins.smartfile.fs.remove(tempPath);
|
||||
} catch (removeError) {
|
||||
// Ignore removal errors
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async hasFileChanged(filePath: string): Promise<boolean> {
|
||||
@@ -59,7 +105,13 @@ export class ChangeCache {
|
||||
|
||||
// Get current file stats
|
||||
const stats = await plugins.smartfile.fs.stat(absolutePath);
|
||||
const content = await plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
|
||||
// Skip directories
|
||||
if (stats.isDirectory()) {
|
||||
return false; // Directories are not processed
|
||||
}
|
||||
|
||||
const content = plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
const currentChecksum = this.calculateChecksum(content);
|
||||
|
||||
// Get cached info
|
||||
@@ -83,7 +135,13 @@ export class ChangeCache {
|
||||
|
||||
// Get current file stats
|
||||
const stats = await plugins.smartfile.fs.stat(absolutePath);
|
||||
const content = await plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
|
||||
// Skip directories
|
||||
if (stats.isDirectory()) {
|
||||
return; // Don't cache directories
|
||||
}
|
||||
|
||||
const content = plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
const checksum = this.calculateChecksum(content);
|
||||
|
||||
// Update manifest
|
||||
@@ -141,4 +199,31 @@ export class ChangeCache {
|
||||
private calculateChecksum(content: string | Buffer): string {
|
||||
return plugins.crypto.createHash('sha256').update(content).digest('hex');
|
||||
}
|
||||
|
||||
private isValidManifest(manifest: any): manifest is ICacheManifest {
|
||||
// Check if manifest has the required structure
|
||||
if (!manifest || typeof manifest !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check required fields
|
||||
if (typeof manifest.version !== 'string' ||
|
||||
typeof manifest.lastFormat !== 'number' ||
|
||||
!Array.isArray(manifest.files)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each file entry
|
||||
for (const file of manifest.files) {
|
||||
if (!file || typeof file !== 'object' ||
|
||||
typeof file.path !== 'string' ||
|
||||
typeof file.checksum !== 'string' ||
|
||||
typeof file.modified !== 'number' ||
|
||||
typeof file.size !== 'number') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -43,7 +43,7 @@ export class RollbackManager {
|
||||
}
|
||||
|
||||
// Read file content and metadata
|
||||
const content = await plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
const content = plugins.smartfile.fs.toStringSync(absolutePath);
|
||||
const stats = await plugins.smartfile.fs.stat(absolutePath);
|
||||
const checksum = this.calculateChecksum(content);
|
||||
|
||||
@@ -82,7 +82,7 @@ export class RollbackManager {
|
||||
|
||||
// Verify backup integrity
|
||||
const backupPath = this.getBackupPath(operationId, file.path);
|
||||
const backupContent = await plugins.smartfile.fs.toStringSync(backupPath);
|
||||
const backupContent = plugins.smartfile.fs.toStringSync(backupPath);
|
||||
const backupChecksum = this.calculateChecksum(backupContent);
|
||||
|
||||
if (backupChecksum !== file.checksum) {
|
||||
@@ -146,7 +146,7 @@ export class RollbackManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
const content = await plugins.smartfile.fs.toStringSync(backupPath);
|
||||
const content = plugins.smartfile.fs.toStringSync(backupPath);
|
||||
const checksum = this.calculateChecksum(content);
|
||||
|
||||
if (checksum !== file.checksum) {
|
||||
@@ -185,17 +185,63 @@ export class RollbackManager {
|
||||
}
|
||||
|
||||
private async getManifest(): Promise<{ operations: IFormatOperation[] }> {
|
||||
const defaultManifest = { operations: [] };
|
||||
|
||||
const exists = await plugins.smartfile.fs.fileExists(this.manifestPath);
|
||||
if (!exists) {
|
||||
return { operations: [] };
|
||||
return defaultManifest;
|
||||
}
|
||||
|
||||
const content = await plugins.smartfile.fs.toStringSync(this.manifestPath);
|
||||
return JSON.parse(content);
|
||||
try {
|
||||
const content = plugins.smartfile.fs.toStringSync(this.manifestPath);
|
||||
const manifest = JSON.parse(content);
|
||||
|
||||
// Validate the manifest structure
|
||||
if (this.isValidManifest(manifest)) {
|
||||
return manifest;
|
||||
} else {
|
||||
console.warn('Invalid rollback manifest structure, returning default manifest');
|
||||
return defaultManifest;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to read rollback manifest: ${error.message}, returning default manifest`);
|
||||
// Try to delete the corrupted file
|
||||
try {
|
||||
await plugins.smartfile.fs.remove(this.manifestPath);
|
||||
} catch (removeError) {
|
||||
// Ignore removal errors
|
||||
}
|
||||
return defaultManifest;
|
||||
}
|
||||
}
|
||||
|
||||
private async saveManifest(manifest: { operations: IFormatOperation[] }): Promise<void> {
|
||||
await plugins.smartfile.memory.toFs(JSON.stringify(manifest, null, 2), this.manifestPath);
|
||||
// Validate before saving
|
||||
if (!this.isValidManifest(manifest)) {
|
||||
throw new Error('Invalid rollback manifest structure, cannot save');
|
||||
}
|
||||
|
||||
// Use atomic write: write to temp file, then move it
|
||||
const tempPath = `${this.manifestPath}.tmp`;
|
||||
|
||||
try {
|
||||
// Write to temporary file
|
||||
const jsonContent = JSON.stringify(manifest, null, 2);
|
||||
await plugins.smartfile.memory.toFs(jsonContent, tempPath);
|
||||
|
||||
// Move temp file to actual manifest (atomic-like operation)
|
||||
// Since smartfile doesn't have rename, we copy and delete
|
||||
await plugins.smartfile.fs.copy(tempPath, this.manifestPath);
|
||||
await plugins.smartfile.fs.remove(tempPath);
|
||||
} catch (error) {
|
||||
// Clean up temp file if it exists
|
||||
try {
|
||||
await plugins.smartfile.fs.remove(tempPath);
|
||||
} catch (removeError) {
|
||||
// Ignore removal errors
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async getOperation(operationId: string): Promise<IFormatOperation | null> {
|
||||
@@ -215,4 +261,38 @@ export class RollbackManager {
|
||||
|
||||
await this.saveManifest(manifest);
|
||||
}
|
||||
|
||||
private isValidManifest(manifest: any): manifest is { operations: IFormatOperation[] } {
|
||||
// Check if manifest has the required structure
|
||||
if (!manifest || typeof manifest !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check required fields
|
||||
if (!Array.isArray(manifest.operations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each operation entry
|
||||
for (const operation of manifest.operations) {
|
||||
if (!operation || typeof operation !== 'object' ||
|
||||
typeof operation.id !== 'string' ||
|
||||
typeof operation.timestamp !== 'number' ||
|
||||
typeof operation.status !== 'string' ||
|
||||
!Array.isArray(operation.files)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each file in the operation
|
||||
for (const file of operation.files) {
|
||||
if (!file || typeof file !== 'object' ||
|
||||
typeof file.path !== 'string' ||
|
||||
typeof file.checksum !== 'string') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -10,13 +10,75 @@ export class PrettierFormatter extends BaseFormatter {
|
||||
|
||||
async analyze(): Promise<IPlannedChange[]> {
|
||||
const changes: IPlannedChange[] = [];
|
||||
const globPattern = '**/*.{ts,tsx,js,jsx,json,md,css,scss,html,xml,yaml,yml}';
|
||||
|
||||
// Define directories to format (TypeScript directories by default)
|
||||
const includeDirs = [
|
||||
'ts',
|
||||
'ts_*',
|
||||
'test',
|
||||
'tests'
|
||||
];
|
||||
|
||||
// File extensions to format
|
||||
const extensions = '{ts,tsx,js,jsx,json,md,css,scss,html,xml,yaml,yml}';
|
||||
|
||||
// Also format root-level config files
|
||||
const rootConfigFiles = [
|
||||
'package.json',
|
||||
'tsconfig.json',
|
||||
'npmextra.json',
|
||||
'.prettierrc',
|
||||
'.prettierrc.json',
|
||||
'.prettierrc.js',
|
||||
'readme.md',
|
||||
'README.md',
|
||||
'changelog.md',
|
||||
'CHANGELOG.md',
|
||||
'license',
|
||||
'LICENSE',
|
||||
'*.md'
|
||||
];
|
||||
|
||||
// Collect all files to format
|
||||
const allFiles: string[] = [];
|
||||
|
||||
// Add files from TypeScript directories
|
||||
for (const dir of includeDirs) {
|
||||
const globPattern = `${dir}/**/*.${extensions}`;
|
||||
const dirFiles = await plugins.smartfile.fs.listFileTree('.', globPattern);
|
||||
allFiles.push(...dirFiles);
|
||||
}
|
||||
|
||||
// Add root config files
|
||||
for (const pattern of rootConfigFiles) {
|
||||
const rootFiles = await plugins.smartfile.fs.listFileTree('.', pattern);
|
||||
// Only include files at root level (no slashes in path)
|
||||
const rootLevelFiles = rootFiles.filter(f => !f.includes('/'));
|
||||
allFiles.push(...rootLevelFiles);
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
const uniqueFiles = [...new Set(allFiles)];
|
||||
|
||||
// Get all files that match the pattern
|
||||
const files = await plugins.smartfile.fs.listFileTree('.', globPattern);
|
||||
const files = uniqueFiles;
|
||||
|
||||
// Ensure we only process actual files (not directories)
|
||||
const validFiles: string[] = [];
|
||||
for (const file of files) {
|
||||
try {
|
||||
const stats = await plugins.smartfile.fs.stat(file);
|
||||
if (!stats.isDirectory()) {
|
||||
validFiles.push(file);
|
||||
}
|
||||
} catch (error) {
|
||||
// Skip files that can't be accessed
|
||||
logVerbose(`Skipping ${file} - cannot access: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check which files need formatting
|
||||
for (const file of files) {
|
||||
for (const file of validFiles) {
|
||||
// Skip files that haven't changed
|
||||
if (!await this.shouldProcessFile(file)) {
|
||||
logVerbose(`Skipping ${file} - no changes detected`);
|
||||
@@ -85,7 +147,7 @@ export class PrettierFormatter extends BaseFormatter {
|
||||
|
||||
try {
|
||||
// Read current content
|
||||
const content = await plugins.smartfile.fs.toStringSync(change.path);
|
||||
const content = plugins.smartfile.fs.toStringSync(change.path);
|
||||
|
||||
// Format with prettier
|
||||
const prettier = await import('prettier');
|
||||
|
@@ -135,7 +135,7 @@ export let run = async (options: {
|
||||
default: true
|
||||
});
|
||||
|
||||
if (!(response as any).proceed) {
|
||||
if (!(response as any).value) {
|
||||
logger.log('info', 'Format operation cancelled by user');
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user