@edcalderon/versioning 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +274 -0
- package/dist/changelog.d.ts +15 -0
- package/dist/changelog.js +99 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +310 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/release.d.ts +32 -0
- package/dist/release.js +101 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.js +113 -0
- package/dist/versioning.d.ts +19 -0
- package/dist/versioning.js +97 -0
- package/package.json +72 -0
- package/scripts/create-tag.js +51 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-01-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of @edcalderon/versioning
|
|
12
|
+
- Comprehensive versioning and changelog management
|
|
13
|
+
- Support for both single repositories and monorepos
|
|
14
|
+
- CLI tool with multiple commands (patch, minor, major, release, bump, changelog, sync, validate, init)
|
|
15
|
+
- Conventional commits integration
|
|
16
|
+
- Git tagging and committing
|
|
17
|
+
- Version synchronization across packages
|
|
18
|
+
- Package selection for selective releases
|
|
19
|
+
- TypeScript support with full type safety
|
|
20
|
+
- Jest testing framework
|
|
21
|
+
- NPM publishable package structure
|
package/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# @edcalderon/versioning
|
|
2
|
+
|
|
3
|
+
A comprehensive versioning and changelog management tool designed for monorepos and single repositories. It provides automated version bumping, changelog generation using conventional commits, and version synchronization across multiple packages.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- š Automated version bumping (patch, minor, major, prerelease)
|
|
8
|
+
- š Conventional commit-based changelog generation
|
|
9
|
+
- š Version synchronization across monorepo packages
|
|
10
|
+
- šÆ Works with both monorepos and single repositories
|
|
11
|
+
- š¦ NPM publishable
|
|
12
|
+
- š·ļø Git tagging and committing
|
|
13
|
+
- ā
Validation of version sync
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @edcalderon/versioning
|
|
19
|
+
# or
|
|
20
|
+
pnpm add -g @edcalderon/versioning
|
|
21
|
+
# or
|
|
22
|
+
yarn global add @edcalderon/versioning
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
1. Initialize configuration:
|
|
28
|
+
```bash
|
|
29
|
+
ed-version init
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. Bump version and generate changelog:
|
|
33
|
+
```bash
|
|
34
|
+
ed-version bump patch
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. Sync versions across packages (for monorepos):
|
|
38
|
+
```bash
|
|
39
|
+
ed-version sync
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Edward's Monorepo Example
|
|
43
|
+
|
|
44
|
+
For this specific monorepo with dashboard app:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Initialize config
|
|
48
|
+
ed-version init
|
|
49
|
+
|
|
50
|
+
# Edit versioning.config.json to:
|
|
51
|
+
{
|
|
52
|
+
"packages": ["apps/dashboard"],
|
|
53
|
+
"ignorePackages": ["packages/versioning"]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Sync dashboard with main version
|
|
57
|
+
ed-version patch --packages "apps/dashboard"
|
|
58
|
+
|
|
59
|
+
# Versioning package maintains its own version
|
|
60
|
+
cd packages/versioning && ed-version patch --skip-sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
Create a `versioning.config.json` file in your project root:
|
|
66
|
+
|
|
67
|
+
For single repositories:
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"rootPackageJson": "package.json",
|
|
71
|
+
"packages": [],
|
|
72
|
+
"changelogFile": "CHANGELOG.md",
|
|
73
|
+
"conventionalCommits": true,
|
|
74
|
+
"syncDependencies": false,
|
|
75
|
+
"ignorePackages": []
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
For monorepos:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"rootPackageJson": "package.json",
|
|
83
|
+
"packages": ["packages/*", "apps/*"],
|
|
84
|
+
"changelogFile": "CHANGELOG.md",
|
|
85
|
+
"conventionalCommits": true,
|
|
86
|
+
"syncDependencies": true,
|
|
87
|
+
"ignorePackages": []
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Configuration Options
|
|
92
|
+
|
|
93
|
+
- `rootPackageJson`: Path to the root package.json file
|
|
94
|
+
- `packages`: Array of glob patterns for packages to sync
|
|
95
|
+
- `changelogFile`: Path to the changelog file
|
|
96
|
+
- `conventionalCommits`: Whether to use conventional commits for changelog
|
|
97
|
+
- `syncDependencies`: Whether to sync internal dependencies
|
|
98
|
+
- `ignorePackages`: Array of package names to ignore during sync
|
|
99
|
+
|
|
100
|
+
## Commands
|
|
101
|
+
|
|
102
|
+
### Release Commands
|
|
103
|
+
|
|
104
|
+
#### `ed-version patch [options]`
|
|
105
|
+
|
|
106
|
+
Create a patch release (bumps 1.0.0 ā 1.0.1)
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
ed-version patch
|
|
110
|
+
ed-version patch --packages "packages/app1,packages/app2" --message "Fix critical bug"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `ed-version minor [options]`
|
|
114
|
+
|
|
115
|
+
Create a minor release (bumps 1.0.0 ā 1.1.0)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
ed-version minor
|
|
119
|
+
ed-version minor --packages "apps/dashboard" --message "Add new features"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### `ed-version major [options]`
|
|
123
|
+
|
|
124
|
+
Create a major release (bumps 1.0.0 ā 2.0.0)
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
ed-version major --message "Breaking changes"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### `ed-version release <version> [options]`
|
|
131
|
+
|
|
132
|
+
Create a custom release with specific version
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
ed-version release 1.2.3 --message "Custom release"
|
|
136
|
+
ed-version release 2.0.0-beta.1 --skip-sync
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Options for release commands:**
|
|
140
|
+
- `-p, --packages <packages>`: Comma-separated list of packages to sync
|
|
141
|
+
- `-m, --message <message>`: Release commit message
|
|
142
|
+
- `-c, --config <file>`: Config file path (default: versioning.config.json)
|
|
143
|
+
- `--no-tag`: Do not create git tag
|
|
144
|
+
- `--no-commit`: Do not commit changes
|
|
145
|
+
- `--skip-sync`: Skip version synchronization (for `release` command)
|
|
146
|
+
|
|
147
|
+
### Other Commands
|
|
148
|
+
|
|
149
|
+
Bump the version and generate changelog.
|
|
150
|
+
|
|
151
|
+
Types: `patch`, `minor`, `major`, `prerelease`
|
|
152
|
+
|
|
153
|
+
Options:
|
|
154
|
+
- `-p, --pre-release <identifier>`: Prerelease identifier
|
|
155
|
+
- `-c, --config <file>`: Config file path (default: versioning.config.json)
|
|
156
|
+
- `--no-commit`: Don't commit changes
|
|
157
|
+
- `--no-tag`: Don't create git tag
|
|
158
|
+
|
|
159
|
+
### `ed-version changelog [options]`
|
|
160
|
+
|
|
161
|
+
Generate changelog from commits.
|
|
162
|
+
|
|
163
|
+
Options:
|
|
164
|
+
- `-f, --from <commit>`: From commit
|
|
165
|
+
- `-t, --to <commit>`: To commit
|
|
166
|
+
- `-c, --config <file>`: Config file path
|
|
167
|
+
|
|
168
|
+
### `ed-version sync [options]`
|
|
169
|
+
|
|
170
|
+
Sync versions across all packages.
|
|
171
|
+
|
|
172
|
+
Options:
|
|
173
|
+
- `-v, --version <version>`: Target version to sync to
|
|
174
|
+
- `-c, --config <file>`: Config file path
|
|
175
|
+
|
|
176
|
+
### `ed-version validate [options]`
|
|
177
|
+
|
|
178
|
+
Validate that all packages have the correct version.
|
|
179
|
+
|
|
180
|
+
Options:
|
|
181
|
+
- `-c, --config <file>`: Config file path
|
|
182
|
+
|
|
183
|
+
### `ed-version init [options]`
|
|
184
|
+
|
|
185
|
+
Initialize a new versioning config file.
|
|
186
|
+
|
|
187
|
+
Options:
|
|
188
|
+
- `-f, --force`: Overwrite existing config
|
|
189
|
+
|
|
190
|
+
## Workflow Integration
|
|
191
|
+
|
|
192
|
+
### GitHub Actions
|
|
193
|
+
|
|
194
|
+
Add to your release workflow:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
- name: Bump version
|
|
198
|
+
run: npx @edcalderon/versioning bump patch
|
|
199
|
+
env:
|
|
200
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Pre-commit Hooks
|
|
204
|
+
|
|
205
|
+
Use with husky for automated versioning:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npx husky add .husky/pre-commit "ed-version validate"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Conventional Commits
|
|
212
|
+
|
|
213
|
+
This tool works best with conventional commits. Examples:
|
|
214
|
+
|
|
215
|
+
- `feat: add new feature` (minor bump)
|
|
216
|
+
- `fix: resolve bug` (patch bump)
|
|
217
|
+
- `BREAKING CHANGE: change API` (major bump)
|
|
218
|
+
|
|
219
|
+
## Documentation
|
|
220
|
+
|
|
221
|
+
- **[Usage Guide](USAGE.md)** - Comprehensive examples and advanced usage patterns
|
|
222
|
+
- **[Configuration Examples](examples.md)** - Real-world configuration examples
|
|
223
|
+
- **[CHANGELOG](CHANGELOG.md)** - Version history and changes
|
|
224
|
+
|
|
225
|
+
## Publishing & Releases
|
|
226
|
+
|
|
227
|
+
### Automated NPM Publishing
|
|
228
|
+
|
|
229
|
+
This package uses GitHub Actions for automated publishing to NPM when version tags are created.
|
|
230
|
+
|
|
231
|
+
#### Release Process
|
|
232
|
+
|
|
233
|
+
1. **Update Version**: Use the versioning commands to bump version and update changelog
|
|
234
|
+
```bash
|
|
235
|
+
ed-version patch # or minor, major
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
2. **Create Git Tag**: The package includes a helper script to create and push version tags
|
|
239
|
+
```bash
|
|
240
|
+
npm run create-tag
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
3. **Automated Publishing**: GitHub Actions will automatically:
|
|
244
|
+
- Build the package
|
|
245
|
+
- Run tests
|
|
246
|
+
- Publish to NPM
|
|
247
|
+
- Create a GitHub Release
|
|
248
|
+
|
|
249
|
+
#### Manual Publishing (First Release)
|
|
250
|
+
|
|
251
|
+
For the initial release, publish manually:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
cd packages/versioning
|
|
255
|
+
npm login
|
|
256
|
+
npm publish
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### NPM Token Setup
|
|
260
|
+
|
|
261
|
+
To enable automated publishing:
|
|
262
|
+
|
|
263
|
+
1. Go to [NPM](https://www.npmjs.com/) ā Access Tokens ā Generate New Token
|
|
264
|
+
2. Create a token with **Automation** scope
|
|
265
|
+
3. Add to GitHub repository secrets as `NPM_TOKEN`
|
|
266
|
+
|
|
267
|
+
### Version Tags
|
|
268
|
+
|
|
269
|
+
Tags should follow the format `v{major}.{minor}.{patch}` (e.g., `v1.0.0`, `v1.1.0`, `v2.0.0`).
|
|
270
|
+
|
|
271
|
+
The `create-tag` script will:
|
|
272
|
+
- Read the version from `package.json`
|
|
273
|
+
- Create an annotated git tag
|
|
274
|
+
- Push the tag to trigger the publish workflow
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ChangelogConfig {
|
|
2
|
+
preset?: string;
|
|
3
|
+
infile?: string;
|
|
4
|
+
outfile?: string;
|
|
5
|
+
releaseCount?: number;
|
|
6
|
+
sameFile?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class ChangelogManager {
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config?: ChangelogConfig);
|
|
11
|
+
generate(from?: string, to?: string): Promise<string>;
|
|
12
|
+
private updateExistingChangelog;
|
|
13
|
+
getLatestRelease(): Promise<string | null>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=changelog.d.ts.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.ChangelogManager = void 0;
|
|
40
|
+
const fs = __importStar(require("fs-extra"));
|
|
41
|
+
const conventional_changelog_1 = __importDefault(require("conventional-changelog"));
|
|
42
|
+
class ChangelogManager {
|
|
43
|
+
constructor(config = {}) {
|
|
44
|
+
this.config = {
|
|
45
|
+
preset: 'angular',
|
|
46
|
+
infile: 'CHANGELOG.md',
|
|
47
|
+
outfile: 'CHANGELOG.md',
|
|
48
|
+
sameFile: true,
|
|
49
|
+
...config
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async generate(from, to) {
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
let changelog = '';
|
|
55
|
+
const stream = (0, conventional_changelog_1.default)({
|
|
56
|
+
preset: this.config.preset,
|
|
57
|
+
releaseCount: this.config.releaseCount,
|
|
58
|
+
...(from && { from }),
|
|
59
|
+
...(to && { to })
|
|
60
|
+
});
|
|
61
|
+
stream.on('data', (chunk) => {
|
|
62
|
+
changelog += chunk.toString();
|
|
63
|
+
});
|
|
64
|
+
stream.on('end', async () => {
|
|
65
|
+
if (this.config.sameFile && this.config.infile) {
|
|
66
|
+
await this.updateExistingChangelog(changelog);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await fs.writeFile(this.config.outfile, changelog);
|
|
70
|
+
}
|
|
71
|
+
resolve(changelog);
|
|
72
|
+
});
|
|
73
|
+
stream.on('error', reject);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async updateExistingChangelog(newContent) {
|
|
77
|
+
const existingContent = await fs.readFile(this.config.infile, 'utf-8');
|
|
78
|
+
const updatedContent = newContent + '\n\n' + existingContent;
|
|
79
|
+
await fs.writeFile(this.config.infile, updatedContent);
|
|
80
|
+
}
|
|
81
|
+
async getLatestRelease() {
|
|
82
|
+
try {
|
|
83
|
+
const content = await fs.readFile(this.config.infile, 'utf-8');
|
|
84
|
+
const lines = content.split('\n');
|
|
85
|
+
for (const line of lines) {
|
|
86
|
+
const match = line.match(/^## \[?(\d+\.\d+\.\d+)/);
|
|
87
|
+
if (match) {
|
|
88
|
+
return match[1];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
// File doesn't exist or can't be read
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.ChangelogManager = ChangelogManager;
|
|
99
|
+
//# sourceMappingURL=changelog.js.map
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const commander_1 = require("commander");
|
|
38
|
+
const fs = __importStar(require("fs-extra"));
|
|
39
|
+
const versioning_1 = require("./versioning");
|
|
40
|
+
const changelog_1 = require("./changelog");
|
|
41
|
+
const sync_1 = require("./sync");
|
|
42
|
+
const release_1 = require("./release");
|
|
43
|
+
const program = new commander_1.Command();
|
|
44
|
+
program
|
|
45
|
+
.name('ed-version')
|
|
46
|
+
.description('Comprehensive versioning and changelog management for monorepos')
|
|
47
|
+
.version('1.0.0');
|
|
48
|
+
program
|
|
49
|
+
.command('bump <type>')
|
|
50
|
+
.description('Bump version (patch, minor, major, prerelease)')
|
|
51
|
+
.option('-p, --pre-release <identifier>', 'prerelease identifier')
|
|
52
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
53
|
+
.option('--no-commit', 'do not commit changes')
|
|
54
|
+
.option('--no-tag', 'do not create git tag')
|
|
55
|
+
.action(async (type, options) => {
|
|
56
|
+
try {
|
|
57
|
+
const config = await loadConfig(options.config);
|
|
58
|
+
const versionManager = new versioning_1.VersionManager(config);
|
|
59
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
60
|
+
const newVersion = await versionManager.bumpVersion(type, options.preRelease);
|
|
61
|
+
console.log(`Bumped version to ${newVersion}`);
|
|
62
|
+
// Generate changelog
|
|
63
|
+
await changelogManager.generate();
|
|
64
|
+
console.log('Generated changelog');
|
|
65
|
+
if (options.commit !== false) {
|
|
66
|
+
await versionManager.commitChanges(newVersion);
|
|
67
|
+
console.log('Committed changes');
|
|
68
|
+
}
|
|
69
|
+
if (options.tag !== false) {
|
|
70
|
+
await versionManager.createGitTag(newVersion);
|
|
71
|
+
console.log('Created git tag');
|
|
72
|
+
}
|
|
73
|
+
console.log(`ā
Successfully released v${newVersion}`);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
program
|
|
81
|
+
.command('changelog')
|
|
82
|
+
.description('Generate changelog')
|
|
83
|
+
.option('-f, --from <commit>', 'from commit')
|
|
84
|
+
.option('-t, --to <commit>', 'to commit')
|
|
85
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
86
|
+
.action(async (options) => {
|
|
87
|
+
try {
|
|
88
|
+
const config = await loadConfig(options.config);
|
|
89
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
90
|
+
await changelogManager.generate(options.from, options.to);
|
|
91
|
+
console.log('ā
Changelog generated');
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
program
|
|
99
|
+
.command('sync')
|
|
100
|
+
.description('Sync versions across monorepo')
|
|
101
|
+
.option('-v, --version <version>', 'target version to sync to')
|
|
102
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
103
|
+
.action(async (options) => {
|
|
104
|
+
try {
|
|
105
|
+
const config = await loadConfig(options.config);
|
|
106
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
107
|
+
await syncManager.syncVersions(options.version);
|
|
108
|
+
console.log('ā
Versions synced');
|
|
109
|
+
const validation = await syncManager.validateSync();
|
|
110
|
+
if (!validation.valid) {
|
|
111
|
+
console.log('ā ļø Validation issues:');
|
|
112
|
+
validation.issues.forEach(issue => console.log(` - ${issue}`));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
program
|
|
121
|
+
.command('validate')
|
|
122
|
+
.description('Validate version sync across monorepo')
|
|
123
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
124
|
+
.action(async (options) => {
|
|
125
|
+
try {
|
|
126
|
+
const config = await loadConfig(options.config);
|
|
127
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
128
|
+
const validation = await syncManager.validateSync();
|
|
129
|
+
if (validation.valid) {
|
|
130
|
+
console.log('ā
All versions are in sync');
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
console.log('ā Version sync issues:');
|
|
134
|
+
validation.issues.forEach(issue => console.log(` - ${issue}`));
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
program
|
|
144
|
+
.command('patch')
|
|
145
|
+
.description('Create a patch release')
|
|
146
|
+
.option('-p, --packages <packages>', 'Comma-separated list of packages to sync')
|
|
147
|
+
.option('-m, --message <message>', 'Release commit message')
|
|
148
|
+
.option('-c, --config <file>', 'Config file path', 'versioning.config.json')
|
|
149
|
+
.option('--no-tag', 'Do not create git tag')
|
|
150
|
+
.option('--no-commit', 'Do not commit changes')
|
|
151
|
+
.action(async (options) => {
|
|
152
|
+
try {
|
|
153
|
+
const config = await loadConfig(options.config);
|
|
154
|
+
const versionManager = new versioning_1.VersionManager(config);
|
|
155
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
156
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
157
|
+
const releaseManager = new release_1.ReleaseManager({
|
|
158
|
+
versionManager,
|
|
159
|
+
changelogManager,
|
|
160
|
+
syncManager,
|
|
161
|
+
createTag: options.tag !== false,
|
|
162
|
+
createCommit: options.commit !== false
|
|
163
|
+
});
|
|
164
|
+
const packages = options.packages ? options.packages.split(',').map((p) => p.trim()) : undefined;
|
|
165
|
+
const newVersion = await releaseManager.patchRelease({
|
|
166
|
+
packages,
|
|
167
|
+
message: options.message
|
|
168
|
+
});
|
|
169
|
+
console.log(`ā
Patch release v${newVersion} completed`);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
program
|
|
177
|
+
.command('minor')
|
|
178
|
+
.description('Create a minor release')
|
|
179
|
+
.option('-p, --packages <packages>', 'Comma-separated list of packages to sync')
|
|
180
|
+
.option('-m, --message <message>', 'Release commit message')
|
|
181
|
+
.option('-c, --config <file>', 'Config file path', 'versioning.config.json')
|
|
182
|
+
.option('--no-tag', 'Do not create git tag')
|
|
183
|
+
.option('--no-commit', 'Do not commit changes')
|
|
184
|
+
.action(async (options) => {
|
|
185
|
+
try {
|
|
186
|
+
const config = await loadConfig(options.config);
|
|
187
|
+
const versionManager = new versioning_1.VersionManager(config);
|
|
188
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
189
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
190
|
+
const releaseManager = new release_1.ReleaseManager({
|
|
191
|
+
versionManager,
|
|
192
|
+
changelogManager,
|
|
193
|
+
syncManager,
|
|
194
|
+
createTag: options.tag !== false,
|
|
195
|
+
createCommit: options.commit !== false
|
|
196
|
+
});
|
|
197
|
+
const packages = options.packages ? options.packages.split(',').map((p) => p.trim()) : undefined;
|
|
198
|
+
const newVersion = await releaseManager.minorRelease({
|
|
199
|
+
packages,
|
|
200
|
+
message: options.message
|
|
201
|
+
});
|
|
202
|
+
console.log(`ā
Minor release v${newVersion} completed`);
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
program
|
|
210
|
+
.command('major')
|
|
211
|
+
.description('Create a major release')
|
|
212
|
+
.option('-p, --packages <packages>', 'Comma-separated list of packages to sync')
|
|
213
|
+
.option('-c, --config <file>', 'Config file path', 'versioning.config.json')
|
|
214
|
+
.option('--no-tag', 'Do not create git tag')
|
|
215
|
+
.option('--no-commit', 'Do not commit changes')
|
|
216
|
+
.action(async (options) => {
|
|
217
|
+
try {
|
|
218
|
+
const config = await loadConfig(options.config);
|
|
219
|
+
const versionManager = new versioning_1.VersionManager(config);
|
|
220
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
221
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
222
|
+
const releaseManager = new release_1.ReleaseManager({
|
|
223
|
+
versionManager,
|
|
224
|
+
changelogManager,
|
|
225
|
+
syncManager,
|
|
226
|
+
createTag: options.tag !== false,
|
|
227
|
+
createCommit: options.commit !== false
|
|
228
|
+
});
|
|
229
|
+
const packages = options.packages ? options.packages.split(',').map((p) => p.trim()) : undefined;
|
|
230
|
+
const newVersion = await releaseManager.majorRelease({
|
|
231
|
+
packages,
|
|
232
|
+
message: options.message
|
|
233
|
+
});
|
|
234
|
+
console.log(`ā
Major release v${newVersion} completed`);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
program
|
|
242
|
+
.command('release <version>')
|
|
243
|
+
.description('Create a custom release')
|
|
244
|
+
.option('-p, --packages <packages>', 'Comma-separated list of packages to sync')
|
|
245
|
+
.option('-m, --message <message>', 'Release commit message')
|
|
246
|
+
.option('-c, --config <file>', 'Config file path', 'versioning.config.json')
|
|
247
|
+
.option('--no-tag', 'Do not create git tag')
|
|
248
|
+
.option('--no-commit', 'Do not commit changes')
|
|
249
|
+
.option('--skip-sync', 'Skip version synchronization')
|
|
250
|
+
.action(async (version, options) => {
|
|
251
|
+
try {
|
|
252
|
+
const config = await loadConfig(options.config);
|
|
253
|
+
const versionManager = new versioning_1.VersionManager(config);
|
|
254
|
+
const changelogManager = new changelog_1.ChangelogManager(config);
|
|
255
|
+
const syncManager = new sync_1.SyncManager(config);
|
|
256
|
+
const releaseManager = new release_1.ReleaseManager({
|
|
257
|
+
versionManager,
|
|
258
|
+
changelogManager,
|
|
259
|
+
syncManager,
|
|
260
|
+
createTag: options.tag !== false,
|
|
261
|
+
createCommit: options.commit !== false
|
|
262
|
+
});
|
|
263
|
+
const packages = options.packages ? options.packages.split(',').map((p) => p.trim()) : undefined;
|
|
264
|
+
await releaseManager.release(version, {
|
|
265
|
+
packages,
|
|
266
|
+
message: options.message,
|
|
267
|
+
skipSync: options.skipSync
|
|
268
|
+
});
|
|
269
|
+
console.log(`ā
Release v${version} completed`);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
program
|
|
277
|
+
.command('init')
|
|
278
|
+
.description('Initialize versioning config')
|
|
279
|
+
.option('-f, --force', 'overwrite existing config')
|
|
280
|
+
.action(async (options) => {
|
|
281
|
+
try {
|
|
282
|
+
const configPath = 'versioning.config.json';
|
|
283
|
+
if (!options.force && await fs.pathExists(configPath)) {
|
|
284
|
+
console.error('ā Config file already exists. Use --force to overwrite.');
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
const defaultConfig = {
|
|
288
|
+
rootPackageJson: 'package.json',
|
|
289
|
+
packages: [],
|
|
290
|
+
changelogFile: 'CHANGELOG.md',
|
|
291
|
+
conventionalCommits: true,
|
|
292
|
+
syncDependencies: false,
|
|
293
|
+
ignorePackages: []
|
|
294
|
+
};
|
|
295
|
+
await fs.writeJson(configPath, defaultConfig, { spaces: 2 });
|
|
296
|
+
console.log('ā
Initialized versioning config at versioning.config.json');
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
console.error('ā Error:', error instanceof Error ? error.message : String(error));
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
async function loadConfig(configPath) {
|
|
304
|
+
if (!(await fs.pathExists(configPath))) {
|
|
305
|
+
throw new Error(`Config file not found: ${configPath}. Run 'ed-version init' to create one.`);
|
|
306
|
+
}
|
|
307
|
+
return await fs.readJson(configPath);
|
|
308
|
+
}
|
|
309
|
+
program.parse();
|
|
310
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./versioning"), exports);
|
|
18
|
+
__exportStar(require("./changelog"), exports);
|
|
19
|
+
__exportStar(require("./sync"), exports);
|
|
20
|
+
__exportStar(require("./release"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { VersionManager, ChangelogManager, SyncManager } from './index';
|
|
2
|
+
export interface ReleaseConfig {
|
|
3
|
+
versionManager: VersionManager;
|
|
4
|
+
changelogManager: ChangelogManager;
|
|
5
|
+
syncManager: SyncManager;
|
|
6
|
+
createTag?: boolean;
|
|
7
|
+
createCommit?: boolean;
|
|
8
|
+
publish?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class ReleaseManager {
|
|
11
|
+
private config;
|
|
12
|
+
constructor(config: ReleaseConfig);
|
|
13
|
+
release(version: string, options?: {
|
|
14
|
+
message?: string;
|
|
15
|
+
packages?: string[];
|
|
16
|
+
skipSync?: boolean;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
private publishPackages;
|
|
19
|
+
patchRelease(options?: {
|
|
20
|
+
packages?: string[];
|
|
21
|
+
message?: string;
|
|
22
|
+
}): Promise<string>;
|
|
23
|
+
minorRelease(options?: {
|
|
24
|
+
packages?: string[];
|
|
25
|
+
message?: string;
|
|
26
|
+
}): Promise<string>;
|
|
27
|
+
majorRelease(options?: {
|
|
28
|
+
packages?: string[];
|
|
29
|
+
message?: string;
|
|
30
|
+
}): Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=release.d.ts.map
|
package/dist/release.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ReleaseManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs-extra"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
class ReleaseManager {
|
|
40
|
+
constructor(config) {
|
|
41
|
+
this.config = {
|
|
42
|
+
createTag: true,
|
|
43
|
+
createCommit: true,
|
|
44
|
+
publish: false,
|
|
45
|
+
...config
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async release(version, options = {}) {
|
|
49
|
+
const { message, packages, skipSync } = options;
|
|
50
|
+
// Update versions
|
|
51
|
+
await this.config.versionManager.updateVersion(version);
|
|
52
|
+
// Sync specific packages if specified
|
|
53
|
+
if (!skipSync && packages && packages.length > 0) {
|
|
54
|
+
for (const pkg of packages) {
|
|
55
|
+
const packageJsonPath = path.join(pkg, 'package.json');
|
|
56
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
57
|
+
await this.config.versionManager.updateVersion(version); // This needs to be package-specific
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (!skipSync) {
|
|
62
|
+
await this.config.syncManager.syncVersions(version);
|
|
63
|
+
}
|
|
64
|
+
// Generate changelog
|
|
65
|
+
await this.config.changelogManager.generate();
|
|
66
|
+
// Commit changes
|
|
67
|
+
if (this.config.createCommit) {
|
|
68
|
+
await this.config.versionManager.commitChanges(version);
|
|
69
|
+
}
|
|
70
|
+
// Create git tag
|
|
71
|
+
if (this.config.createTag) {
|
|
72
|
+
await this.config.versionManager.createGitTag(version, message);
|
|
73
|
+
}
|
|
74
|
+
// Publish if requested (future implementation)
|
|
75
|
+
if (this.config.publish) {
|
|
76
|
+
await this.publishPackages(packages);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async publishPackages(packages) {
|
|
80
|
+
// TODO: Implement npm publish logic
|
|
81
|
+
console.log('Publishing packages:', packages || 'all');
|
|
82
|
+
}
|
|
83
|
+
async patchRelease(options = {}) {
|
|
84
|
+
const currentVersion = await this.config.versionManager.getCurrentVersion();
|
|
85
|
+
const newVersion = await this.config.versionManager.bumpVersion('patch');
|
|
86
|
+
await this.release(newVersion, options);
|
|
87
|
+
return newVersion;
|
|
88
|
+
}
|
|
89
|
+
async minorRelease(options = {}) {
|
|
90
|
+
const newVersion = await this.config.versionManager.bumpVersion('minor');
|
|
91
|
+
await this.release(newVersion, options);
|
|
92
|
+
return newVersion;
|
|
93
|
+
}
|
|
94
|
+
async majorRelease(options = {}) {
|
|
95
|
+
const newVersion = await this.config.versionManager.bumpVersion('major');
|
|
96
|
+
await this.release(newVersion, options);
|
|
97
|
+
return newVersion;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.ReleaseManager = ReleaseManager;
|
|
101
|
+
//# sourceMappingURL=release.js.map
|
package/dist/sync.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { VersionConfig } from './versioning';
|
|
2
|
+
export interface SyncConfig extends VersionConfig {
|
|
3
|
+
syncDependencies?: boolean;
|
|
4
|
+
ignorePackages?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare class SyncManager {
|
|
7
|
+
private config;
|
|
8
|
+
private versionManager;
|
|
9
|
+
constructor(config: SyncConfig);
|
|
10
|
+
syncVersions(targetVersion?: string): Promise<void>;
|
|
11
|
+
private updatePackageVersion;
|
|
12
|
+
private syncInternalDependencies;
|
|
13
|
+
private getInternalDependencies;
|
|
14
|
+
validateSync(): Promise<{
|
|
15
|
+
valid: boolean;
|
|
16
|
+
issues: string[];
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=sync.d.ts.map
|
package/dist/sync.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SyncManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs-extra"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const versioning_1 = require("./versioning");
|
|
40
|
+
class SyncManager {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.config = {
|
|
43
|
+
syncDependencies: true,
|
|
44
|
+
ignorePackages: [],
|
|
45
|
+
...config
|
|
46
|
+
};
|
|
47
|
+
this.versionManager = new versioning_1.VersionManager(config);
|
|
48
|
+
}
|
|
49
|
+
async syncVersions(targetVersion) {
|
|
50
|
+
const version = targetVersion || await this.versionManager.getCurrentVersion();
|
|
51
|
+
// Update all packages to match root version
|
|
52
|
+
for (const pkgPath of this.config.packages) {
|
|
53
|
+
if (this.config.ignorePackages?.includes(path.basename(pkgPath))) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const packageJsonPath = path.join(pkgPath, 'package.json');
|
|
57
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
58
|
+
await this.updatePackageVersion(packageJsonPath, version);
|
|
59
|
+
if (this.config.syncDependencies) {
|
|
60
|
+
await this.syncInternalDependencies(packageJsonPath, version);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async updatePackageVersion(packageJsonPath, version) {
|
|
66
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
67
|
+
packageJson.version = version;
|
|
68
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
69
|
+
}
|
|
70
|
+
async syncInternalDependencies(packageJsonPath, version) {
|
|
71
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
72
|
+
const internalDeps = this.getInternalDependencies(packageJson);
|
|
73
|
+
for (const dep of internalDeps) {
|
|
74
|
+
if (packageJson.dependencies && packageJson.dependencies[dep]) {
|
|
75
|
+
packageJson.dependencies[dep] = `^${version}`;
|
|
76
|
+
}
|
|
77
|
+
if (packageJson.devDependencies && packageJson.devDependencies[dep]) {
|
|
78
|
+
packageJson.devDependencies[dep] = `^${version}`;
|
|
79
|
+
}
|
|
80
|
+
if (packageJson.peerDependencies && packageJson.peerDependencies[dep]) {
|
|
81
|
+
packageJson.peerDependencies[dep] = `^${version}`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
85
|
+
}
|
|
86
|
+
getInternalDependencies(packageJson) {
|
|
87
|
+
const allDeps = [
|
|
88
|
+
...Object.keys(packageJson.dependencies || {}),
|
|
89
|
+
...Object.keys(packageJson.devDependencies || {}),
|
|
90
|
+
...Object.keys(packageJson.peerDependencies || {})
|
|
91
|
+
];
|
|
92
|
+
return allDeps.filter(dep => dep.startsWith('@ed/') || dep.startsWith('workspace:'));
|
|
93
|
+
}
|
|
94
|
+
async validateSync() {
|
|
95
|
+
const rootVersion = await this.versionManager.getCurrentVersion();
|
|
96
|
+
const issues = [];
|
|
97
|
+
for (const pkgPath of this.config.packages) {
|
|
98
|
+
const packageJsonPath = path.join(pkgPath, 'package.json');
|
|
99
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
100
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
101
|
+
if (packageJson.version !== rootVersion) {
|
|
102
|
+
issues.push(`${pkgPath}: version ${packageJson.version} does not match root ${rootVersion}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
valid: issues.length === 0,
|
|
108
|
+
issues
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.SyncManager = SyncManager;
|
|
113
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as semver from 'semver';
|
|
2
|
+
export interface VersionConfig {
|
|
3
|
+
rootPackageJson: string;
|
|
4
|
+
packages: string[];
|
|
5
|
+
changelogFile?: string;
|
|
6
|
+
conventionalCommits?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class VersionManager {
|
|
9
|
+
private config;
|
|
10
|
+
private git;
|
|
11
|
+
constructor(config: VersionConfig);
|
|
12
|
+
getCurrentVersion(): Promise<string>;
|
|
13
|
+
bumpVersion(releaseType: semver.ReleaseType, preRelease?: string): Promise<string>;
|
|
14
|
+
updateVersion(newVersion: string): Promise<void>;
|
|
15
|
+
private updatePackageJson;
|
|
16
|
+
createGitTag(version: string, message?: string): Promise<void>;
|
|
17
|
+
commitChanges(version: string): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=versioning.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.VersionManager = void 0;
|
|
40
|
+
const fs = __importStar(require("fs-extra"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const semver = __importStar(require("semver"));
|
|
43
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
44
|
+
class VersionManager {
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.git = (0, simple_git_1.default)();
|
|
47
|
+
this.config = {
|
|
48
|
+
changelogFile: 'CHANGELOG.md',
|
|
49
|
+
conventionalCommits: true,
|
|
50
|
+
...config
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async getCurrentVersion() {
|
|
54
|
+
const packageJson = await fs.readJson(this.config.rootPackageJson);
|
|
55
|
+
return packageJson.version;
|
|
56
|
+
}
|
|
57
|
+
async bumpVersion(releaseType, preRelease) {
|
|
58
|
+
const currentVersion = await this.getCurrentVersion();
|
|
59
|
+
const newVersion = preRelease
|
|
60
|
+
? semver.inc(currentVersion, releaseType, preRelease)
|
|
61
|
+
: semver.inc(currentVersion, releaseType);
|
|
62
|
+
if (!newVersion) {
|
|
63
|
+
throw new Error(`Invalid version bump: ${releaseType} from ${currentVersion}`);
|
|
64
|
+
}
|
|
65
|
+
await this.updateVersion(newVersion);
|
|
66
|
+
return newVersion;
|
|
67
|
+
}
|
|
68
|
+
async updateVersion(newVersion) {
|
|
69
|
+
// Update root package.json
|
|
70
|
+
await this.updatePackageJson(this.config.rootPackageJson, newVersion);
|
|
71
|
+
// Update all specified packages
|
|
72
|
+
for (const pkgPath of this.config.packages) {
|
|
73
|
+
const packageJsonPath = path.join(pkgPath, 'package.json');
|
|
74
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
75
|
+
await this.updatePackageJson(packageJsonPath, newVersion);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async updatePackageJson(packageJsonPath, version) {
|
|
80
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
81
|
+
packageJson.version = version;
|
|
82
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
83
|
+
}
|
|
84
|
+
async createGitTag(version, message) {
|
|
85
|
+
const tagMessage = message || `Release v${version}`;
|
|
86
|
+
await this.git.addAnnotatedTag(`v${version}`, tagMessage);
|
|
87
|
+
}
|
|
88
|
+
async commitChanges(version) {
|
|
89
|
+
const commitMessage = this.config.conventionalCommits
|
|
90
|
+
? `chore: release v${version}`
|
|
91
|
+
: `Release v${version}`;
|
|
92
|
+
await this.git.add('.');
|
|
93
|
+
await this.git.commit(commitMessage);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.VersionManager = VersionManager;
|
|
97
|
+
//# sourceMappingURL=versioning.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edcalderon/versioning",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "A comprehensive versioning and changelog management tool for monorepos",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ed-version": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"test:watch": "jest --watch",
|
|
14
|
+
"test:coverage": "jest --coverage",
|
|
15
|
+
"lint": "eslint src/**/*.ts",
|
|
16
|
+
"prepublishOnly": "npm run build && npm run test",
|
|
17
|
+
"create-tag": "node scripts/create-tag.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"versioning",
|
|
21
|
+
"changelog",
|
|
22
|
+
"monorepo",
|
|
23
|
+
"npm",
|
|
24
|
+
"conventional-commits"
|
|
25
|
+
],
|
|
26
|
+
"author": "Edward",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/fs-extra": "^11.0.4",
|
|
33
|
+
"@types/jest": "^29.5.12",
|
|
34
|
+
"@types/node": "^20.11.17",
|
|
35
|
+
"@types/semver": "^7.5.8",
|
|
36
|
+
"jest": "^29.7.0",
|
|
37
|
+
"ts-jest": "^29.1.2",
|
|
38
|
+
"typescript": "^5.3.3"
|
|
39
|
+
},
|
|
40
|
+
"jest": {
|
|
41
|
+
"testEnvironment": "node",
|
|
42
|
+
"testMatch": [
|
|
43
|
+
"**/__tests__/**/*.test.ts"
|
|
44
|
+
],
|
|
45
|
+
"collectCoverageFrom": [
|
|
46
|
+
"src/**/*.ts",
|
|
47
|
+
"!src/**/*.d.ts",
|
|
48
|
+
"!src/**/__tests__/**"
|
|
49
|
+
],
|
|
50
|
+
"setupFilesAfterEnv": [
|
|
51
|
+
"<rootDir>/src/__tests__/setup.ts"
|
|
52
|
+
],
|
|
53
|
+
"transform": {
|
|
54
|
+
"^.+\\.ts$": "ts-jest"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"commander": "^12.0.0",
|
|
59
|
+
"conventional-changelog": "^5.1.0",
|
|
60
|
+
"fs-extra": "^11.2.0",
|
|
61
|
+
"semver": "^7.6.0",
|
|
62
|
+
"simple-git": "^3.22.0"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18.0.0"
|
|
66
|
+
},
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "git+https://github.com/edcalderon/my-second-brain.git",
|
|
70
|
+
"directory": "packages/versioning"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
function createVersionTag() {
|
|
8
|
+
try {
|
|
9
|
+
// Get current version from package.json (go up two directories from scripts/)
|
|
10
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
11
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
12
|
+
const version = packageJson.version;
|
|
13
|
+
|
|
14
|
+
// Use versioning prefix to avoid conflicts with monorepo tags
|
|
15
|
+
const tagPrefix = 'versioning-v';
|
|
16
|
+
const fullTag = `${tagPrefix}${version}`;
|
|
17
|
+
|
|
18
|
+
// Check if tag already exists
|
|
19
|
+
try {
|
|
20
|
+
const result = execSync(`git tag -l "${fullTag}"`, { stdio: 'pipe' });
|
|
21
|
+
const output = result.toString().trim();
|
|
22
|
+
if (output === fullTag) {
|
|
23
|
+
console.log(`Tag ${fullTag} already exists`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
// Tag doesn't exist, continue
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Create annotated tag
|
|
31
|
+
const tagMessage = `Release @edcalderon/versioning v${version}`;
|
|
32
|
+
execSync(`git tag -a "${fullTag}" -m "${tagMessage}"`, { stdio: 'inherit' });
|
|
33
|
+
|
|
34
|
+
console.log(`Created tag ${fullTag}`);
|
|
35
|
+
|
|
36
|
+
// Push tag
|
|
37
|
+
execSync('git push origin --tags', { stdio: 'inherit' });
|
|
38
|
+
|
|
39
|
+
console.log(`Pushed tag ${fullTag} to remote`);
|
|
40
|
+
console.log(`\nš Tag ${fullTag} created and pushed!`);
|
|
41
|
+
console.log(`The NPM publish workflow will now run automatically.`);
|
|
42
|
+
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Error creating version tag:', error.message);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (require.main === module) {
|
|
50
|
+
createVersionTag();
|
|
51
|
+
}
|