@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 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
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
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
@@ -0,0 +1,5 @@
1
+ export * from './versioning';
2
+ export * from './changelog';
3
+ export * from './sync';
4
+ export * from './release';
5
+ //# sourceMappingURL=index.d.ts.map
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
@@ -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
+ }