From 982cee4268abdf2592bccec7fe6aed8219a1eea3 Mon Sep 17 00:00:00 2001 From: Jamie Mason Date: Fri, 17 Feb 2023 20:01:40 +0000 Subject: [PATCH] docs(site): more progress adding documentation --- site/docs/{config-file.md => config-file.mdx} | 2 +- .../{custom-types.md => custom-types.mdx} | 14 +- site/docs/config/dependency-types.md | 81 ------- site/docs/config/dependency-types.mdx | 77 +++++++ site/docs/config/{filter.md => filter.mdx} | 6 +- site/docs/config/{indent.md => indent.mdx} | 6 +- .../{semver-groups.md => semver-groups.mdx} | 12 +- .../{semver-range.md => semver-range.mdx} | 10 +- site/docs/config/{sort-az.md => sort-az.mdx} | 2 + .../config/{sort-first.md => sort-first.mdx} | 2 + site/docs/config/{source.md => source.mdx} | 14 +- site/docs/config/version-groups.md | 150 ------------- site/docs/config/version-groups.mdx | 208 ++++++++++++++++++ .../{fix-mismatches.md => fix-mismatches.mdx} | 2 +- site/docs/{format.md => format.mdx} | 0 .../{github-action.md => github-action.mdx} | 0 site/docs/guide/version-groups.mdx | 86 ++++++++ site/docs/installation.md | 8 - site/docs/installation.mdx | 56 +++++ ...emver-ranges.md => lint-semver-ranges.mdx} | 2 +- ...list-mismatches.md => list-mismatches.mdx} | 2 +- site/docs/{list.md => list.mdx} | 0 site/docs/option/{config.md => config.mdx} | 2 +- site/docs/option/{filter.md => filter.mdx} | 2 +- site/docs/option/{indent.md => indent.mdx} | 2 +- site/docs/option/semver-range.md | 12 - site/docs/option/semver-range.mdx | 12 + site/docs/option/{source.md => source.mdx} | 2 +- site/docs/option/{types.md => types.mdx} | 4 +- ...semver-ranges.md => set-semver-ranges.mdx} | 2 +- site/docusaurus.config.js | 5 + site/sidebars.js | 1 + .../features}/index.tsx | 0 .../features}/styles.module.css | 0 site/src/components/homepage/header/index.tsx | 25 +++ .../homepage/header/styles.module.css | 18 ++ site/src/components/pill/index.tsx | 11 + site/src/components/pill/styles.module.css | 44 ++++ site/src/pages/index.module.css | 26 +-- site/src/pages/index.tsx | 45 ++-- site/src/pages/markdown-page.md | 7 - .../src/partials/default-dependency-types.mdx | 9 + site/static/img/favicon.ico | Bin 3626 -> 15406 bytes 43 files changed, 625 insertions(+), 344 deletions(-) rename site/docs/{config-file.md => config-file.mdx} (98%) rename site/docs/config/{custom-types.md => custom-types.mdx} (80%) delete mode 100644 site/docs/config/dependency-types.md create mode 100644 site/docs/config/dependency-types.mdx rename site/docs/config/{filter.md => filter.mdx} (76%) rename site/docs/config/{indent.md => indent.mdx} (87%) rename site/docs/config/{semver-groups.md => semver-groups.mdx} (86%) rename site/docs/config/{semver-range.md => semver-range.mdx} (72%) rename site/docs/config/{sort-az.md => sort-az.mdx} (96%) rename site/docs/config/{sort-first.md => sort-first.mdx} (91%) rename site/docs/config/{source.md => source.mdx} (84%) delete mode 100644 site/docs/config/version-groups.md create mode 100644 site/docs/config/version-groups.mdx rename site/docs/{fix-mismatches.md => fix-mismatches.mdx} (95%) rename site/docs/{format.md => format.mdx} (100%) rename site/docs/{github-action.md => github-action.mdx} (100%) create mode 100644 site/docs/guide/version-groups.mdx delete mode 100644 site/docs/installation.md create mode 100644 site/docs/installation.mdx rename site/docs/{lint-semver-ranges.md => lint-semver-ranges.mdx} (95%) rename site/docs/{list-mismatches.md => list-mismatches.mdx} (94%) rename site/docs/{list.md => list.mdx} (100%) rename site/docs/option/{config.md => config.mdx} (71%) rename site/docs/option/{filter.md => filter.mdx} (94%) rename site/docs/option/{indent.md => indent.mdx} (96%) delete mode 100644 site/docs/option/semver-range.md create mode 100644 site/docs/option/semver-range.mdx rename site/docs/option/{source.md => source.mdx} (88%) rename site/docs/option/{types.md => types.mdx} (88%) rename site/docs/{set-semver-ranges.md => set-semver-ranges.mdx} (95%) rename site/src/components/{HomepageFeatures => homepage/features}/index.tsx (100%) rename site/src/components/{HomepageFeatures => homepage/features}/styles.module.css (100%) create mode 100644 site/src/components/homepage/header/index.tsx create mode 100644 site/src/components/homepage/header/styles.module.css create mode 100644 site/src/components/pill/index.tsx create mode 100644 site/src/components/pill/styles.module.css delete mode 100644 site/src/pages/markdown-page.md create mode 100644 site/src/partials/default-dependency-types.mdx diff --git a/site/docs/config-file.md b/site/docs/config-file.mdx similarity index 98% rename from site/docs/config-file.md rename to site/docs/config-file.mdx index c242ffd4..27733bda 100644 --- a/site/docs/config-file.md +++ b/site/docs/config-file.mdx @@ -15,7 +15,7 @@ tree in the following places: - a `config.syncpack` property in `package.json` If you want to specify a path to a configuration file, overriding the discovered -configuration file (if present), you can use the [`--config`](./config-file.md) +configuration file (if present), you can use the [`--config`](./config-file.mdx) option. ## Default Configuration diff --git a/site/docs/config/custom-types.md b/site/docs/config/custom-types.mdx similarity index 80% rename from site/docs/config/custom-types.md rename to site/docs/config/custom-types.mdx index d72245f7..31953d8a 100644 --- a/site/docs/config/custom-types.md +++ b/site/docs/config/custom-types.mdx @@ -3,10 +3,12 @@ id: custom-types title: customTypes --- +# `customTypes` object + Extend syncpack to find and fix versions in your packages which are not available by default. Custom types behave like any other dependency, so can be -included in [versionGroups](./version-groups.md) or -[semverGroups](./semver-groups.md) etc. +included in [versionGroups](./version-groups.mdx) or +[semverGroups](./semver-groups.mdx) etc. The example below adds support for synchronising versions found in: @@ -36,10 +38,10 @@ The example below adds support for synchronising versions found in: The key of each custom type is its name, this can be used in the following places to toggle when it is enabled: -1. [`--types`](../option/types.md) and - [`dependencyTypes`](./dependency-types.md). -1. [`versionGroup.dependencyTypes`](./version-groups.md#dependencytypes) -1. [`semverGroup.dependencyTypes`](./semver-groups.md#dependencytypes) +1. [`--types`](../option/types.mdx) and + [`dependencyTypes`](./dependency-types.mdx). +1. [`versionGroup.dependencyTypes`](./version-groups.mdx#dependencytypes) +1. [`semverGroup.dependencyTypes`](./semver-groups.mdx#dependencytypes) ## customTypes\[name\].path diff --git a/site/docs/config/dependency-types.md b/site/docs/config/dependency-types.md deleted file mode 100644 index dd15c990..00000000 --- a/site/docs/config/dependency-types.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -id: dependency-types -title: dependencyTypes ---- - -All of the [default dependency types](#dependency-types) are enabled by default, -but can be reduced to a smaller list via the `dependencyTypes` property of your -config file. - -In this example, only dependencies found in the -[`dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#dependencies) -and -[`devDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#devDependencies) -properties of package.json files will be inspected by syncpack: - -```json -{ - "dependencyTypes": ["dev", "prod"] -} -``` - -:::tip - -The [default dependency types](#dependency-types) can be extended with your own -[`customTypes`](./custom-types.md), so you can find and fix versions found in -other parts of your package.json files. - -::: - -:::info - -Your `dependencyTypes` configuration in your [config file](../config-file.md) -can be overridden on an ad hoc basis using the [`--types`](../option/types.md) -option. - -::: - -## Default dependency types - -| Value | Property in package.json | -| --------------- | ------------------------------------------------------------------------------------------------- | -| `dev` | [`devDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#devDependencies) | -| `overrides` | [`overrides`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides) | -| `peer` | [`peerDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#peerDependencies) | -| `pnpmOverrides` | [`pnpm.overrides`](https://pnpm.io/package_json#pnpmoverrides) | -| `prod` | [`dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#dependencies) | -| `resolutions` | [`resolutions`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#resolutions) | -| `workspace` | [`version`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#version) | - -## The `workspace` type - -This option synchronises the versions of your dependencies with the -[`version`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#version) -properties of the package.json files developed in your own local -workspace/project, when they relate to eachother. - -Take this example, `@your-repo/fetch` is developed in your repo: - -```jsonc -{ - "name": "@your-repo/fetch", - "version": "1.0.2" - // ...rest of the file -} -``` - -and another package developed in your repo depends on it: - -```jsonc -{ - "name": "@your-repo/ui", - // ...other stuff - "dependencies": { - "@your-repo/fetch": "0.9.4" - } - // ...rest of the file -} -``` - -When `workspace` is enabled, syncpack will fix `@your-repo/ui` so it depends on -version `1.0.2` of `@your-repo/fetch`. diff --git a/site/docs/config/dependency-types.mdx b/site/docs/config/dependency-types.mdx new file mode 100644 index 00000000..244673e9 --- /dev/null +++ b/site/docs/config/dependency-types.mdx @@ -0,0 +1,77 @@ +--- +id: dependency-types +title: dependencyTypes +--- + +import DefaultDependencyTypes from '@site/src/partials/default-dependency-types.mdx'; + +# `dependencyTypes` string[] + +All of the [default dependency types](#default-dependency-types) are enabled by +default, but can be reduced to a smaller list via the `dependencyTypes` property +of your config file. + +In this example, only dependencies found in the +[`dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#dependencies) +and +[`devDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#devDependencies) +properties of package.json files will be inspected by syncpack: + +```json +{ + "dependencyTypes": ["dev", "prod"] +} +``` + +:::tip + +The [default dependency types](#default-dependency-types) can be extended with +your own [`customTypes`](./custom-types.mdx), so you can find and fix versions +found in other parts of your package.json files. + +::: + +:::info + +Your `dependencyTypes` configuration in your [config file](../config-file.mdx) +can be overridden on an ad hoc basis using the [`--types`](../option/types.mdx) +option. + +::: + +## Default dependency types + + + +## The `workspace` type + +This option synchronises the versions of your dependencies with the +[`version`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#version) +properties of the package.json files developed in your own local +workspace/project, when they relate to eachother. + +Take this example, `@your-repo/fetch` is developed in your repo: + +```jsonc +{ + "name": "@your-repo/fetch", + "version": "1.0.2" + // ...rest of the file +} +``` + +and another package developed in your repo depends on it: + +```jsonc +{ + "name": "@your-repo/ui", + // ...other stuff + "dependencies": { + "@your-repo/fetch": "0.9.4" + } + // ...rest of the file +} +``` + +When `workspace` is enabled, syncpack will fix `@your-repo/ui` so it depends on +version `1.0.2` of `@your-repo/fetch`. diff --git a/site/docs/config/filter.md b/site/docs/config/filter.mdx similarity index 76% rename from site/docs/config/filter.md rename to site/docs/config/filter.mdx index 4b672f5c..3ee05612 100644 --- a/site/docs/config/filter.md +++ b/site/docs/config/filter.mdx @@ -3,6 +3,8 @@ id: filter title: filter --- +# `filter` string[] + A string which will be passed to `new RegExp()` to match against package names that should be included. @@ -12,7 +14,7 @@ that should be included. line to filter the output of `syncpack list`, **it is not recommended to add this to your config file to manage your project more generally**. -Instead use [`versionGroups`](./version-groups.md) and/or -[`semverGroups`](./semver-groups.md). +Instead use [`versionGroups`](./version-groups.mdx) and/or +[`semverGroups`](./semver-groups.mdx). ::: diff --git a/site/docs/config/indent.md b/site/docs/config/indent.mdx similarity index 87% rename from site/docs/config/indent.md rename to site/docs/config/indent.mdx index 905ce71d..9887054e 100644 --- a/site/docs/config/indent.md +++ b/site/docs/config/indent.mdx @@ -3,6 +3,8 @@ id: indent title: indent --- +# `indent` string + The character(s) to be used to indent your package.json files when writing to disk. @@ -14,8 +16,8 @@ disk. :::info -The `indent` configuration in your [config file](../config-file.md) can be -overridden on an ad hoc basis using the [`--indent`](../option/indent.md) +The `indent` configuration in your [config file](../config-file.mdx) can be +overridden on an ad hoc basis using the [`--indent`](../option/indent.mdx) option. ::: diff --git a/site/docs/config/semver-groups.md b/site/docs/config/semver-groups.mdx similarity index 86% rename from site/docs/config/semver-groups.md rename to site/docs/config/semver-groups.mdx index 65dca96f..871cfe37 100644 --- a/site/docs/config/semver-groups.md +++ b/site/docs/config/semver-groups.mdx @@ -3,6 +3,8 @@ id: semver-groups title: semverGroups --- +# `semverGroups` object[] + Allow some packages to have different semver range rules to the rest of your monorepo. Each dependency can only belong to one semver group, the first rule which matches a given dependency and package will apply. @@ -91,23 +93,23 @@ and peer dependencies can be broader. ## `semverGroup.range` -Which of the [Supported Ranges](./semver-range.md#supported-ranges) this group +Which of the [Supported Ranges](./semver-range.mdx#supported-ranges) this group should use. ## `semverGroup.dependencies` Works the same as -[`versionGroup.dependencies`](./version-groups.md#dependencies). +[`versionGroup.dependencies`](./version-groups.mdx#dependencies). ## `semverGroup.isIgnored` -Works the same as [`versionGroup.isIgnored`](./version-groups.md#isignored). +Works the same as [`versionGroup.isIgnored`](./version-groups.mdx#isignored). ## `semverGroup.packages` -Works the same as [`versionGroup.packages`](./version-groups.md#packages). +Works the same as [`versionGroup.packages`](./version-groups.mdx#packages). ## `semverGroup.dependencyTypes` Works the same as -[`versionGroup.dependencyTypes`](./version-groups.md#dependencytypes). +[`versionGroup.dependencyTypes`](./version-groups.mdx#dependencytypes). diff --git a/site/docs/config/semver-range.md b/site/docs/config/semver-range.mdx similarity index 72% rename from site/docs/config/semver-range.md rename to site/docs/config/semver-range.mdx index fc0ea878..36b38e38 100644 --- a/site/docs/config/semver-range.md +++ b/site/docs/config/semver-range.mdx @@ -3,6 +3,8 @@ id: semver-range title: semverRange --- +# `semverRange` string + The semver range to be used consistently throughout your monorepo. ## Default Value @@ -19,16 +21,16 @@ loose ranges. :::tip If you want to use different ranges in different packages and/or types of -dependencies, you can use [`semverGroups`](./semver-groups.md) to partition your -repo into different sets of rules. +dependencies, you can use [`semverGroups`](./semver-groups.mdx) to partition +your repo into different sets of rules. ::: :::info -The `semverRange` configuration in your [config file](../config-file.md) can be +The `semverRange` configuration in your [config file](../config-file.mdx) can be overridden on an ad hoc basis using the -[`--semver-range`](../option/semver-range.md) option. +[`--semver-range`](../option/semver-range.mdx) option. ::: diff --git a/site/docs/config/sort-az.md b/site/docs/config/sort-az.mdx similarity index 96% rename from site/docs/config/sort-az.md rename to site/docs/config/sort-az.mdx index 14ff127d..ccc3b5cb 100644 --- a/site/docs/config/sort-az.md +++ b/site/docs/config/sort-az.mdx @@ -3,6 +3,8 @@ id: sort-az title: sortAz --- +# `sortAz` string[] + When using the `format` command, determines which fields within package.json files should be sorted alphabetically. When the value is an Object, its keys are sorted alphabetically. When the value is an Array, its values are sorted diff --git a/site/docs/config/sort-first.md b/site/docs/config/sort-first.mdx similarity index 91% rename from site/docs/config/sort-first.md rename to site/docs/config/sort-first.mdx index d4a4a1c6..fa261bd7 100644 --- a/site/docs/config/sort-first.md +++ b/site/docs/config/sort-first.mdx @@ -3,6 +3,8 @@ id: sort-first title: sortFirst --- +# `sortFirst` string[] + When using the `format` command, determines which fields within package.json files should appear at the top, and in what order. diff --git a/site/docs/config/source.md b/site/docs/config/source.mdx similarity index 84% rename from site/docs/config/source.md rename to site/docs/config/source.mdx index ca603164..009aca3c 100644 --- a/site/docs/config/source.md +++ b/site/docs/config/source.mdx @@ -3,6 +3,8 @@ id: source title: source --- +# `source` string[] + Patterns supported by [glob](https://github.com/isaacs/node-glob) to find package.json files you want to manage with syncpack. @@ -31,13 +33,17 @@ package.json files are resolved in this order of precendence: `./pnpm-workspace.yaml`. 5. Default to `'package.json'` and `'packages/*/package.json'`. -> 👋 Always add quotes around your `--source` patterns -> [[more info](https://github.com/JamieMason/syncpack/issues/66#issuecomment-1146011769)]. +:::tip + +Always add quotes around your `--source` patterns +[[more info](https://github.com/JamieMason/syncpack/issues/66#issuecomment-1146011769)]. + +::: :::info -Your `source` configuration in your [config file](../config-file.md) can be -overridden on an ad hoc basis using multiple [`--source`](../option/source.md) +Your `source` configuration in your [config file](../config-file.mdx) can be +overridden on an ad hoc basis using multiple [`--source`](../option/source.mdx) options – one for each glob pattern. ::: diff --git a/site/docs/config/version-groups.md b/site/docs/config/version-groups.md deleted file mode 100644 index 19bfe836..00000000 --- a/site/docs/config/version-groups.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -id: version-groups -title: versionGroups ---- - -The most common use case for version groups is when some of the packages in your -Monorepo are considered alpha (or legacy). Since those packages are much further -ahead (or behind) the other packages, the dependencies within those packages -need to be managed differently to the rest of the Monorepo. - -Your alpha packages might use unstable versions of some dependencies, while the -rest of the repo might need to remain on stable versions. - -You don't want mismatches within your alpha packages, you don't want mismatches -within the other packages, but you _do_ want those groups to use different -versions _to each other_ and not have `syncpack` make them all the same. - -In the following example, 2 of our packages are using different versions of -`react` and `react-dom` to the rest of the project. - -```json -{ - "versionGroups": [ - { - "dependencies": ["react", "react-dom"], - "packages": ["@alpha/server", "@alpha/ui"] - } - ] -} -``` - -> 👋 The `dependencies` and `packages` fields are processed using -> [minimatch](https://github.com/isaacs/minimatch), so the above example can -> also be written as `"packages": ["@alpha/**"]`. - -`syncpack` will make ensure that: - -- The versions of `react` and `react-dom` are the same within `@alpha/server` - and `@alpha/ui`. -- The versions of `react` and `react-dom` are the same across every package - except `@alpha/server` and `@alpha/ui`. -- The versions of `react` and `react-dom` within `@alpha/server` and `@alpha/ui` - can be different to the other packages in the monorepo. -- The versions of every other dependency in the monorepo (eg `lodash`) are the - same across every package including `@alpha/server` and `@alpha/ui`. - -Each dependency can only belong to one version group, the first rule which -matches a given dependency and package will apply. - -You can be quite granular with these rules, so the partitioning doesn't _have_ -to apply to an entire package: - -- A specific dependency in a specific package. -- A specific dependency in some specific packages only. -- Any dependency who name matches a pattern such as `@aws-sdk/**`. - -See [`semverGroups`](./semver-groups.md) for more examples, they work the same -way. - -## versionGroup.dependencies - -Required. An array of minimatch glob patterns which should match the key of -dependencies defined in your package.json files. - -| Pattern | Matches | -| ------------------------ | ---------------------------------------- | -| `["**"]` | Any dependency | -| `["@aws-sdk/**"]` | Any dependency with the scope `@aws-sdk` | -| `["react", "react-dom"]` | Specific dependencies by name | - -## versionGroup.packages - -Required. An array of minimatch glob patterns which should match the `name` -property of packages developed within your monorepo. - -| Pattern | Matches | -| ---------------------------- | ------------------------------------- | -| `["**"]` | Any package | -| `["@my-repo/**"]` | Any package with the scope `@my-repo` | -| `["my-server", "my-client"]` | Specific packages by name | - -## versionGroup.dependencyTypes - -Optional. If set, will result in only the dependency types included in that -array being considered a match for this version group. - -In this example we define that all dependencies within `peerDependencies` in the -repo must match, regardless of what versions of the same dependencies might be -used in `dependencies` or `devDependencies`. - -```json -{ - "versionGroups": [ - { - "dependencies": ["**"], - "dependencyTypes": ["peerDependencies"], - "packages": ["**"] - } - ] -} -``` - -## versionGroup.isBanned - -Remove dependencies which you've decided should never be allowed. - -```json -{ - "versionGroups": [ - { - "dependencies": ["never-gonna"], - "isBanned": true, - "packages": ["**"] - } - ] -} -``` - -## versionGroup.isIgnored - -Have syncpack ignore these dependencies completely. - -```json -{ - "versionGroups": [ - { - "dependencies": ["**"], - "isIgnored": true, - "packages": ["oops-moment", "workaround"] - } - ] -} -``` - -## versionGroup.pinVersion - -Pin the version of all dependencies in this group to match this specific version -you've defined. - -```json -{ - "versionGroups": [ - { - "dependencies": ["@aws-sdk/**"], - "packages": ["**"], - "pinVersion": "3.55.0" - } - ] -} -``` diff --git a/site/docs/config/version-groups.mdx b/site/docs/config/version-groups.mdx new file mode 100644 index 00000000..9f44cbbf --- /dev/null +++ b/site/docs/config/version-groups.mdx @@ -0,0 +1,208 @@ +--- +id: version-groups +title: versionGroups +--- + +import Pills from '@site/src/components/pill'; +import DefaultDependencyTypes from '@site/src/partials/default-dependency-types.mdx'; + +# `versionGroups` object[] + +:::info + +Learn more in our [guide to Version Groups](../guide/version-groups.mdx) + +::: + +## `packages` string[] + + + +An array of strings which should match the `name` properties of your +package.json files. This is used in combination with the +[`dependencies`](#dependencies-string) property to determine which dependencies +should belong to this version group. + +The strings can any combination of exact matches or +[minimatch](https://github.com/isaacs/minimatch) glob patterns: + +```json +// match any package +["**"] + +// match any package with a certain scope +["@my-repo/**"] + +// match specific packages by name +["my-server", "my-client"] +``` + +## `dependencies` string[] + + + +An array of strings which should match the names of dependencies you've +installed or otherwise referenced in your package.json files. This is used in +combination with the [`packages`](#packages-string) property to determine which +dependencies should belong to this version group. + +```json title="Example of which strings are matched against" +{ + "name": "not-here", + "dependencies": { "HERE": "0.0.0" }, + "devDependencies": { "HERE": "0.0.0" }, + "overrides": { "HERE": "0.0.0" }, + "peerDependencies": { "HERE": "0.0.0" }, + "pnpm": { "overrides": { "HERE": "0.0.0" } }, + "resolutions": { "HERE": "0.0.0" } +} +``` + +The strings can any combination of exact matches or +[minimatch](https://github.com/isaacs/minimatch) glob patterns: + +```json title="Examples of valid values" +// match any dependency +["**"] + +// match all dependencies with a certain scope +["@aws-sdk/**"] + +// match specific dependencies by name +["react", "react-dom"] +``` + +:::tip + +You can extend syncpack to look in more places by defining your own +[`customTypes`](./custom-types.mdx). If you do that, then the names of any +dependencies found by your `customTypes` can also be targeted using this field. + +::: + +## `dependencyTypes` string[] + + + +Can be used in combination with the [`packages`](#packages-string) and +[`dependencies`](#dependencies-string) properties to narrow further which +dependencies should belong to this version group. When set, only dependencies +present in the named locations will be considered a match for this version +group. + +The possible values available by default are in the table below: + + + +:::tip + +If you define your own [`customTypes`](./custom-types.mdx), their names can also +be used in addition to those in the table above. + +::: + +In this example we define that all dependencies within `peerDependencies` in the +repo must use `"*"` as its version number, regardless of what versions of the +same dependencies might be used in `dependencies` or `devDependencies`. + +```json title="Ensure peerDependencies always use *" +{ + "versionGroups": [ + { + "packages": ["**"], + "dependencies": ["**"], + "dependencyTypes": ["peer"], + "pinVersion": "*" + } + ] +} +``` + +## `label` string + + + +A short name or description to be displayed in a header in syncpack's output, +above the dependencies which matched this group. If a `label` is not set, then +the order which this group appears in your config will be used instead. + +```json title="Example where a label is used to give context to other Devs" +{ + "versionGroups": [ + { + "label": "AWS dependencies must all share the same version", + "packages": ["**"], + "dependencies": ["@aws-sdk/**"], + "pinVersion": "3.272.0" + } + ] +} +``` + +## `isBanned` boolean + + + +Remove dependencies which you've decided should never be used. + +```json title="Completely ban a dependency from being used anywhere" +{ + "versionGroups": [ + { + "packages": ["**"], + "dependencies": ["never-gonna"], + "isBanned": true + } + ] +} +``` + +```json title="Ban a dependency from being used in production" +{ + "versionGroups": [ + { + "packages": ["my-fast-ui"], + "dependencies": ["huge-filesize-party"], + "dependencyTypes": ["prod"], + "isBanned": true + } + ] +} +``` + +## `isIgnored` boolean + + + +Have syncpack ignore these dependencies completely. + +```json title="Hide dependencies from syncpack" +{ + "versionGroups": [ + { + "packages": ["oops-moment", "workaround"], + "dependencies": ["**"], + "isIgnored": true + } + ] +} +``` + +## `pinVersion` string + + + +Pin the version of all dependencies in this group to match this specific version +you've defined. + +```json title="Ensure AWS dependencies always have the same version" +{ + "versionGroups": [ + { + "dependencies": ["@aws-sdk/**"], + "packages": ["**"], + "pinVersion": "3.272.0" + } + ] +} +``` diff --git a/site/docs/fix-mismatches.md b/site/docs/fix-mismatches.mdx similarity index 95% rename from site/docs/fix-mismatches.md rename to site/docs/fix-mismatches.mdx index 55741f9f..76976aac 100644 --- a/site/docs/fix-mismatches.md +++ b/site/docs/fix-mismatches.mdx @@ -7,7 +7,7 @@ Ensure that multiple packages requiring the same dependency define the same version, so that every package requires eg. `react@16.4.2`, instead of a combination of `react@16.4.2`, `react@0.15.9`, and `react@16.0.0`. -See [`versionGroups`](./config/version-groups.md) if you have advanced +See [`versionGroups`](./config/version-groups.mdx) if you have advanced requirements. ## CLI Options diff --git a/site/docs/format.md b/site/docs/format.mdx similarity index 100% rename from site/docs/format.md rename to site/docs/format.mdx diff --git a/site/docs/github-action.md b/site/docs/github-action.mdx similarity index 100% rename from site/docs/github-action.md rename to site/docs/github-action.mdx diff --git a/site/docs/guide/version-groups.mdx b/site/docs/guide/version-groups.mdx new file mode 100644 index 00000000..e180ff17 --- /dev/null +++ b/site/docs/guide/version-groups.mdx @@ -0,0 +1,86 @@ +--- +id: version-groups +title: Version Groups +--- + +import Pills from '@site/src/components/pill'; +import DefaultDependencyTypes from '@site/src/partials/default-dependency-types.mdx'; + +:::info + +See also the [versionGroups Configuration API](../config/version-groups.mdx). + +::: + +## Overview + +Syncpack helps you find and fix inconsistencies between every dependency defined +throughout your monorepo's package.json files. Version Groups create partitions +where dependencies inside each group can be internally consistent, without +affecting the other groups. + +Version Groups let you handle special cases or provide more specific rules for +what to do in certain situations. + +They're best understood by looking at some example use cases. + +## Example use cases + +### Incompatible packages using the same framework + +A 3rd party framework has had a major update which requires breaking changes but +some of your packages can't easily be upgraded and will need to remain on an +older version, while the rest are able to upgrade today. + +1. You **don't** want mismatches between your packages using the latest version + of the framework - they should all use eg. `next@13.1.6` and `react@18.2.0`. +1. You **don't** want mismatches between the packages using the old version - + they should all use eg. `next@11.1.4` and `react@17.0.2`. +1. You **do** want those groups to use **different versions to each other** and + not have Syncpack make them all the same. +1. You only have this problem with `next` and `react`, other dependencies can + continue to be kept consistent with each other throughout the full monorepo. + +```json title="Allow different versions of just these dependencies, in these packages only" +{ + "versionGroups": [ + { + "dependencies": ["next", "react", "react-dom"], + "packages": ["@stricken/server", "@stricken/ui"], + "label": "These packages are stuck on next@11 for now" + } + ] +} +``` + +:::note + +Syncpack will make ensure that: + +1. The versions of `next` and `react` are the same between `@stricken/server` + and `@stricken/ui`. +1. The versions of `next` and `react` are the same across every package + **except** `@stricken/server` and `@stricken/ui`. +1. The versions of `next` and `react` between `@stricken/server` and + `@stricken/ui` can be different to the other packages in the monorepo. +1. The versions of every **other** dependency in the monorepo (eg `lodash`) are + the same across every package **including** `@stricken/server` and + `@stricken/ui`. + +::: + +## How groups are assigned + +Each dependency can only belong to one version group, the first group which +matches a given dependency will apply. + +You can be quite granular with these rules, so the partitioning doesn't _have_ +to apply to an entire package: + +- A specific dependency in a specific part of a specific package. +- A specific dependency in a specific package. +- A specific dependency in some specific packages only. +- Any dependency who name matches a pattern such as `@aws-sdk/**`. + +See [`semverGroups`](../config/semver-groups.mdx) for more examples, they work +the same way. diff --git a/site/docs/installation.md b/site/docs/installation.md deleted file mode 100644 index a954051c..00000000 --- a/site/docs/installation.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: installation -title: Installation ---- - -```bash -npm install --save-dev syncpack -``` diff --git a/site/docs/installation.mdx b/site/docs/installation.mdx new file mode 100644 index 00000000..1faaa355 --- /dev/null +++ b/site/docs/installation.mdx @@ -0,0 +1,56 @@ +--- +id: installation +title: Installation +--- + +Syncpack is a +[Command Line Application](https://en.wikipedia.org/wiki/Console_application) +run from your Terminal. + +## Global Install + +Installing syncpack globally on your system let's you easily use it on any of +the projects on your machine: + +```bash +npm install --global syncpack +``` + +### Usage + +```bash +syncpack --help +``` + +## Project Install + +Adding syncpack to your project as a dev dependency ensures that everyone on +your team will use the same version. + +```bash +npm install --save-dev syncpack +``` + +### Usage + +When installed into your project, it can be run via your project's Package +Manager. + +| Package Manager | Command | +| --------------- | ----------------------------- | +| npm | `npm exec syncpack -- --help` | +| pnpm | `pnpm syncpack --help` | +| yarn | `yarn syncpack --help` | + +## Run Remotely + +[npx](https://docs.npmjs.com/cli/v9/commands/npx?v=true) comes installed with +[npm](https://docs.npmjs.com/cli/v9/commands) and allows you to install and run +any CLI application in the npm registry on the fly. + +Just run the following command from the root directory of your project to use +syncpack any time. + +```bash +npx syncpack --help +``` diff --git a/site/docs/lint-semver-ranges.md b/site/docs/lint-semver-ranges.mdx similarity index 95% rename from site/docs/lint-semver-ranges.md rename to site/docs/lint-semver-ranges.mdx index 1ae8678d..7ecb6671 100644 --- a/site/docs/lint-semver-ranges.md +++ b/site/docs/lint-semver-ranges.mdx @@ -6,7 +6,7 @@ title: lint-semver-ranges Check whether dependency versions used within "dependencies", "devDependencies" etc follow a consistent format. -See [`semverGroups`](./config/semver-groups.md) if you have advanced +See [`semverGroups`](./config/semver-groups.mdx) if you have advanced requirements. ## CLI Options diff --git a/site/docs/list-mismatches.md b/site/docs/list-mismatches.mdx similarity index 94% rename from site/docs/list-mismatches.md rename to site/docs/list-mismatches.mdx index c0a582f4..92496260 100644 --- a/site/docs/list-mismatches.md +++ b/site/docs/list-mismatches.mdx @@ -6,7 +6,7 @@ title: list-mismatches List dependencies which are required by multiple packages, where the version is not the same across every package. -See [`versionGroups`](./config/version-groups.md) if you have advanced +See [`versionGroups`](./config/version-groups.mdx) if you have advanced requirements. ## CLI Options diff --git a/site/docs/list.md b/site/docs/list.mdx similarity index 100% rename from site/docs/list.md rename to site/docs/list.mdx diff --git a/site/docs/option/config.md b/site/docs/option/config.mdx similarity index 71% rename from site/docs/option/config.md rename to site/docs/option/config.mdx index d79e075a..201ab4b2 100644 --- a/site/docs/option/config.md +++ b/site/docs/option/config.mdx @@ -3,7 +3,7 @@ id: config title: --config --- -If your [configuration file](../config-file.md) is not in the root of your +If your [configuration file](../config-file.mdx) is not in the root of your monorepo or one of it's ancestor directories, you can specify its location via the --config option. diff --git a/site/docs/option/filter.md b/site/docs/option/filter.mdx similarity index 94% rename from site/docs/option/filter.md rename to site/docs/option/filter.mdx index ef2f06c9..cc45632d 100644 --- a/site/docs/option/filter.md +++ b/site/docs/option/filter.mdx @@ -4,7 +4,7 @@ title: --filter --- A string which will be passed to `new RegExp()` to match against package names -that should be included. This is useful alongside [`syncpack list`](../list.md) +that should be included. This is useful alongside [`syncpack list`](../list.mdx) to check the status of a subset of dependencies throughout your monorepo. ``` diff --git a/site/docs/option/indent.md b/site/docs/option/indent.mdx similarity index 96% rename from site/docs/option/indent.md rename to site/docs/option/indent.mdx index 0e16c43d..c7b2d285 100644 --- a/site/docs/option/indent.md +++ b/site/docs/option/indent.mdx @@ -4,7 +4,7 @@ title: --indent --- The character(s) to be used to indent your package.json files when writing to -disk. This can be used to override your [`indent`](../config/indent.md) +disk. This can be used to override your [`indent`](../config/indent.mdx) configuration on an ad hoc basis. ``` diff --git a/site/docs/option/semver-range.md b/site/docs/option/semver-range.md deleted file mode 100644 index 95cb1755..00000000 --- a/site/docs/option/semver-range.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: semver-range -title: --semver-range ---- - -Can be used with [`syncpack set-semver-ranges`](../set-semver-ranges.md) and -[`syncpack lint-semver-ranges`](../lint-semver-ranges.md) to override your -[`semverRange`](../config/semver-range.md) configuration on an ad hoc basis. - -``` -syncpack set-semver-ranges --semver-range '^' -``` diff --git a/site/docs/option/semver-range.mdx b/site/docs/option/semver-range.mdx new file mode 100644 index 00000000..14a7e9f8 --- /dev/null +++ b/site/docs/option/semver-range.mdx @@ -0,0 +1,12 @@ +--- +id: semver-range +title: --semver-range +--- + +Can be used with [`syncpack set-semver-ranges`](../set-semver-ranges.mdx) and +[`syncpack lint-semver-ranges`](../lint-semver-ranges.mdx) to override your +[`semverRange`](../config/semver-range.mdx) configuration on an ad hoc basis. + +``` +syncpack set-semver-ranges --semver-range '^' +``` diff --git a/site/docs/option/source.md b/site/docs/option/source.mdx similarity index 88% rename from site/docs/option/source.md rename to site/docs/option/source.mdx index b8dfb588..090ae217 100644 --- a/site/docs/option/source.md +++ b/site/docs/option/source.mdx @@ -3,7 +3,7 @@ id: source title: --source --- -Override your [`source`](../config/source.md) configuration on an ad hoc basis. +Override your [`source`](../config/source.mdx) configuration on an ad hoc basis. This can be useful when you only want to deal with one package at a single time, to list all of the devDependencies in one package for example: diff --git a/site/docs/option/types.md b/site/docs/option/types.mdx similarity index 88% rename from site/docs/option/types.md rename to site/docs/option/types.mdx index fef1c6b8..e268d76d 100644 --- a/site/docs/option/types.md +++ b/site/docs/option/types.mdx @@ -3,7 +3,7 @@ id: types title: --types --- -Override your [`dependencyTypes`](../config/dependency-types.md) configuration +Override your [`dependencyTypes`](../config/dependency-types.mdx) configuration on an ad hoc basis. This can be used to work with every package in your monorepo, but only with a @@ -22,7 +22,7 @@ syncpack set-semver-ranges --types dev,peer --semver-range "^" Running syncpack multiple times with different options to target different parts of your package.json files is a lot of work to maintain, so -[`semverGroups`](../config/semver-groups.md) exist to make this easier. +[`semverGroups`](../config/semver-groups.mdx) exist to make this easier. The above example would would defined like so: diff --git a/site/docs/set-semver-ranges.md b/site/docs/set-semver-ranges.mdx similarity index 95% rename from site/docs/set-semver-ranges.md rename to site/docs/set-semver-ranges.mdx index ed60b6b7..a83e7e80 100644 --- a/site/docs/set-semver-ranges.md +++ b/site/docs/set-semver-ranges.mdx @@ -6,7 +6,7 @@ title: set-semver-ranges Ensure dependency versions used within `"dependencies"`, `"devDependencies"` etc follow a consistent format. -See [`semverGroups`](./config/semver-groups.md) if you have advanced +See [`semverGroups`](./config/semver-groups.mdx) if you have advanced requirements. ## CLI Options diff --git a/site/docusaurus.config.js b/site/docusaurus.config.js index b29be441..cb49f405 100644 --- a/site/docusaurus.config.js +++ b/site/docusaurus.config.js @@ -82,6 +82,11 @@ const config = { position: 'left', label: 'Docs', }, + { + href: 'https://github.com/sponsors/JamieMason', + label: '❤️ Sponsor', + position: 'right', + }, { href: 'https://github.com/JamieMason/syncpack', label: 'GitHub', diff --git a/site/sidebars.js b/site/sidebars.js index 25bf3beb..957a4c53 100644 --- a/site/sidebars.js +++ b/site/sidebars.js @@ -15,6 +15,7 @@ const sidebars = { docs: { 'Introduction': ['installation', 'config-file', 'github-action'], + 'Guides': ['guide/version-groups'], 'CLI Commands': [ 'fix-mismatches', 'format', diff --git a/site/src/components/HomepageFeatures/index.tsx b/site/src/components/homepage/features/index.tsx similarity index 100% rename from site/src/components/HomepageFeatures/index.tsx rename to site/src/components/homepage/features/index.tsx diff --git a/site/src/components/HomepageFeatures/styles.module.css b/site/src/components/homepage/features/styles.module.css similarity index 100% rename from site/src/components/HomepageFeatures/styles.module.css rename to site/src/components/homepage/features/styles.module.css diff --git a/site/src/components/homepage/header/index.tsx b/site/src/components/homepage/header/index.tsx new file mode 100644 index 00000000..08abd193 --- /dev/null +++ b/site/src/components/homepage/header/index.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import css from './styles.module.css'; + +export function HomepageHeader() { + const { siteConfig } = useDocusaurusContext(); + return ( +
+
+

{siteConfig.title}

+

{siteConfig.tagline}

+
+ + Get Started + +
+
+
+ ); +} diff --git a/site/src/components/homepage/header/styles.module.css b/site/src/components/homepage/header/styles.module.css new file mode 100644 index 00000000..f331949d --- /dev/null +++ b/site/src/components/homepage/header/styles.module.css @@ -0,0 +1,18 @@ +.heroBanner { + padding: 4rem 0; + text-align: center; + position: relative; + overflow: hidden; +} + +@media screen and (max-width: 996px) { + .heroBanner { + padding: 2rem; + } +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/site/src/components/pill/index.tsx b/site/src/components/pill/index.tsx new file mode 100644 index 00000000..d2081369 --- /dev/null +++ b/site/src/components/pill/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import css from './styles.module.css'; + +export default function Pills({ required, optional }) { + return ( +

+ {required && Required} + {optional && Optional} +

+ ); +} diff --git a/site/src/components/pill/styles.module.css b/site/src/components/pill/styles.module.css new file mode 100644 index 00000000..8c464771 --- /dev/null +++ b/site/src/components/pill/styles.module.css @@ -0,0 +1,44 @@ +.pill { + display: inline-flex; + padding-top: 0.125rem; + padding-bottom: 0.125rem; + padding-left: 0.625rem; + padding-right: 0.625rem; + font-size: 0.75rem; + line-height: 1rem; + font-weight: 500; + align-items: center; + border-radius: 9999px; +} +.gray { + background-color: #f3f4f6; + color: #1f2937; +} +.red { + background-color: #fee2e2; + color: #991b1b; +} +.yellow { + background-color: #fef3c7; + color: #92400e; +} +.green { + background-color: #d1fae5; + color: #065f46; +} +.blue { + background-color: #dbeafe; + color: #1e40af; +} +.indigo { + background-color: #e0e7ff; + color: #3730a3; +} +.purple { + background-color: #ede9fe; + color: #5b21b6; +} +.pink { + background-color: #fce7f3; + color: #9d174d; +} diff --git a/site/src/pages/index.module.css b/site/src/pages/index.module.css index 9f71a5da..52780c95 100644 --- a/site/src/pages/index.module.css +++ b/site/src/pages/index.module.css @@ -1,23 +1,5 @@ -/** - * CSS files with the .module.css suffix will be treated as CSS modules - * and scoped locally. - */ - -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; -} - -@media screen and (max-width: 996px) { - .heroBanner { - padding: 2rem; - } -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; +.video { + display: block; + max-width: 1400px; + margin: 4em auto; } diff --git a/site/src/pages/index.tsx b/site/src/pages/index.tsx index 98dec4a7..ebd10c08 100644 --- a/site/src/pages/index.tsx +++ b/site/src/pages/index.tsx @@ -1,41 +1,26 @@ -import React from 'react'; -import clsx from 'clsx'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; -import HomepageFeatures from '@site/src/components/HomepageFeatures'; -import styles from './index.module.css'; - -function HomepageHeader() { - const { siteConfig } = useDocusaurusContext(); - return ( -
-
-

{siteConfig.title}

-

{siteConfig.tagline}

-
- - Get Started - -
-
-
- ); -} +import React from 'react'; +import { HomepageHeader } from '@site/src/components/homepage/header'; +import css from './index.module.css'; export default function Home(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); return (
- +
); diff --git a/site/src/pages/markdown-page.md b/site/src/pages/markdown-page.md deleted file mode 100644 index 9756c5b6..00000000 --- a/site/src/pages/markdown-page.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Markdown page example ---- - -# Markdown page example - -You don't need React to write simple standalone pages. diff --git a/site/src/partials/default-dependency-types.mdx b/site/src/partials/default-dependency-types.mdx new file mode 100644 index 00000000..6061e7e6 --- /dev/null +++ b/site/src/partials/default-dependency-types.mdx @@ -0,0 +1,9 @@ +| Value | Property in package.json | +| :-------------- | :------------------------------------------------------------------------------------------------ | +| `dev` | [`devDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#devDependencies) | +| `overrides` | [`overrides`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides) | +| `peer` | [`peerDependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#peerDependencies) | +| `pnpmOverrides` | [`pnpm.overrides`](https://pnpm.io/package_json#pnpmoverrides) | +| `prod` | [`dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#dependencies) | +| `resolutions` | [`resolutions`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#resolutions) | +| `workspace` | [`version`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#version) | diff --git a/site/static/img/favicon.ico b/site/static/img/favicon.ico index c01d54bcd39a5f853428f3cd5aa0f383d963c484..82291986096d788867adc54d5310e70ede02fd58 100644 GIT binary patch literal 15406 zcmeHOd5~1a8GjS;46-{j@6D`85Cs)bEZm&~G*s|Hi4m7MVgeqhDUXUt3QbIbNgQ@& zmLndeNuh#eRjkDFD2)a%qNsr=$Ii?msEJAxFA$I@2ogCrzpwjszkdDRn;odiKPjhp z+x@z~{=VP$_1E2BcRvgxWE^HRHycO?88`GXjFe#*g9h>Up<%;#2xTKj+V!Ux#&XLr zhJpr7(1MpE3I2spMGyXj#*Xb1otVDT%BB`Yv#Is;Aiu!Oq$e4900A8%wVQ;*3*MWu ziIdE1YBio7daR87WYg^3%%)dHGwA^&iT&)hl$iNM3uJx3+Y-Haz=QaKm(6!wzx?P3 zwPDR|9?@*#Nupu2XiKs|ztPO4HreesPn1V;$%mM(wld*M+eU!qJv@`lY;wPqO>8tL zCch(OL?$LLie^$<86V=CN$m^g+6D^w(M)1`G(Re3uIy-wWYeYa#PqjGKN}iLqxtlu zTnBCo;QevPHeSC8twXG8aayca+7VgNF^n~^8&eX^rN%`w$yKBq*N=2dZm=@RJE-2Q z6vxIY<$bYgsRz$%gVq<0qH@jxfAKGxO*;0;qZ2&JR!cO5R2E!8>nrZ+SeG5 zd1%glj0bQ+-zGDg_?KMf$HMb;#{=b7ORzcTi*WtSgknDVL-W%5y>Qzkh>dp zoMUzu`g7jEUoGDp=j|8gvaVCjf_`{Q_&X}#Fzehgjp#~7c}N;ou|aA zWdqB4zx;`&ti!{2tbbPGR@d?KOTkyUhdiIF-She_Rd{yy8TP+R|O456@S{w$P z?=V}6z973+!GrT#Z&eBy>C7ZdwA8^a>|ZS$6RUOHVpfY)wEK!4=v_sB{35<)&NrQw z3KPcZ(EiXoGYHREJRz1tCg>-?s`W}4&*Ja+AxC2TUd;R?ms$v)tFi}qjKf)xZ0bVe zy0*hrHVx+$c}^Q%*xWv{8U9(qv(=tI#GK=sKfBZ1`l%YRoJ9C;ZZ$-9^!-a>+>~@*d%|TkK=Z_lt;43nVLA)Yjk4kFj{BXTHBtS3_0s07NJ`!w$*b1XY(Ec^N(_`p~1Y&al4 z>S)+(k))SnL*PhZeNEmdo5>7U0zOZ1)shg!Q}&PI0h`~lP(Clq1q4p!FtYMv`-1*m zY9s6}`w=z(|HXp0n#S7O21D14u?gw8@$!s5R;Bc)wY)HdXsk@)(dLPX(^Yyk??~sR zkz6WY#|Ar$g7FQtJ>?<$l5nnd4CS$=-_7EU8jo3w-0&mVdQX)BKXby_$3o^^uO{b@v|WND?_me~OmqEu2e_K|kyj7=$mdG?Uyw7)5JJ@R+h<|_pwdQ{7lwi_`dpXgkHM^T{6KB*$qRFkFXWQXOAP1>!lcu~ z=CkoUi|18028vH@Oh_>%m!c1r!50@fH~wD(1fg7VMwgI zc)r^A)Hd`+;RyKI9tQ*Thg>_pMeN?m<_1-co)>Z{=Ek1jcB-fS8v1<=t$hQQ-*q(j zuW5O$<1|4ld7uC>_)0F*$M%)dtHu+`{3{#U8HFKaJc4I`eASE#nV$L6jvy-N_aMr* z7=;3x|CA<-iB&1zhI(g@pya6>d#XEZX-=XsiPwr#6&_p27DOEDE?-Hy0mFRWSZj#F z=I+u7u}VqqX%s#Z6MW#Yh|QDpp}!%c@2Z(m*l#XtBm4%KF`xbo`?yw=f63~)N@qFk z#AqTc91k!)>?c<%+l}|vrL_|1%h0|2k}BKD3tNP^4H#A* zA0Xa}PimNK8wIqhmiAg*Wwu9iBK$Ht?;=NA#l+nX|ULW^5CV|3u;_<`ai;eh#2bYQi{<>hm@~KCwa-dSSwLL}%ync>8$9~xvmn<*sto4Cij{W^!^kdO@T%9u%-Xz;Cn43l;A+l%{YXm=s zptFZSeQn=3Ksv`(md~KJ`cJUuqQ#p|<^LXEQ#=v8rvbzB80#DOTtR0b$fFGB3DaqQ zm#qbRk;)1?6I8C#{U5*6ISEY)Q}Be0LHPSW{NW6@B|p-_nd+$);%zIJnvS*kLBs`5 z(Sv>5e4Hsx595r*%C`>be@UBZsCy0{Xue(OTj!+DZj72>nMZb`+7e`Ts<;xT~I@m<6ro)#OY=x`3&|3IK!d6 ztrxQ>(^ETc-G}l|p!Xl?TsCn241(bWT&Kig(vm;ZisqSrc+MgmoZ6Xy(hm-ev-gEQ zTM-Li9~p0-Lpb7sF@dH&nYT9Do=8Fd0_^YhNF2TFha_Eq4t8IVzkP|l(;sMj1cMH) zk!WScMH_;Tp9dSg-5VZnz1kOQUfch2JJ9&3gtKYiHNuTZdGp6C39Ni#B=%kZRIw>` zbL~G>nnv{J#16eHXxUDfc5C zp`!ui^jfT?zXRR_lIOwM^L?yskAg=DeK-rT!&Bh3S=Ij_@_WJKS~ptl4d6L`{+Grq zWQsYS=Cr5r%*DgYG+nrkXxi*DMdj_E$GvZ!-BXD3`M1K#`EWGbHq^?d`MtQbRq})IrKvIQG3G@s$%LpoWl8N{FPTLL-%T_ZLraH+#O#Hde@mWbZAHY7n~>L=Tbj%W0y$l zW`>L(eMDTgtjXThnzQBAqDVQ5#;(S{Z_8(7z=VF1YfAxW5 zu(!ndV(Blqt2U`U`7rwb6>~!3R2M&K3S?xSQ)sWESqNk2CV`*N1A+G65Bzj?7{Cf= zikY_KFjqa?lu58NaqEpjU+jPB%#ZEOu@5dA)d$#qqhEe_M1b&3RVm1`SIj}-Z0i|O zd|yKMhV0AL#j0d~jPoSz?S|vr75n#FaK5lp z+&e&z-8hT9#=!Z97qd^1P6WQVhqxSgx4AK^IMsZRUaWj4cudtqgv3~k;XD!eHw)W4 zY4L;D>dv#hXtfgURmd51_1L4}pR_iLad`-7n)Z7Savz5vRTlC%7d;MVOY0oW?z0_? zg@wm;cjBw9L;DTE_Y#o543FF^yY!L%aGhB14!%wq`Qz3J-uE1BdxhDv(Ql3kFiu>eqB_lOcz3yIYT#{OVGIVwwS-f_=bsle__hjuw2*wx z&6D>?BmF}6Kk$8u5AAUrIRA80{Nk3w-y$mu{eb(~UU7STh|Y-1bhmY<$BXI=0bMV4 zZl{d}&HlTh+0kjB)tef$9?|(MFf`)xzWqUCJYFqNa-V7YSt_tBggNyp^ucz~4+{QW z_}1wfzm}v7?szV?&zXI(HQpy!7rHvm_LJk3dCe#4SX_meOW?QDJYd-BP&ZmawcCQmqV&h(?yBX*KOb3Jxe)GSm!yVv7#4FgUfs$m!v8$#E!h2IIbO-ffgM;D4qQ7EUqIuh3RUv4YR3)0_aA}LHqtZt4V^< zG74L*#(sUd&<9-bKT@RYwq^I$?PyZ@{=sp~@ zK5>ulyto>`$|MMt_W} z7l;Ni*N2g=j?>(7>^JaKCE}ZiBI7Ik#53=E`eF_G;k(95=>Oh+h`r<0jx>CMaLI8d z^}swp`wj!K494N_`CS~7_cWEM>{ZNax%m&opViVXeJ!pxmO;M-^uO)5yukN0KFs;I z#-&?9`@Y1h*v96+!|Lw57WrR+hVJv358(R+|Cmh$uH<7~Y+SkQ(+hs#YoEa{=D~KC zN4sVw%~hoYeOrTd<{tRW2FE6vA1ZnP^OuU<;X6hCZJm!z6v(cuxr)9~FTE}FZzv7& zx1e%h?%gKE&DP2i`~L|pCwHOsdBI#}f43t0P}RXJm&d4*M#Ze=-F6mzrlhWZ*^jvL zUiyZOA@sFB3Vq9Q&hUCU4m>L)re0-x#qWbZkT=>=8ufg(^D5{-AYv# z>~rmJ2{*d?p+P)S-`;%)`=QV9{8XGXsWANW4Qhe!Rq+3YCIElUtwV2^pku@M%jABqA zcfaS{d+xbU5JKp0*;0YOg+;Fl!eT)XRuapIwFLL`=imZCSon$`se`_<%@MB=M~KG+ z=EW^FL`w|Bo>*ktlaS^(fut!95`iG5u=SZ8nfDHO#GaTlH1-XG^;vsjUb^gWTVz0+ z^=WR1wv9-2oeR=_;fL0H7rNWqAzGtO(D;`~cX(RcN0w2v24Y8)6t`cS^_ghs`_ho? z{0ka~1Dgo8TfAP$r*ua?>$_V+kZ!-(TvEJ7O2f;Y#tezt$&R4 zLI}=-y@Z!grf*h3>}DUL{km4R>ya_I5Ag#{h_&?+HpKS!;$x3LC#CqUQ8&nM?X))Q zXAy2?`YL4FbC5CgJu(M&Q|>1st8XXLZ|5MgwgjP$m_2Vt0(J z&Gu7bOlkbGzGm2sh?X`){7w69Y$1#@P@7DF{ZE=4%T0NDS)iH`tiPSKpDNW)zmtn( zw;4$f>k)4$LBc>eBAaTZeCM2(iD+sHlj!qd z2GjRJ>f_Qes(+mnzdA^NH?^NB(^o-%Gmg$c8MNMq&`vm@9Ut;*&$xSD)PKH{wBCEC z4P9%NQ;n2s59ffMn8*5)5AAg4-93gBXBDX`A7S& zH-|%S3Wd%T79fk-e&l`{!?lve8_epXhE{d3Hn$Cg!t=-4D(t$cK~7f&4s?t7wr3ZP z*!SRQ-+tr|e1|hbc__J`k3S!rMy<0PHy&R`v#aJv?`Y?2{avK5sQz%=Us()jcNuZV z*$>auD4cEw>;t`+m>h?f?%VFJZj8D|Y1e_SjxG%J4{-AkFtT2+ZZS5UScS~%;dp!V>)7zi`w(xwSd*FS;Lml=f6hn#jq)2is4nkp+aTrV?)F6N z>DY#SU0IZ;*?Hu%tSj4edd~kYNHMFvS&5}#3-M;mBCOCZL3&;2obdG?qZ>rD|zC|Lu|sny76pn2xl|6sk~Hs{X9{8iBW zwiwgQt+@hi`FYMEhX2