From ce8511f1d4baba5911399c596a2ee4766cbd048b Mon Sep 17 00:00:00 2001 From: Lucho Date: Fri, 26 Apr 2024 04:26:27 -0300 Subject: [PATCH 1/3] Upgrade command: Version prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When you create a new FoalTS project, all @foal dependencies begins with the '^' prefix. I think maybe it's a good idea to keep it. See the NPM docs and semver docs: ~version “Approximately equivalent to version”, will update you to all future patch versions, without incrementing the minor version. ~1.2.3 will use releases from 1.2.3 to <1.3.0. ^version “Compatible with version”, will update you to all future minor/patch versions, without incrementing the major version. ^1.2.3 will use releases from 1.2.3 to <2.0.0. --- packages/cli/src/generate/file-system.ts | 15 +++++++++------ .../cli/src/generate/generators/app/create-app.ts | 2 +- .../generators/upgrade/package-version-prefix.ts | 1 + .../generate/generators/upgrade/upgrade.spec.ts | 12 ++++++------ .../src/generate/generators/upgrade/upgrade.ts | 4 ++-- 5 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 packages/cli/src/generate/generators/upgrade/package-version-prefix.ts diff --git a/packages/cli/src/generate/file-system.ts b/packages/cli/src/generate/file-system.ts index 0256cfdd42..53ad1fe979 100644 --- a/packages/cli/src/generate/file-system.ts +++ b/packages/cli/src/generate/file-system.ts @@ -16,6 +16,9 @@ import { dirname, join, parse } from 'path'; // 3p import { cyan, green } from 'colors/safe'; +// npm +import { PackageVersionPrefix } from './generators/upgrade/package-version-prefix'; + function rmDirAndFiles(path: string) { const files = readdirSync(path); for (const file of files) { @@ -476,13 +479,13 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDependency(name: string, version: string): this { + setOrUpdateProjectDependency(name: string, version: string, prefix: PackageVersionPrefix): this { const initialCurrentDir = this.currentDir; this.cdProjectRootDir(); const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')); - pkg.dependencies[name] = version; + pkg.dependencies[name] = `${prefix}${version}`; writeFileSync(this.parse('package.json'), JSON.stringify(pkg, null, 2)); @@ -495,9 +498,9 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDependencyOnlyIf(condition: boolean, name: string, version: string): this { + setOrUpdateProjectDependencyOnlyIf(condition: boolean, name: string, version: string, prefix: PackageVersionPrefix): this { if (condition) { - this.setOrUpdateProjectDependency(name, version); + this.setOrUpdateProjectDependency(name, version, prefix); } return this; } @@ -523,13 +526,13 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDevDependency(name: string, version: string): this { + setOrUpdateProjectDevDependency(name: string, version: string, prefix: PackageVersionPrefix): this { const initialCurrentDir = this.currentDir; this.cdProjectRootDir(); const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')); - pkg.devDependencies[name] = version; + pkg.devDependencies[name] = `${prefix}${version}`; writeFileSync(this.parse('package.json'), JSON.stringify(pkg, null, 2)); diff --git a/packages/cli/src/generate/generators/app/create-app.ts b/packages/cli/src/generate/generators/app/create-app.ts index 203959fd0f..d28bc45d00 100644 --- a/packages/cli/src/generate/generators/app/create-app.ts +++ b/packages/cli/src/generate/generators/app/create-app.ts @@ -46,7 +46,7 @@ export async function createApp({ name, autoInstall, initRepo, mongodb = false, .copy('app/gitignore', '.gitignore') .renderOnlyIf(!mongodb, 'app/package.json', 'package.json', locals) .renderOnlyIf(mongodb, 'app/package.mongodb.json', 'package.json', locals) - .setOrUpdateProjectDependencyOnlyIf(yaml, 'yamljs', '~0.3.0') + .setOrUpdateProjectDependencyOnlyIf(yaml, 'yamljs', '0.3.0', '~') .copy('app/tsconfig.app.json', 'tsconfig.app.json') .copy('app/tsconfig.e2e.json', 'tsconfig.e2e.json') .copy('app/tsconfig.json', 'tsconfig.json') diff --git a/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts b/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts new file mode 100644 index 0000000000..f129f080fb --- /dev/null +++ b/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts @@ -0,0 +1 @@ +export type PackageVersionPrefix = '' | '^' | '~'; \ No newline at end of file diff --git a/packages/cli/src/generate/generators/upgrade/upgrade.spec.ts b/packages/cli/src/generate/generators/upgrade/upgrade.spec.ts index b252915533..55c3f6e461 100644 --- a/packages/cli/src/generate/generators/upgrade/upgrade.spec.ts +++ b/packages/cli/src/generate/generators/upgrade/upgrade.spec.ts @@ -19,8 +19,8 @@ describe('upgrade', () => { const actualDependencies = fs.getProjectDependencies(); const expectedDependencies = [ - { name: '@foal/core', version: '3.0.0' }, - { name: '@foal/foobar', version: '3.0.0' }, + { name: '@foal/core', version: '^3.0.0' }, + { name: '@foal/foobar', version: '^3.0.0' }, { name: 'another-dependency', version: '^1.0.0' } ]; deepStrictEqual(actualDependencies, expectedDependencies); @@ -34,7 +34,7 @@ describe('upgrade', () => { const actualDevDependencies = fs.getProjectDevDependencies(); const expectedDevDependencies = [ - { name: '@foal/cli', version: '3.0.0' }, + { name: '@foal/cli', version: '^3.0.0' }, { name: 'another-dependency2', version: '^2.0.0' } ]; deepStrictEqual(actualDevDependencies, expectedDevDependencies); @@ -50,8 +50,8 @@ describe('upgrade', () => { const actualDependencies = fs.getProjectDependencies(); const expectedDependencies = [ - { name: '@foal/core', version: '3.0.0' }, - { name: '@foal/foobar', version: '3.0.0' }, + { name: '@foal/core', version: '^3.0.0' }, + { name: '@foal/foobar', version: '^3.0.0' }, { name: 'another-dependency', version: '^1.0.0' } ]; deepStrictEqual(actualDependencies, expectedDependencies); @@ -65,7 +65,7 @@ describe('upgrade', () => { const actualDevDependencies = fs.getProjectDevDependencies(); const expectedDevDependencies = [ - { name: '@foal/cli', version: '3.0.0' }, + { name: '@foal/cli', version: '^3.0.0' }, { name: 'another-dependency2', version: '^2.0.0' } ]; deepStrictEqual(actualDevDependencies, expectedDevDependencies); diff --git a/packages/cli/src/generate/generators/upgrade/upgrade.ts b/packages/cli/src/generate/generators/upgrade/upgrade.ts index 1390ec8f36..b0b6dca96a 100644 --- a/packages/cli/src/generate/generators/upgrade/upgrade.ts +++ b/packages/cli/src/generate/generators/upgrade/upgrade.ts @@ -26,14 +26,14 @@ export async function upgrade( const dependencies = fs.getProjectDependencies(); for (const dependency of dependencies) { if (dependency.name.startsWith('@foal/')) { - fs.setOrUpdateProjectDependency(dependency.name, version); + fs.setOrUpdateProjectDependency(dependency.name, version, '^'); } } const devDependencies = fs.getProjectDevDependencies(); for (const devDependency of devDependencies) { if (devDependency.name.startsWith('@foal/')) { - fs.setOrUpdateProjectDevDependency(devDependency.name, version); + fs.setOrUpdateProjectDevDependency(devDependency.name, version, '^'); } } From 49a3ec5312353d4dab61fe43cf0b1ba0b4459f16 Mon Sep 17 00:00:00 2001 From: Lucho Date: Fri, 26 Apr 2024 05:35:04 -0300 Subject: [PATCH 2/3] Foal upgrade: refactor Now it keeps the package prefix. --- packages/cli/package.json | 4 +- packages/cli/src/generate/file-system.spec.ts | 24 +++---- packages/cli/src/generate/file-system.ts | 35 ++++++---- .../src/generate/generators/app/create-app.ts | 2 +- .../upgrade/package-version-prefix.ts | 1 - .../generate/generators/upgrade/upgrade.ts | 4 +- .../generate/utils/node-dependencies.spec.ts | 68 +++++++++++++++++++ .../src/generate/utils/node-dependencies.ts | 54 +++++++++++++++ 8 files changed, 163 insertions(+), 29 deletions(-) delete mode 100644 packages/cli/src/generate/generators/upgrade/package-version-prefix.ts create mode 100644 packages/cli/src/generate/utils/node-dependencies.spec.ts create mode 100644 packages/cli/src/generate/utils/node-dependencies.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index 27f546c506..f1c34fd0da 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -5,7 +5,7 @@ "main": "./lib/index.js", "types": "./lib/index.d.ts", "scripts": { - "test": "npm run test:generators && npm run test:run-script && npm run test:create-secret && npm run test:rmdir && npm run test:fs", + "test": "npm run test:generators && npm run test:run-script && npm run test:create-secret && npm run test:rmdir && npm run test:fs && npm run test:utils", "test:fs": "mocha --file \"./src/test.ts\" --require ts-node/register \"./src/generate/file-system.spec.ts\"", "dev:test:fs": "mocha --file \"./src/test.ts\" --require ts-node/register --watch --extension ts \"./src/generate/file-system.spec.ts\"", "test:generators": "mocha --file \"./src/test.ts\" --require ts-node/register \"./src/generate/generators/**/*.spec.ts\"", @@ -16,6 +16,8 @@ "dev:test:run-script": "mocha --file \"./src/test.ts\" --require ts-node/register --watch --extension ts \"./src/run-script/**/*.spec.ts\"", "test:create-secret": "mocha --file \"./src/test.ts\" --require ts-node/register \"./src/create-secret/**/*.spec.ts\"", "dev:test:create-secret": "mocha --file \"./src/test.ts\" --require ts-node/register --watch --extension ts \"./src/create-secret/**/*.spec.ts\"", + "test:utils": "mocha --file \"./src/test.ts\" --require ts-node/register \"./src/generate/utils/**/*.spec.ts\"", + "dev:test:utils": "mocha --file \"./src/test.ts\" --require ts-node/register --watch --extension ts \"./src/generate/utils/**/*.spec.ts\"", "build": "rimraf lib && tsc -p tsconfig-build.json && copyfiles -a -u 3 \"src/generate/templates/**/*\" lib/generate/templates", "prepublish": "npm run build" }, diff --git a/packages/cli/src/generate/file-system.spec.ts b/packages/cli/src/generate/file-system.spec.ts index e6d07d2683..e86ce843c9 100644 --- a/packages/cli/src/generate/file-system.spec.ts +++ b/packages/cli/src/generate/file-system.spec.ts @@ -952,11 +952,11 @@ describe('FileSystem', () => { }); it('should return itself.', () => { - strictEqual(fs.setOrUpdateProjectDependency('foo', '1.0.0'), fs); + strictEqual(fs.setOrUpdateProjectDependency('foo', '1.0.0', { prefix: '' }), fs); }); it('should add the dependency if it does not exist.', () => { - fs.setOrUpdateProjectDependency('foo', '1.0.0'); + fs.setOrUpdateProjectDependency('foo', '1.0.0', { prefix: '~' }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); @@ -964,18 +964,18 @@ describe('FileSystem', () => { deepStrictEqual(pkg.dependencies, { '@foal/core': '~1.0.1', 'bar': '~2.2.0', - 'foo': '1.0.0' + 'foo': '~1.0.0' }); }); it('should update the dependency if it already exists.', () => { - fs.setOrUpdateProjectDependency('@foal/core', '2.0.0'); + fs.setOrUpdateProjectDependency('@foal/core', '2.0.0', { prefix: '^', keepExistingPrefix: true }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); deepStrictEqual(pkg.dependencies, { - '@foal/core': '2.0.0', + '@foal/core': '~2.0.0', 'bar': '~2.2.0' }); @@ -1006,12 +1006,12 @@ describe('FileSystem', () => { }); it('should return itself.', () => { - strictEqual(fs.setOrUpdateProjectDependency('foo', '1.0.0'), fs); + strictEqual(fs.setOrUpdateProjectDependency('foo', '1.0.0', { prefix: '' }), fs); }); context('given the condition is true', () => { it('should add the dependency if it does not exist.', () => { - fs.setOrUpdateProjectDependencyOnlyIf(true, 'foo', '1.0.0'); + fs.setOrUpdateProjectDependencyOnlyIf(true, 'foo', '1.0.0', { prefix: '' }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); @@ -1026,7 +1026,7 @@ describe('FileSystem', () => { context('given the condition is false', () => { it('should not add the dependency if it does not exist.', () => { - fs.setOrUpdateProjectDependencyOnlyIf(false, 'foo', '1.0.0'); + fs.setOrUpdateProjectDependencyOnlyIf(false, 'foo', '1.0.0', { prefix: '' }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); @@ -1108,11 +1108,11 @@ describe('FileSystem', () => { }); it('should return itself.', () => { - strictEqual(fs.setOrUpdateProjectDevDependency('foo', '1.0.0'), fs); + strictEqual(fs.setOrUpdateProjectDevDependency('foo', '1.0.0', { prefix: '' }), fs); }); it('should add the dependency if it does not exist.', () => { - fs.setOrUpdateProjectDevDependency('foo', '1.0.0'); + fs.setOrUpdateProjectDevDependency('foo', '1.0.0', { prefix: '' }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); @@ -1125,13 +1125,13 @@ describe('FileSystem', () => { }); it('should update the dependency if it already exists.', () => { - fs.setOrUpdateProjectDevDependency('@foal/cli', '2.0.0'); + fs.setOrUpdateProjectDevDependency('@foal/cli', '2.0.0', { prefix: '', keepExistingPrefix: true }); const fileContent = readFileSync('package.json', 'utf8'); const pkg = JSON.parse(fileContent); deepStrictEqual(pkg.devDependencies, { - '@foal/cli': '2.0.0', + '@foal/cli': '~2.0.0', 'bar': '~2.2.0' }); diff --git a/packages/cli/src/generate/file-system.ts b/packages/cli/src/generate/file-system.ts index 53ad1fe979..cb8d331fd4 100644 --- a/packages/cli/src/generate/file-system.ts +++ b/packages/cli/src/generate/file-system.ts @@ -17,7 +17,7 @@ import { dirname, join, parse } from 'path'; import { cyan, green } from 'colors/safe'; // npm -import { PackageVersionPrefix } from './generators/upgrade/package-version-prefix'; +import { INpmPackage, IPrefixSettings, NodeDependencies } from './utils/node-dependencies'; function rmDirAndFiles(path: string) { const files = readdirSync(path); @@ -95,7 +95,7 @@ export class FileSystem { */ cdProjectRootDir(): this { // "/" on Unix, C:\ on Windows - const root = parse(process.cwd()).root; + const root = parse(process.cwd()).root; while (!this.exists('package.json')) { if (join(process.cwd(), this.parse('.')) === root) { @@ -479,13 +479,13 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDependency(name: string, version: string, prefix: PackageVersionPrefix): this { + setOrUpdateProjectDependency(name: string, version: string, prefixSettings: IPrefixSettings): this { const initialCurrentDir = this.currentDir; this.cdProjectRootDir(); - const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')); + const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')) as INpmPackage; - pkg.dependencies[name] = `${prefix}${version}`; + pkg.dependencies = this.setOrUpdate(pkg.dependencies, name, version, prefixSettings); writeFileSync(this.parse('package.json'), JSON.stringify(pkg, null, 2)); @@ -498,9 +498,9 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDependencyOnlyIf(condition: boolean, name: string, version: string, prefix: PackageVersionPrefix): this { + setOrUpdateProjectDependencyOnlyIf(condition: boolean, name: string, version: string, prefixSettings: IPrefixSettings): this { if (condition) { - this.setOrUpdateProjectDependency(name, version, prefix); + this.setOrUpdateProjectDependency(name, version, prefixSettings); } return this; } @@ -526,13 +526,13 @@ export class FileSystem { * * @returns {this} */ - setOrUpdateProjectDevDependency(name: string, version: string, prefix: PackageVersionPrefix): this { + setOrUpdateProjectDevDependency(name: string, version: string, prefixSettings: IPrefixSettings): this { const initialCurrentDir = this.currentDir; this.cdProjectRootDir(); - const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')); + const pkg = JSON.parse(readFileSync(this.parse('package.json'), 'utf8')) as INpmPackage; - pkg.devDependencies[name] = `${prefix}${version}`; + pkg.devDependencies = this.setOrUpdate(pkg.devDependencies, name, version, prefixSettings); writeFileSync(this.parse('package.json'), JSON.stringify(pkg, null, 2)); @@ -550,7 +550,7 @@ export class FileSystem { * @memberof FileSystem */ setUp(): void { - const [ firstDir ] = this.testDir.split('/'); + const [firstDir] = this.testDir.split('/'); mkdirSync(firstDir); mkdirSync(this.testDir); this.currentDir = ''; @@ -562,7 +562,7 @@ export class FileSystem { * @memberof FileSystem */ tearDown(): void { - const [ firstDir ] = this.testDir.split('/'); + const [firstDir] = this.testDir.split('/'); rmDirAndFiles(firstDir); this.currentDir = ''; @@ -670,6 +670,17 @@ export class FileSystem { return process.env.P1Z7kEbSUUPMxF8GqPwD8Gx_FOAL_CLI_TEST === 'true'; } + private setOrUpdate(dependencies: Record, name: string, version: string, prefixSettings: IPrefixSettings): Record { + const dependenciesManager = new NodeDependencies(dependencies); + + const defaultPrefix = prefixSettings.prefix; + const keepExistingPrefix = (prefixSettings.keepExistingPrefix === undefined || prefixSettings.keepExistingPrefix === true); + + dependenciesManager.setOrUpdate(name, version, defaultPrefix, keepExistingPrefix); + + return dependenciesManager.getDependencies(); + } + private parse(path: string) { if (this.isTestingEnvironment()) { return join(this.testDir, this.currentDir, path); diff --git a/packages/cli/src/generate/generators/app/create-app.ts b/packages/cli/src/generate/generators/app/create-app.ts index d28bc45d00..fd72d837d9 100644 --- a/packages/cli/src/generate/generators/app/create-app.ts +++ b/packages/cli/src/generate/generators/app/create-app.ts @@ -46,7 +46,7 @@ export async function createApp({ name, autoInstall, initRepo, mongodb = false, .copy('app/gitignore', '.gitignore') .renderOnlyIf(!mongodb, 'app/package.json', 'package.json', locals) .renderOnlyIf(mongodb, 'app/package.mongodb.json', 'package.json', locals) - .setOrUpdateProjectDependencyOnlyIf(yaml, 'yamljs', '0.3.0', '~') + .setOrUpdateProjectDependencyOnlyIf(yaml, 'yamljs', '0.3.0', { prefix: '~', keepExistingPrefix: false }) .copy('app/tsconfig.app.json', 'tsconfig.app.json') .copy('app/tsconfig.e2e.json', 'tsconfig.e2e.json') .copy('app/tsconfig.json', 'tsconfig.json') diff --git a/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts b/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts deleted file mode 100644 index f129f080fb..0000000000 --- a/packages/cli/src/generate/generators/upgrade/package-version-prefix.ts +++ /dev/null @@ -1 +0,0 @@ -export type PackageVersionPrefix = '' | '^' | '~'; \ No newline at end of file diff --git a/packages/cli/src/generate/generators/upgrade/upgrade.ts b/packages/cli/src/generate/generators/upgrade/upgrade.ts index b0b6dca96a..28fe9975fe 100644 --- a/packages/cli/src/generate/generators/upgrade/upgrade.ts +++ b/packages/cli/src/generate/generators/upgrade/upgrade.ts @@ -26,14 +26,14 @@ export async function upgrade( const dependencies = fs.getProjectDependencies(); for (const dependency of dependencies) { if (dependency.name.startsWith('@foal/')) { - fs.setOrUpdateProjectDependency(dependency.name, version, '^'); + fs.setOrUpdateProjectDependency(dependency.name, version, { prefix: '^', keepExistingPrefix: true }); } } const devDependencies = fs.getProjectDevDependencies(); for (const devDependency of devDependencies) { if (devDependency.name.startsWith('@foal/')) { - fs.setOrUpdateProjectDevDependency(devDependency.name, version, '^'); + fs.setOrUpdateProjectDevDependency(devDependency.name, version, { prefix: '^', keepExistingPrefix: true }); } } diff --git a/packages/cli/src/generate/utils/node-dependencies.spec.ts b/packages/cli/src/generate/utils/node-dependencies.spec.ts new file mode 100644 index 0000000000..b613370d6e --- /dev/null +++ b/packages/cli/src/generate/utils/node-dependencies.spec.ts @@ -0,0 +1,68 @@ +import { deepStrictEqual, strictEqual } from 'assert'; +import { INpmPackage, NodeDependencies } from './node-dependencies'; + +describe('NodeDependencies', () => { + let manager: NodeDependencies; + const npmPackage: INpmPackage = { + dependencies: { + '@foal/core': '^4.4.0', + 'foo': '1.1.0', + 'lat': 'latest' + }, + devDependencies: { + '@foal/cli': '^4.4.0' + } + }; + + it('should not affect the original npmPackage object', () => { + const dependenciesForTest = { ...npmPackage.devDependencies }; + + manager = new NodeDependencies(dependenciesForTest); + manager.setOrUpdate('mocha', '1.0.0', '^', true); + + deepStrictEqual(npmPackage.devDependencies, dependenciesForTest); + }); + + it('should keep the prefix if keepExistingPrefix is true', () => { + manager = new NodeDependencies(npmPackage.dependencies); + manager.setOrUpdate('@foal/core', '5.0.0', '', true); + + const result = manager.getDependencies()['@foal/core']; + const expected = '^5.0.0'; + + strictEqual(expected, result); + }); + + it('should override the prefix if keepExistingPrefix is true but the prefix is not supported', () => { + manager = new NodeDependencies(npmPackage.dependencies); + manager.setOrUpdate('lat', '5.0.0', '^', true); + + const result = manager.getDependencies()['lat']; + const expected = '^5.0.0'; + + strictEqual(expected, result); + }); + + it('should override the prefix if keepExistingPrefix is false', () => { + manager = new NodeDependencies(npmPackage.dependencies); + manager.setOrUpdate('@foal/core', '5.0.0', '', false); + + const result = manager.getDependencies()['@foal/core']; + const expected = '5.0.0'; + + strictEqual(expected, result); + }); + + it('should use the prefix if the package does not exists', () => { + manager = new NodeDependencies(npmPackage.dependencies); + manager.setOrUpdate('@foal/mongodb', '4.4.0', '^', true); + manager.setOrUpdate('@foal/password', '4.4.0', '^', false); + + const mongoPackage = manager.getDependencies()['@foal/mongodb']; + const passwordPackage = manager.getDependencies()['@foal/password']; + const expected = '^4.4.0'; + + strictEqual(expected, mongoPackage); + strictEqual(expected, passwordPackage); + }); +}); diff --git a/packages/cli/src/generate/utils/node-dependencies.ts b/packages/cli/src/generate/utils/node-dependencies.ts new file mode 100644 index 0000000000..5ce3fab937 --- /dev/null +++ b/packages/cli/src/generate/utils/node-dependencies.ts @@ -0,0 +1,54 @@ +export type NpmPackageVersionPrefix = '' | '^' | '~'; + +const supportedPrefixes = ['^', '~']; + +export interface INpmPackage { + dependencies: Record; + devDependencies: Record; +} + +export interface IPrefixSettings { + prefix: NpmPackageVersionPrefix; + keepExistingPrefix?: boolean; +} + +export class NodeDependencies { + private dependencies: Record; + + constructor(packageDependencies: Record) { + this.dependencies = { ...packageDependencies }; + } + + getDependencies(): Record { + return { ...this.dependencies }; + } + + /** + * Installs a dependency if it does not exists. + * Updates a dependency if it exists. + * @param name Dependency name. + * @param version New version. + * @param prefix New or default prefix. + * @param keepExistingPrefix Keeps the version prefix. + */ + setOrUpdate(name: string, version: string, prefix: string, keepExistingPrefix: boolean): void { + if (!this.exists(name) || !keepExistingPrefix) { + this.dependencies[name] = `${prefix}${version}`; + } + else if (this.isPrefixed(name)) { + const existingPrefix = this.dependencies[name][0]; + this.dependencies[name] = `${existingPrefix}${version}`; + } + else { + this.dependencies[name] = `${prefix}${version}`; + } + } + + private isPrefixed(name: string): boolean { + return supportedPrefixes.includes(this.dependencies[name][0]); + } + + private exists(name: string): boolean { + return !!this.dependencies[name]; + } +} \ No newline at end of file From 48a785671197e87baf5bf4ae9c939383712a99aa Mon Sep 17 00:00:00 2001 From: Lucho Date: Fri, 26 Apr 2024 05:57:47 -0300 Subject: [PATCH 3/3] Lint fix --- packages/cli/src/generate/utils/node-dependencies.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/generate/utils/node-dependencies.spec.ts b/packages/cli/src/generate/utils/node-dependencies.spec.ts index b613370d6e..c8dbee67d0 100644 --- a/packages/cli/src/generate/utils/node-dependencies.spec.ts +++ b/packages/cli/src/generate/utils/node-dependencies.spec.ts @@ -37,7 +37,7 @@ describe('NodeDependencies', () => { manager = new NodeDependencies(npmPackage.dependencies); manager.setOrUpdate('lat', '5.0.0', '^', true); - const result = manager.getDependencies()['lat']; + const result = manager.getDependencies().lat; const expected = '^5.0.0'; strictEqual(expected, result);