Skip to content

Commit

Permalink
Update config, test normalizeConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
NullVoxPopuli committed Jan 28, 2024
1 parent cc99d25 commit 3eeb6cc
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 14 deletions.
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,32 @@ Example `.defragrc.yaml`
# to an exact version.
#
# Possible values:
# pinned
# patches
# minors
write-as: pinned
# Default assumes every package follows semver and
# is 100% safe to upgrade within semver ranges.
# pinned ( default )
# patches ( e.g.: ~1.0.0 )
# minors ( e.g.: ^1.0.0 )
write-as: pinned
# This whole object is optional,
# but if your monorepo has public libraries
# where you *need* wider ranges, that can be configured here
#
# overrides is an array of objects
overrides:
# path may be either a single glob or an array of glabs
- path:
- packages/*/addon/package.json
- packages/*/*/package.json
# for both devDependencies and dependencies
# in addition to the 3 global options,
# pinned, patches, and minors, you may also
# specify `false` to disable version re-writing entirely
# (which may be useful for some packages that do
# complex multi-version specifiers)
devDependencies: pinned
dependencies: minors

# Default assumes every package follows semver (minors) and
# is 100% safe to upgrade within those ranges.
#
# in practice, this is only true if all dependencies
# sharing those listed here do not use private APIs.
Expand Down
10 changes: 4 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { cosmiconfig } from 'cosmiconfig';
import debug from 'debug';
import { packageJson, project } from 'ember-apply';

import { injestDeps, updateManifestFor } from './utils.js';
import { injestDeps, normalizeConfig, updateManifestFor } from './utils.js';

const d = debug('defrag');
const configExplorer = cosmiconfig('defrag');
Expand All @@ -20,12 +20,10 @@ export default async function run() {
const projectResult = await getPackages(root);

/**
* @type {import('./types.ts').Config}
* @type {import('./types.ts').UserConfig}
*/
const config = {
'write-as': 'pinned',
...(configResult?.config || {}),
};
const userConfig = configResult?.config || {};
const config = normalizeConfig(userConfig);

d(`Resolved config:`);
d(config);
Expand Down
23 changes: 22 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@ import type { Package } from '@manypkg/get-packages';

export type Manifest = Package['packageJson'];

type Range = 'pinned' | 'minors' | 'patches';

export interface Config {
'write-as': 'pinned' | 'minors' | 'patches';
'write-as': Range;
'update-range': {
// list of names or globs to match packages against
'~': string[];
'^': string[];
// '>=': string[]
};
overrides: {
path: string[];
devDependencies: Range | false;
dependencies: Range | false;
}[]
}


export interface UserConfig {
'write-as'?: Range;
'update-range'?: {
'~'?: string[];
'^'?: string[];
};
overrides?: {
path: string | string[];
devDependencies?: Range | false;
dependencies?: Range | false;
}[]
}
88 changes: 88 additions & 0 deletions src/utils-normalizeConfig.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { describe, expect as e, it } from 'vitest';

import { normalizeConfig } from './utils.js';

const expect = e.soft;

describe('normalizeConfig', () => {
it('no passed config', () => {
expect(normalizeConfig()).toMatchInlineSnapshot(`
{
"overrides": [],
"update-range": {
"^": [],
"~": [],
},
"write-as": "pinned",
}
`);
});

it('overrides "write-as"', () => {
expect(normalizeConfig({ 'write-as': "minors" })).toMatchInlineSnapshot(`
{
"overrides": [],
"update-range": {
"^": [],
"~": [],
},
"write-as": "minors",
}
`);
});

it('specifies overrides', () => {
expect(normalizeConfig({
overrides: [
{
path: 'x/y/z',
devDependencies: false,
dependencies: false,
}
]
})).toMatchInlineSnapshot(`
{
"overrides": [
{
"dependencies": false,
"devDependencies": false,
"path": [
"x/y/z",
],
},
],
"update-range": {
"^": [],
"~": [],
},
"write-as": "pinned",
}
`);
});

it('specifies update-range', () => {
expect(normalizeConfig({
'update-range': {
'~': [
'ember-data',
],
'^': [
'@ember-data/*'
],
}
})).toMatchInlineSnapshot(`
{
"overrides": [],
"update-range": {
"^": [
"@ember-data/*",
],
"~": [
"ember-data",
],
},
"write-as": "pinned",
}
`);
});
});
37 changes: 37 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,43 @@ const DEFAULT_BUMP = '^';
/** @type {Map<string, Set<string>>} */
const DEPS = new Map();

/**
* @param {Partial<import('./types.ts').UserConfig>} [ userConfig ]
* @return {import('./types.ts').Config}
*/
export function normalizeConfig(userConfig) {
let config = userConfig || {};

let topLevel = {
'write-as': config['write-as'] || 'pinned',
};

/** @type {import('./types.ts').Config['overrides'] } */
const overrides =
config['overrides']?.map((override) => {
const defaultRange = topLevel['write-as'];
const pathsArray = Array.isArray(override.path)
? override.path
: [override.path];

return {
devDependencies: override['devDependencies'] ?? defaultRange,
dependencies: override['dependencies'] ?? defaultRange,
path: pathsArray,
};
}) || [];

return {
...topLevel,
'update-range': {
'~': [],
'^': [],
...config['update-range'],
},
overrides,
};
}

/**
* @private for testing only
*
Expand Down

0 comments on commit 3eeb6cc

Please sign in to comment.