diff --git a/.gitignore b/.gitignore index 49812c9..3d07e97 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ coverage cypress/screenshots/** cypress/videos/** storybook-static +.DS_Store diff --git a/package-lock.json b/package-lock.json index 9aba860..cb2cc47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vuesion", - "version": "5.0.0", + "version": "6.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vuesion", - "version": "5.0.0", + "version": "6.0.0", "license": "MIT", "dependencies": { "@pinia/nuxt": "0.4.6", @@ -45,7 +45,6 @@ "@vitejs/plugin-vue": "4.0.0", "@vitest/coverage-c8": "0.26.3", "@vuesion/storybook-theme-switcher": "4.0.0-beta.4", - "@vuesion/utils": "4.0.0-beta.4", "babel-loader": "9.1.0", "c8": "7.12.0", "concurrently": "7.6.0", @@ -55,6 +54,7 @@ "eslint-plugin-storybook": "0.6.8", "eslint-plugin-vue": "9.8.0", "flush-promises": "1.0.2", + "generate-changelog": "1.8.0", "happy-dom": "8.1.1", "html-webpack-plugin": "5.5.0", "husky": "8.0.2", @@ -9036,86 +9036,6 @@ "react": "*" } }, - "node_modules/@vuesion/utils": { - "version": "4.0.0-beta.4", - "resolved": "https://registry.npmjs.org/@vuesion/utils/-/utils-4.0.0-beta.4.tgz", - "integrity": "sha512-nXgZypeP68AaoH3n8OtE83Z5GkIgY9QFRDzUanBub2LB8PIgIPkcIge3UWR0rR8W/mKdNzMZwthcLH4YW5QVeQ==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "cross-spawn": "7.0.3" - } - }, - "node_modules/@vuesion/utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vuesion/utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@vuesion/utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@vuesion/utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@vuesion/utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@vuesion/utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@vueuse/core": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.9.0.tgz", @@ -17155,6 +17075,27 @@ "node": ">=10" } }, + "node_modules/generate-changelog": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/generate-changelog/-/generate-changelog-1.8.0.tgz", + "integrity": "sha512-msgpxeB75Ziyg3wGsZuPNl7c5RxChMKmYcAX5obnhUow90dBZW3nLic6nxGtst7Bpx453oS6zAIHcX7F3QVasw==", + "dev": true, + "dependencies": { + "bluebird": "^3.0.6", + "commander": "^2.9.0", + "github-url-from-git": "^1.4.0" + }, + "bin": { + "changelog": "bin/generate", + "generate-changelog": "bin/generate" + } + }, + "node_modules/generate-changelog/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -17341,6 +17282,12 @@ "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", "dev": true }, + "node_modules/github-url-from-git": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.5.0.tgz", + "integrity": "sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==", + "dev": true + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", diff --git a/package.json b/package.json index 8ab0161..5a8d271 100644 --- a/package.json +++ b/package.json @@ -35,13 +35,13 @@ "new:page": "hygen new page", "type-gen:swagger": "openapi-typescript https://petstore.swagger.io/v2/swagger.json --output src/interfaces/swagger.ts", "extract-i18n-messages": "ts-node ./tools/extract-i18n-messages.ts", - "test:watch": "cross-env NODE_ICU_DATA=node_modules/full-icu vuesion test --coverage --watch", + "test:watch": "cross-env NODE_ICU_DATA=node_modules/full-icu vitest", "e2e": "cypress run --headless", "lint": "eslint . --ext ts,vue --fix --cache && tsc --project ./tsconfig.json --noEmit", "storybook:build": "build-storybook", - "release:major": "vuesion release --major", - "release:minor": "vuesion release --minor", - "release:patch": "vuesion release --patch", + "release:major": "ts-node ./tools/release.ts --major", + "release:minor": "ts-node ./tools/release.ts --minor", + "release:patch": "ts-node ./tools/release.ts --patch", "build": "nuxt build", "build:analyze": "nuxt build --analyze", "build:spa": "nuxt generate", @@ -97,6 +97,7 @@ "eslint-plugin-storybook": "0.6.8", "eslint-plugin-vue": "9.8.0", "flush-promises": "1.0.2", + "generate-changelog": "1.8.0", "happy-dom": "8.1.1", "html-webpack-plugin": "5.5.0", "husky": "8.0.2", diff --git a/tools/extract-i18n-messages.ts b/tools/extract-i18n-messages.ts index dcb4574..bde6b9a 100644 --- a/tools/extract-i18n-messages.ts +++ b/tools/extract-i18n-messages.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ + import * as fs from 'fs'; import * as path from 'path'; import * as glob from 'glob'; diff --git a/tools/release.ts b/tools/release.ts new file mode 100644 index 0000000..ce5c406 --- /dev/null +++ b/tools/release.ts @@ -0,0 +1,52 @@ +/* eslint-disable no-console */ +import { runProcess } from './utils'; + +const versionArg = process.argv[2]; + +const run = async () => { + let npmVersion = 'major'; + + if (versionArg === '--minor') { + npmVersion = 'minor'; + } else if (versionArg === '--patch') { + npmVersion = 'patch'; + } + + console.log(`Releasing new ${npmVersion} version...`); + + try { + console.log('Generating CHANGELOG.md...'); + + await runProcess('changelog', [versionArg]); + + console.log('Adding CHANGELOG.md...'); + + await runProcess('git', ['add', 'CHANGELOG.md']); + + console.log('Running pre-commit hooks...'); + + await runProcess('git', ['commit', '-m', 'chore: update changelog']); + + console.log('Committing changes...'); + + console.log(`Releasing npm ${npmVersion} version...`); + + await runProcess('npm', ['version', npmVersion]); + + console.log('Pushing changes...'); + + await runProcess('git', ['push', 'origin']); + + console.log('Pushing tags...'); + + await runProcess('git', ['push', 'origin', '--tags']); + + console.log(''); + + console.log('New version released.'); + } catch (e) { + console.error(e); + } +}; + +run().catch((e) => console.log(e)); diff --git a/tools/utils.ts b/tools/utils.ts index 130f13c..f9b5478 100644 --- a/tools/utils.ts +++ b/tools/utils.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; +import { spawn, SpawnOptions } from 'child_process'; export const getTranslationsFromString = (content: string): RegExpMatchArray => { const result: any = []; @@ -61,4 +62,47 @@ export const ensureDirectoryExists = (filePath: string) => { fs.mkdirSync(dirname); }; +export interface IProcessOptions { + cwd?: string; + silent?: boolean; + debug?: boolean; +} + +export interface IProcessError { + code: number; + trace: string; +} + +export const runProcess = (name: string, args: string[] = [], options?: IProcessOptions): Promise => { + return new Promise((resolve: any, reject: any) => { + options = Object.assign({ cwd: process.cwd(), silent: false, debug: false }, options); + + const localOptions: SpawnOptions = Object.assign( + { + detached: false, + cwd: options.cwd, + env: process.env, + }, + options.silent === false || options.debug === true ? { stdio: 'inherit' as const } : {}, + ); + const childProcess: any = spawn(name, args, localOptions); + + childProcess.on('exit', (code: number) => { + childProcess.kill(); + + if (code === 0) { + resolve(undefined); + } else { + const err: IProcessError = { code, trace: '' }; + reject(err); + } + }); + + childProcess.on('error', (e: Error) => { + childProcess.kill(); + reject(e); + }); + }); +}; + /* c8 ignore end */