syncpack 12.4.0 → 14.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/index.js +48 -0
  2. package/package.json +17 -76
  3. package/schema.json +917 -0
  4. package/syncpack.d.ts +122 -0
  5. package/LICENSE +0 -20
  6. package/dist/bin-fix-mismatches/fix-mismatches.d.ts +0 -16
  7. package/dist/bin-fix-mismatches/fix-mismatches.js +0 -110
  8. package/dist/bin-fix-mismatches/index.d.ts +0 -2
  9. package/dist/bin-fix-mismatches/index.js +0 -64
  10. package/dist/bin-format/format.d.ts +0 -13
  11. package/dist/bin-format/format.js +0 -90
  12. package/dist/bin-format/index.d.ts +0 -2
  13. package/dist/bin-format/index.js +0 -53
  14. package/dist/bin-lint/index.d.ts +0 -2
  15. package/dist/bin-lint/index.js +0 -38
  16. package/dist/bin-lint/lint.d.ts +0 -11
  17. package/dist/bin-lint/lint.js +0 -52
  18. package/dist/bin-lint-semver-ranges/index.d.ts +0 -2
  19. package/dist/bin-lint-semver-ranges/index.js +0 -65
  20. package/dist/bin-lint-semver-ranges/lint-semver-ranges.d.ts +0 -16
  21. package/dist/bin-lint-semver-ranges/lint-semver-ranges.js +0 -91
  22. package/dist/bin-list/index.d.ts +0 -2
  23. package/dist/bin-list/index.js +0 -57
  24. package/dist/bin-list/list.d.ts +0 -14
  25. package/dist/bin-list/list.js +0 -147
  26. package/dist/bin-list-mismatches/index.d.ts +0 -2
  27. package/dist/bin-list-mismatches/index.js +0 -59
  28. package/dist/bin-list-mismatches/list-mismatches.d.ts +0 -18
  29. package/dist/bin-list-mismatches/list-mismatches.js +0 -218
  30. package/dist/bin-prompt/index.d.ts +0 -2
  31. package/dist/bin-prompt/index.js +0 -61
  32. package/dist/bin-prompt/prompt.d.ts +0 -11
  33. package/dist/bin-prompt/prompt.js +0 -93
  34. package/dist/bin-set-semver-ranges/index.d.ts +0 -2
  35. package/dist/bin-set-semver-ranges/index.js +0 -69
  36. package/dist/bin-set-semver-ranges/set-semver-ranges.d.ts +0 -11
  37. package/dist/bin-set-semver-ranges/set-semver-ranges.js +0 -58
  38. package/dist/bin-update/effects.d.ts +0 -52
  39. package/dist/bin-update/effects.js +0 -267
  40. package/dist/bin-update/index.d.ts +0 -2
  41. package/dist/bin-update/index.js +0 -54
  42. package/dist/bin-update/update.d.ts +0 -6
  43. package/dist/bin-update/update.js +0 -59
  44. package/dist/bin.d.ts +0 -2
  45. package/dist/bin.js +0 -37
  46. package/dist/config/get-custom-types.d.ts +0 -19
  47. package/dist/config/get-custom-types.js +0 -50
  48. package/dist/config/get-enabled-types.d.ts +0 -17
  49. package/dist/config/get-enabled-types.js +0 -94
  50. package/dist/config/get-filter.d.ts +0 -2
  51. package/dist/config/get-filter.js +0 -10
  52. package/dist/config/get-indent.d.ts +0 -2
  53. package/dist/config/get-indent.js +0 -9
  54. package/dist/config/get-sort-az.d.ts +0 -2
  55. package/dist/config/get-sort-az.js +0 -8
  56. package/dist/config/get-sort-exports.d.ts +0 -2
  57. package/dist/config/get-sort-exports.js +0 -8
  58. package/dist/config/get-sort-first.d.ts +0 -2
  59. package/dist/config/get-sort-first.js +0 -8
  60. package/dist/config/get-source.d.ts +0 -2
  61. package/dist/config/get-source.js +0 -8
  62. package/dist/config/tag.d.ts +0 -3
  63. package/dist/config/tag.js +0 -2
  64. package/dist/config/types.d.ts +0 -132
  65. package/dist/config/types.js +0 -1
  66. package/dist/constants.d.ts +0 -106
  67. package/dist/constants.js +0 -103
  68. package/dist/error-handlers/default-error-handlers.d.ts +0 -25
  69. package/dist/error-handlers/default-error-handlers.js +0 -80
  70. package/dist/get-context/index.d.ts +0 -23
  71. package/dist/get-context/index.js +0 -18
  72. package/dist/get-context/lib/key-by.d.ts +0 -6
  73. package/dist/get-context/lib/key-by.js +0 -12
  74. package/dist/get-instances/index.d.ts +0 -14
  75. package/dist/get-instances/index.js +0 -42
  76. package/dist/get-instances/instance.d.ts +0 -26
  77. package/dist/get-instances/instance.js +0 -31
  78. package/dist/get-package-json-files/get-file-paths.d.ts +0 -21
  79. package/dist/get-package-json-files/get-file-paths.js +0 -22
  80. package/dist/get-package-json-files/get-patterns/get-lerna-patterns.d.ts +0 -3
  81. package/dist/get-package-json-files/get-patterns/get-lerna-patterns.js +0 -10
  82. package/dist/get-package-json-files/get-patterns/get-pnpm-patterns.d.ts +0 -3
  83. package/dist/get-package-json-files/get-patterns/get-pnpm-patterns.js +0 -14
  84. package/dist/get-package-json-files/get-patterns/get-yarn-patterns.d.ts +0 -3
  85. package/dist/get-package-json-files/get-patterns/get-yarn-patterns.js +0 -16
  86. package/dist/get-package-json-files/get-patterns/index.d.ts +0 -8
  87. package/dist/get-package-json-files/get-patterns/index.js +0 -23
  88. package/dist/get-package-json-files/index.d.ts +0 -10
  89. package/dist/get-package-json-files/index.js +0 -8
  90. package/dist/get-package-json-files/package-json-file.d.ts +0 -47
  91. package/dist/get-package-json-files/package-json-file.js +0 -29
  92. package/dist/guards/can-add-to-group.d.ts +0 -5
  93. package/dist/guards/can-add-to-group.js +0 -52
  94. package/dist/guards/is-semver.d.ts +0 -2
  95. package/dist/guards/is-semver.js +0 -13
  96. package/dist/guards/is-valid-semver-range.d.ts +0 -3
  97. package/dist/guards/is-valid-semver-range.js +0 -14
  98. package/dist/index.d.ts +0 -2
  99. package/dist/index.js +0 -1
  100. package/dist/io/ask-for-choice.d.ts +0 -14
  101. package/dist/io/ask-for-choice.js +0 -17
  102. package/dist/io/ask-for-input.d.ts +0 -13
  103. package/dist/io/ask-for-input.js +0 -14
  104. package/dist/io/exit-if-invalid.d.ts +0 -4
  105. package/dist/io/exit-if-invalid.js +0 -9
  106. package/dist/io/glob-sync.d.ts +0 -11
  107. package/dist/io/glob-sync.js +0 -14
  108. package/dist/io/index.d.ts +0 -27
  109. package/dist/io/index.js +0 -26
  110. package/dist/io/read-config-file.d.ts +0 -7
  111. package/dist/io/read-config-file.js +0 -22
  112. package/dist/io/read-file-sync.d.ts +0 -12
  113. package/dist/io/read-file-sync.js +0 -9
  114. package/dist/io/read-json-file-sync.d.ts +0 -30
  115. package/dist/io/read-json-file-sync.js +0 -19
  116. package/dist/io/read-yaml-file-sync.d.ts +0 -12
  117. package/dist/io/read-yaml-file-sync.js +0 -9
  118. package/dist/io/to-json.d.ts +0 -9
  119. package/dist/io/to-json.js +0 -29
  120. package/dist/io/write-file-sync.d.ts +0 -12
  121. package/dist/io/write-file-sync.js +0 -10
  122. package/dist/io/write-if-changed.d.ts +0 -5
  123. package/dist/io/write-if-changed.js +0 -10
  124. package/dist/lib/format-repository-url.d.ts +0 -1
  125. package/dist/lib/format-repository-url.js +0 -37
  126. package/dist/lib/get-group-header.d.ts +0 -10
  127. package/dist/lib/get-group-header.js +0 -23
  128. package/dist/lib/get.d.ts +0 -11
  129. package/dist/lib/get.js +0 -36
  130. package/dist/lib/pad-start.d.ts +0 -1
  131. package/dist/lib/pad-start.js +0 -3
  132. package/dist/lib/ring-buffer.d.ts +0 -10
  133. package/dist/lib/ring-buffer.js +0 -20
  134. package/dist/lib/set-semver-range.d.ts +0 -3
  135. package/dist/lib/set-semver-range.js +0 -20
  136. package/dist/lib/show-help-on-error.d.ts +0 -2
  137. package/dist/lib/show-help-on-error.js +0 -32
  138. package/dist/lib/sort-by-name.d.ts +0 -5
  139. package/dist/lib/sort-by-name.js +0 -9
  140. package/dist/lib/with-logger.d.ts +0 -2
  141. package/dist/lib/with-logger.js +0 -29
  142. package/dist/option.d.ts +0 -10
  143. package/dist/option.js +0 -27
  144. package/dist/report.d.ts +0 -131
  145. package/dist/report.js +0 -129
  146. package/dist/schema.json +0 -544
  147. package/dist/semver-group/create-semver-groups.d.ts +0 -4
  148. package/dist/semver-group/create-semver-groups.js +0 -79
  149. package/dist/semver-group/disabled.d.ts +0 -26
  150. package/dist/semver-group/disabled.js +0 -28
  151. package/dist/semver-group/filtered-out.d.ts +0 -27
  152. package/dist/semver-group/filtered-out.js +0 -34
  153. package/dist/semver-group/ignored.d.ts +0 -22
  154. package/dist/semver-group/ignored.js +0 -24
  155. package/dist/semver-group/index.d.ts +0 -20
  156. package/dist/semver-group/index.js +0 -7
  157. package/dist/semver-group/with-range.d.ts +0 -22
  158. package/dist/semver-group/with-range.js +0 -45
  159. package/dist/specifier/alias.d.ts +0 -17
  160. package/dist/specifier/alias.js +0 -20
  161. package/dist/specifier/base.d.ts +0 -41
  162. package/dist/specifier/base.js +0 -54
  163. package/dist/specifier/delete.d.ts +0 -17
  164. package/dist/specifier/delete.js +0 -16
  165. package/dist/specifier/exact.d.ts +0 -20
  166. package/dist/specifier/exact.js +0 -21
  167. package/dist/specifier/file.d.ts +0 -8
  168. package/dist/specifier/file.js +0 -7
  169. package/dist/specifier/hosted-git.d.ts +0 -15
  170. package/dist/specifier/hosted-git.js +0 -22
  171. package/dist/specifier/index.d.ts +0 -28
  172. package/dist/specifier/index.js +0 -63
  173. package/dist/specifier/latest.d.ts +0 -19
  174. package/dist/specifier/latest.js +0 -20
  175. package/dist/specifier/lib/non-semver-error.d.ts +0 -11
  176. package/dist/specifier/lib/non-semver-error.js +0 -6
  177. package/dist/specifier/lib/parse-specifier.d.ts +0 -14
  178. package/dist/specifier/lib/parse-specifier.js +0 -16
  179. package/dist/specifier/lib/specific-registry-result.d.ts +0 -9
  180. package/dist/specifier/lib/specific-registry-result.js +0 -1
  181. package/dist/specifier/range.d.ts +0 -19
  182. package/dist/specifier/range.js +0 -20
  183. package/dist/specifier/tag.d.ts +0 -11
  184. package/dist/specifier/tag.js +0 -10
  185. package/dist/specifier/unsupported.d.ts +0 -7
  186. package/dist/specifier/unsupported.js +0 -7
  187. package/dist/specifier/url.d.ts +0 -8
  188. package/dist/specifier/url.js +0 -7
  189. package/dist/specifier/workspace-protocol.d.ts +0 -19
  190. package/dist/specifier/workspace-protocol.js +0 -34
  191. package/dist/strategy/lib/get-non-empty-string-prop.d.ts +0 -3
  192. package/dist/strategy/lib/get-non-empty-string-prop.js +0 -7
  193. package/dist/strategy/name-and-version-props.d.ts +0 -12
  194. package/dist/strategy/name-and-version-props.js +0 -60
  195. package/dist/strategy/named-version-string.d.ts +0 -11
  196. package/dist/strategy/named-version-string.js +0 -49
  197. package/dist/strategy/unnamed-version-string.d.ts +0 -11
  198. package/dist/strategy/unnamed-version-string.js +0 -45
  199. package/dist/strategy/versions-by-name.d.ts +0 -11
  200. package/dist/strategy/versions-by-name.js +0 -25
  201. package/dist/version-group/banned.d.ts +0 -17
  202. package/dist/version-group/banned.js +0 -26
  203. package/dist/version-group/create-version-groups.d.ts +0 -4
  204. package/dist/version-group/create-version-groups.js +0 -114
  205. package/dist/version-group/filtered-out.d.ts +0 -19
  206. package/dist/version-group/filtered-out.js +0 -30
  207. package/dist/version-group/ignored.d.ts +0 -17
  208. package/dist/version-group/ignored.js +0 -23
  209. package/dist/version-group/index.d.ts +0 -26
  210. package/dist/version-group/index.js +0 -7
  211. package/dist/version-group/lib/clean.d.ts +0 -2
  212. package/dist/version-group/lib/clean.js +0 -6
  213. package/dist/version-group/lib/delete.d.ts +0 -2
  214. package/dist/version-group/lib/delete.js +0 -1
  215. package/dist/version-group/lib/get-highest-version.d.ts +0 -6
  216. package/dist/version-group/lib/get-highest-version.js +0 -8
  217. package/dist/version-group/lib/get-lowest-version.d.ts +0 -6
  218. package/dist/version-group/lib/get-lowest-version.js +0 -8
  219. package/dist/version-group/lib/get-preferred-version.d.ts +0 -5
  220. package/dist/version-group/lib/get-preferred-version.js +0 -44
  221. package/dist/version-group/lib/get-range-score.d.ts +0 -2
  222. package/dist/version-group/lib/get-range-score.js +0 -18
  223. package/dist/version-group/lib/group-by.d.ts +0 -5
  224. package/dist/version-group/lib/group-by.js +0 -11
  225. package/dist/version-group/pinned.d.ts +0 -17
  226. package/dist/version-group/pinned.js +0 -26
  227. package/dist/version-group/same-range.d.ts +0 -19
  228. package/dist/version-group/same-range.js +0 -96
  229. package/dist/version-group/snapped-to.d.ts +0 -17
  230. package/dist/version-group/snapped-to.js +0 -69
  231. package/dist/version-group/standard.d.ts +0 -18
  232. package/dist/version-group/standard.js +0 -116
@@ -1,267 +0,0 @@
1
- import * as Schema from '@effect/schema/Schema';
2
- import chalk from 'chalk-template';
3
- import { Data, Effect, identity, pipe } from 'effect';
4
- import https from 'https';
5
- import ora from 'ora';
6
- import { EOL } from 'os';
7
- import prompts from 'prompts';
8
- import { diff } from 'semver';
9
- import gtr from 'semver/ranges/gtr.js';
10
- import { isArray } from 'tightrope/guard/is-array.js';
11
- import { isEmptyObject } from 'tightrope/guard/is-empty-object.js';
12
- import { ICON } from '../constants.js';
13
- import { formatRepositoryUrl } from '../lib/format-repository-url.js';
14
- import { RingBuffer } from '../lib/ring-buffer.js';
15
- import { setSemverRange } from '../lib/set-semver-range.js';
16
- import { Specifier } from '../specifier/index.js';
17
- /** full release history from the npm registry for a given package */
18
- class Releases extends Data.TaggedClass('Releases') {
19
- }
20
- // https://github.com/terkelg/prompts?tab=readme-ov-file#prompts
21
- class PromptCancelled extends Data.TaggedClass('PromptCancelled') {
22
- }
23
- class HttpError extends Data.TaggedClass('HttpError') {
24
- }
25
- class NpmRegistryError extends Data.TaggedClass('NpmRegistryError') {
26
- }
27
- /** the API client for the terminal spinner */
28
- let spinner = null;
29
- /** how many HTTP requests have been sent */
30
- let fetchedCount = 0;
31
- /** how many instances have updates available */
32
- let outdatedCount = 0;
33
- /** names of instances currently being fetched from npm */
34
- const inFlight = new Set();
35
- /** names of instances most recently finished being fetched from npm */
36
- const mostRecent = new RingBuffer(5);
37
- /** page size when prompting */
38
- const optionsPerPage = 50;
39
- /** instance names in `inFlight` are formatted for display */
40
- function format(instance) {
41
- return chalk `{gray ${instance.name}}`;
42
- }
43
- /** we need to remove colours when sorting loading status output */
44
- function stripAnsi(str) {
45
- // eslint-disable-next-line no-control-regex
46
- const ansiChars = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
47
- return str.replace(ansiChars, '');
48
- }
49
- export const updateEffects = {
50
- onFetchAllStart() {
51
- if (!spinner)
52
- spinner = ora().start();
53
- fetchedCount = 0;
54
- return Effect.void;
55
- },
56
- onFetchStart(instance, totalCount) {
57
- inFlight.add(format(instance));
58
- fetchedCount++;
59
- if (spinner) {
60
- const indent = `${EOL} `;
61
- const progress = new Set([...mostRecent.filter(Boolean), ...inFlight.values()]);
62
- const sortedProgress = Array.from(progress).sort((a, b) => stripAnsi(a).localeCompare(stripAnsi(b)));
63
- const suffixText = sortedProgress.join(indent);
64
- spinner.text = chalk `${outdatedCount} updates found in ${fetchedCount}/${totalCount} dependencies${indent}${suffixText}`;
65
- }
66
- return Effect.void;
67
- },
68
- onFetchEnd(instance, versions) {
69
- inFlight.delete(format(instance));
70
- const latest = versions?.latest;
71
- if (latest) {
72
- if (gtr(latest, String(instance.rawSpecifier.raw), true)) {
73
- outdatedCount++;
74
- mostRecent.push(chalk `${instance.name} {gray {red ${String(instance.rawSpecifier.raw)}} ${ICON.rightArrow}} {green ${latest}}`);
75
- }
76
- else {
77
- mostRecent.push(chalk `{green ${instance.name}}`);
78
- }
79
- }
80
- return Effect.void;
81
- },
82
- /** After checking the registry, store this instance known to be up to date */
83
- onUpToDate(instance) {
84
- mostRecent.push(chalk `{green ${instance.name}}`);
85
- return Effect.void;
86
- },
87
- /** After checking the registry, store this instance known to have newer versions available */
88
- onOutdated(instance, latest) {
89
- outdatedCount++;
90
- mostRecent.push(chalk `${instance.name} {gray {red ${String(instance.rawSpecifier.raw)}} ${ICON.rightArrow}} {green ${latest}}`);
91
- return Effect.void;
92
- },
93
- /** As the last request completes, remove the progress information */
94
- onFetchAllEnd() {
95
- if (spinner)
96
- spinner.stop();
97
- spinner = null;
98
- fetchedCount = 0;
99
- return Effect.void;
100
- },
101
- /** Fetch available versions for a given package from the npm registry */
102
- fetchLatestVersions(instance) {
103
- return pipe(fetchJson(`https://registry.npmjs.org/${instance.name}`),
104
- // parse and validate the specific data we expect
105
- Effect.flatMap(Schema.decodeUnknownEither(Schema.Struct({
106
- 'dist-tags': Schema.Struct({ latest: Schema.String }),
107
- 'time': Schema.Record({ key: Schema.String, value: Schema.String }),
108
- 'homepage': Schema.optional(Schema.String),
109
- 'repository': Schema.optional(Schema.Union(Schema.String, Schema.Struct({ url: Schema.optional(Schema.String) }))),
110
- }))),
111
- // transform it into something more appropriate
112
- Effect.map((struct) => {
113
- const rawRepoUrl = typeof struct.repository === 'object' ? struct.repository.url : struct.repository;
114
- return new Releases({
115
- instance,
116
- versions: {
117
- all: Object.keys(struct.time).filter((key) => key !== 'modified' && key !== 'created'),
118
- latest: struct['dist-tags'].latest,
119
- },
120
- repoUrl: formatRepositoryUrl(rawRepoUrl),
121
- });
122
- }),
123
- // hide ParseErrors and just treat them as another kind of NpmRegistryError
124
- Effect.catchTags({
125
- ParseError: () => Effect.fail(new NpmRegistryError({ error: `Invalid response for ${instance.name}` })),
126
- }));
127
- },
128
- /** Given responses from npm, ask the user which they want */
129
- promptForUpdates(outdated) {
130
- return pipe(Effect.Do, Effect.bind('releasesByType', () => groupByReleaseType(outdated)),
131
- // Create choices to ask if they want major, minor, patch etc
132
- Effect.bind('releaseTypeQuestions', ({ releasesByType }) => Effect.succeed(Object.keys(releasesByType)
133
- .filter((type) => releasesByType[type].length > 0)
134
- .map((type) => ({
135
- title: chalk `${releasesByType[type].length} ${type}`,
136
- selected: true,
137
- value: type,
138
- })))),
139
- // Ask which release types (major, minor, patch etc) they want
140
- Effect.bind('releaseTypeAnswers', ({ releaseTypeQuestions }) => releaseTypeQuestions.length > 0
141
- ? pipe(Effect.tryPromise({
142
- try: () => prompts({
143
- name: 'releaseTypeAnswers',
144
- type: 'multiselect',
145
- instructions: true,
146
- message: `${outdated.length} updates are available`,
147
- choices: releaseTypeQuestions,
148
- }).then((res) => res?.releaseTypeAnswers || []),
149
- catch: identity,
150
- }), Effect.catchAll(() => pipe(Effect.logError('Error when prompting for releaseTypeAnswers'), Effect.map(() => []))))
151
- : Effect.succeed([])),
152
- // For each chosen release type, list the available updates to choose from
153
- Effect.bind('prepatchAnswers', (doState) => promptForReleaseType('prepatch', doState)), Effect.bind('patchAnswers', (doState) => promptForReleaseType('patch', doState)), Effect.bind('preminorAnswers', (doState) => promptForReleaseType('preminor', doState)), Effect.bind('minorAnswers', (doState) => promptForReleaseType('minor', doState)), Effect.bind('premajorAnswers', (doState) => promptForReleaseType('premajor', doState)), Effect.bind('majorAnswers', (doState) => promptForReleaseType('major', doState)), Effect.bind('prereleaseAnswers', (doState) => promptForReleaseType('prerelease', doState)),
154
- /** Apply every update to the package.json files */
155
- Effect.flatMap((doState) => pipe([
156
- ...doState.prepatchAnswers,
157
- ...doState.patchAnswers,
158
- ...doState.preminorAnswers,
159
- ...doState.minorAnswers,
160
- ...doState.premajorAnswers,
161
- ...doState.majorAnswers,
162
- ...doState.prereleaseAnswers,
163
- ], Effect.forEach(({ instance, versions }) => pipe(instance.semverGroup.getFixed(Specifier.create(instance, versions.latest)), Effect.flatMap((latestWithRange) => instance.write(latestWithRange.raw)), Effect.catchTag('NonSemverError', Effect.logError))), Effect.flatMap(() => Effect.void))));
164
- },
165
- };
166
- function promptForReleaseType(releaseType, doState) {
167
- const { releasesByType, releaseTypeAnswers } = doState;
168
- const prop = `${releaseType}Answers`;
169
- const releases = releasesByType[releaseType];
170
- return releaseTypeAnswers.includes(releaseType)
171
- ? pipe(Effect.tryPromise({
172
- try: () => prompts({
173
- name: prop,
174
- type: 'multiselect',
175
- instructions: false,
176
- // @ts-expect-error optionsPerPage *does* exist https://github.com/terkelg/prompts#options-7
177
- optionsPerPage,
178
- message: `${releases.length} ${releaseType} updates`,
179
- choices: releases.map((updateable) => {
180
- const spacingValue = 50 -
181
- updateable.instance.name.length -
182
- String(updateable.instance.rawSpecifier).length -
183
- updateable.versions.latest.length;
184
- const spacing = Array.from({ length: spacingValue }).fill(' ').join('');
185
- const repoUrl = updateable.repoUrl
186
- ? chalk `${spacing} {white - ${updateable.repoUrl}}`
187
- : '';
188
- return {
189
- title: chalk `${updateable.instance.name} {gray ${String(updateable.instance.rawSpecifier.raw)} ${ICON.rightArrow}} {green ${updateable.versions.latest}} ${repoUrl}`,
190
- selected: true,
191
- value: updateable,
192
- };
193
- }),
194
- }),
195
- catch: identity,
196
- }),
197
- // Paper over errors in terkelg/prompts for now
198
- Effect.catchAll(() => pipe(Effect.logError(`terkelg/prompts errored while prompting for ${prop}`), Effect.map(() => ({ [prop]: [] })))),
199
- // In terkelg/prompts, an empty object means that the user cancelled via
200
- // ctrl+c or the escape key etc. Handle this case so we can skip any
201
- // remaining steps.
202
- Effect.flatMap((res) => isEmptyObject(res)
203
- ? Effect.fail(new PromptCancelled({ name: releaseType }))
204
- : Effect.succeed(isArray(res?.[prop]) ? res?.[prop] : [])))
205
- : Effect.succeed([]);
206
- }
207
- function groupByReleaseType(releases) {
208
- return Effect.succeed(releases.reduce((releasesByType, release) => {
209
- const previous = setSemverRange('', String(release.instance.rawSpecifier.raw));
210
- const latest = release.versions.latest;
211
- try {
212
- const type = diff(previous, latest);
213
- if (type && releasesByType[type]) {
214
- releasesByType[type].push(release);
215
- }
216
- }
217
- catch {
218
- //
219
- }
220
- return releasesByType;
221
- }, {
222
- prepatch: [],
223
- patch: [],
224
- preminor: [],
225
- minor: [],
226
- premajor: [],
227
- major: [],
228
- prerelease: [],
229
- }));
230
- }
231
- // @TODO: add a cache with a short TTL on disk in $TMPDIR
232
- function fetchJson(url) {
233
- return pipe(Effect.async((resume) => {
234
- // setTimeout(
235
- // () => {
236
- // resume(
237
- // Effect.succeed(
238
- // JSON.stringify({
239
- // 'dist-tags': { latest: '3.1.1' },
240
- // 'time': {
241
- // '0.3.1': new Date().toJSON(),
242
- // },
243
- // }),
244
- // ),
245
- // );
246
- // },
247
- // Math.floor(Math.random() * 500) + 1,
248
- // );
249
- https
250
- .get(url, (res) => {
251
- let body = '';
252
- res.setEncoding('utf8');
253
- res.on('data', (chunk) => {
254
- body = `${body}${chunk}`;
255
- });
256
- res.on('end', () => {
257
- resume(Effect.succeed(body));
258
- });
259
- })
260
- .on('error', (err) => {
261
- resume(Effect.fail(new HttpError({ error: `Node https threw on ${url}: ${String(err)}` })));
262
- });
263
- }), Effect.flatMap((body) => Effect.try({
264
- try: () => JSON.parse(body),
265
- catch: () => new NpmRegistryError({ error: `JSON.parse threw on response from ${url}` }),
266
- })));
267
- }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,54 +0,0 @@
1
- #!/usr/bin/env node
2
- import chalk from 'chalk-template';
3
- import { program } from 'commander';
4
- import { Effect } from 'effect';
5
- import { io } from '../io/index.js';
6
- import { showHelpOnError } from '../lib/show-help-on-error.js';
7
- import { option } from '../option.js';
8
- import { update } from './update.js';
9
- program.description(' Update to the latest versions on the npm registry.');
10
- program.on('--help', () => {
11
- console.log(chalk `
12
- Examples:
13
- {dim # uses defaults for resolving packages}
14
- syncpack update
15
- {dim # uses packages defined by --source when provided}
16
- syncpack update --source {yellow "apps/*/package.json"}
17
- {dim # multiple globs can be provided like this}
18
- syncpack update --source {yellow "apps/*/package.json"} --source {yellow "core/*/package.json"}
19
- {dim # uses dependencies regular expression defined by --filter when provided}
20
- syncpack update --filter {yellow "typescript|tslint"}
21
- {dim # only inspect "devDependencies"}
22
- syncpack update --types dev
23
- {dim # only inspect "devDependencies" and "peerDependencies"}
24
- syncpack update --types dev,peer
25
-
26
- Resolving Packages:
27
- 1. If {yellow --source} globs are provided, use those.
28
- 2. If using Pnpm Workspaces, read {yellow packages} from {yellow pnpm-workspace.yaml} in the root of the project.
29
- 3. If using Yarn Workspaces, read {yellow workspaces} from {yellow package.json}.
30
- 4. If using Lerna, read {yellow packages} from {yellow lerna.json}.
31
- 5. Default to {yellow "package.json"} and {yellow "packages/*/package.json"}.
32
-
33
- Reference:
34
- globs {blue.underline https://github.com/isaacs/node-glob#glob-primer}
35
- lerna.json {blue.underline https://github.com/lerna/lerna#lernajson}
36
- Yarn Workspaces {blue.underline https://yarnpkg.com/lang/en/docs/workspaces}
37
- Pnpm Workspaces {blue.underline https://pnpm.js.org/en/workspaces}
38
- `);
39
- });
40
- showHelpOnError(program);
41
- program
42
- .option(...option.source)
43
- .option(...option.filter)
44
- .option(...option.config)
45
- .option(...option.specs)
46
- .option(...option.types)
47
- .parse(process.argv);
48
- Effect.runPromise(update(io, {
49
- configPath: program.opts().config,
50
- filter: program.opts().filter,
51
- source: program.opts().source,
52
- specs: program.opts().specs,
53
- types: program.opts().types,
54
- }));
@@ -1,6 +0,0 @@
1
- import { Effect } from 'effect';
2
- import { type CliConfig } from '../config/types.js';
3
- import type { ErrorHandlers } from '../error-handlers/default-error-handlers.js';
4
- import type { Io } from '../io/index.js';
5
- import { updateEffects } from './effects.js';
6
- export declare function update(io: Io, cli: Partial<CliConfig>, effects?: typeof updateEffects, errorHandlers?: ErrorHandlers): Effect.Effect<unknown, never, never>;
@@ -1,59 +0,0 @@
1
- import chalk from 'chalk-template';
2
- import { Context, Effect, flow, pipe } from 'effect';
3
- import { gtr } from 'semver';
4
- import { CliConfigTag } from '../config/tag.js';
5
- import { ICON } from '../constants.js';
6
- import { defaultErrorHandlers } from '../error-handlers/default-error-handlers.js';
7
- import { getContext } from '../get-context/index.js';
8
- import { getInstances } from '../get-instances/index.js';
9
- import { exitIfInvalid } from '../io/exit-if-invalid.js';
10
- import { IoTag } from '../io/index.js';
11
- import { writeIfChanged } from '../io/write-if-changed.js';
12
- import { withLogger } from '../lib/with-logger.js';
13
- import { Specifier } from '../specifier/index.js';
14
- import { updateEffects } from './effects.js';
15
- export function update(io, cli, effects = updateEffects, errorHandlers = defaultErrorHandlers) {
16
- return pipe(Effect.Do, Effect.bind('ctx', () => getContext({ io, cli, errorHandlers })), Effect.bind('instances', ({ ctx }) => getInstances(ctx, io, errorHandlers)), Effect.bind('update', ({ instances }) => pipe(Effect.succeed(instances.all), Effect.map((instances) => {
17
- const isVisitedByName = {};
18
- const updateable = [];
19
- instances.forEach((instance) => {
20
- if (!isVisitedByName[instance.name] &&
21
- (instance.versionGroup._tag === 'SameRange' ||
22
- instance.versionGroup._tag === 'Standard')) {
23
- const specifier = Specifier.create(instance, instance.rawSpecifier.raw);
24
- if (specifier._tag === 'Range' || specifier._tag === 'Exact') {
25
- isVisitedByName[instance.name] = true;
26
- updateable.push(instance);
27
- }
28
- }
29
- });
30
- return updateable;
31
- }), Effect.tap(updateEffects.onFetchAllStart), Effect.flatMap((instances) => pipe(instances, Effect.partition((instance) => pipe(Effect.succeed(instance), Effect.tap(() => updateEffects.onFetchStart(instance, instances.length)), Effect.flatMap(effects.fetchLatestVersions), Effect.tapBoth({
32
- onFailure: () => updateEffects.onFetchEnd(instance),
33
- onSuccess: ({ versions }) => updateEffects.onFetchEnd(instance, versions),
34
- }),
35
- // move up to date dependencies to error channel
36
- Effect.flatMap((updateable) => gtr(updateable.versions.latest, String(instance.rawSpecifier.raw))
37
- ? pipe(updateEffects.onOutdated(instance, updateable.versions.latest), Effect.map(() => updateable))
38
- : pipe(updateEffects.onUpToDate(instance), Effect.flatMap(() => Effect.fail(updateable)))),
39
- // log error but don't catch it
40
- Effect.tapErrorTag('HttpError', ({ error }) => Effect.logError(chalk `{red ${ICON.cross} ${error}}`)),
41
- // log error but don't catch it
42
- Effect.tapErrorTag('NpmRegistryError', ({ error }) => Effect.logError(chalk `{red ${ICON.cross} ${error}}`))), { concurrency: 10 }),
43
- // discard errors and up to date dependencies
44
- Effect.flatMap(([_, outOfDate]) => Effect.succeed(outOfDate)))),
45
- // always remove the spinner when we're done
46
- Effect.tapBoth({
47
- onFailure: updateEffects.onFetchAllEnd,
48
- onSuccess: updateEffects.onFetchAllEnd,
49
- }),
50
- // ask the user which updates they want
51
- Effect.flatMap(updateEffects.promptForUpdates),
52
- // if we think the user cancelled, say so
53
- Effect.catchTag('PromptCancelled', () => Effect.logInfo(chalk `{red ${ICON.panic}} aborting after {blue syncpack update} was cancelled`)))), Effect.flatMap(({ ctx }) => pipe(writeIfChanged(ctx), Effect.catchTags({
54
- WriteFileError: flow(errorHandlers.WriteFileError, Effect.map(() => {
55
- ctx.isInvalid = true;
56
- return ctx;
57
- })),
58
- }))), Effect.flatMap(exitIfInvalid), Effect.withConcurrency(10), Effect.provide(pipe(Context.empty(), Context.add(CliConfigTag, cli), Context.add(IoTag, io))), withLogger);
59
- }
package/dist/bin.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/bin.js DELETED
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env node
2
- import { program } from 'commander';
3
- import fs from 'fs';
4
- import path from 'path';
5
- import { fileURLToPath } from 'url';
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
- program
9
- .version(JSON.parse(fs.readFileSync(`${__dirname}/../package.json`, 'utf8')).version)
10
- .command('fix-mismatches', 'set dependencies used with different versions to the same version', {
11
- executableFile: './bin-fix-mismatches/index.js',
12
- })
13
- .command('format', 'sort and shorten properties according to a convention', {
14
- executableFile: './bin-format/index.js',
15
- })
16
- .command('lint', 'lint all versions and ranges', {
17
- executableFile: './bin-lint/index.js',
18
- })
19
- .command('lint-semver-ranges', 'check dependency versions comply with the given semver range format', {
20
- executableFile: './bin-lint-semver-ranges/index.js',
21
- })
22
- .command('list-mismatches', 'list every dependency used with different versions in your packages', {
23
- executableFile: './bin-list-mismatches/index.js',
24
- })
25
- .command('list', 'list every dependency used in your packages', {
26
- executableFile: './bin-list/index.js',
27
- })
28
- .command('prompt', 'fix mismatches which syncpack cannot fix automatically', {
29
- executableFile: './bin-prompt/index.js',
30
- })
31
- .command('set-semver-ranges', 'set semver ranges to the given format', {
32
- executableFile: './bin-set-semver-ranges/index.js',
33
- })
34
- .command('update', 'update to the latest versions on the npm registry', {
35
- executableFile: './bin-update/index.js',
36
- })
37
- .parse(process.argv);
@@ -1,19 +0,0 @@
1
- import { Effect } from 'effect';
2
- import type { Ctx } from '../get-context/index.js';
3
- import { NameAndVersionPropsStrategy } from '../strategy/name-and-version-props.js';
4
- import { NamedVersionStringStrategy } from '../strategy/named-version-string.js';
5
- import { UnnamedVersionStringStrategy } from '../strategy/unnamed-version-string.js';
6
- import { VersionsByNameStrategy } from '../strategy/versions-by-name.js';
7
- export declare namespace Strategy {
8
- type Any = NameAndVersionPropsStrategy | NamedVersionStringStrategy | UnnamedVersionStringStrategy | VersionsByNameStrategy;
9
- }
10
- declare const InvalidCustomTypeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
11
- readonly _tag: "InvalidCustomTypeError";
12
- };
13
- export declare class InvalidCustomTypeError extends InvalidCustomTypeError_base<{
14
- readonly config: unknown;
15
- readonly reason: string;
16
- }> {
17
- }
18
- export declare function getCustomTypes({ rcFile, }: Ctx['config']): Effect.Effect<Strategy.Any[], InvalidCustomTypeError>;
19
- export {};
@@ -1,50 +0,0 @@
1
- import { Data, Effect } from 'effect';
2
- import { isNonEmptyObject } from 'tightrope/guard/is-non-empty-object.js';
3
- import { isNonEmptyString } from 'tightrope/guard/is-non-empty-string.js';
4
- import { isObject } from 'tightrope/guard/is-object.js';
5
- import { DEFAULT_CONFIG } from '../constants.js';
6
- import { NameAndVersionPropsStrategy } from '../strategy/name-and-version-props.js';
7
- import { NamedVersionStringStrategy } from '../strategy/named-version-string.js';
8
- import { UnnamedVersionStringStrategy } from '../strategy/unnamed-version-string.js';
9
- import { VersionsByNameStrategy } from '../strategy/versions-by-name.js';
10
- export class InvalidCustomTypeError extends Data.TaggedClass('InvalidCustomTypeError') {
11
- }
12
- export function getCustomTypes({ rcFile, }) {
13
- if (!isNonEmptyObject(rcFile.customTypes))
14
- return Effect.succeed([]);
15
- return Effect.all([...Object.entries(rcFile.customTypes), ...Object.entries(DEFAULT_CONFIG.customTypes)].map(([name, config]) => {
16
- const ERR_OBJ = 'Invalid customType';
17
- const ERR_PATH = 'Invalid customType.path';
18
- const ERR_NAME_PATH = 'Invalid customType.namePath';
19
- const ERR_STRATEGY = 'Invalid customType.strategy';
20
- if (!isObject(config))
21
- return createError(config, ERR_OBJ);
22
- if (!isNonEmptyString(config.path))
23
- return createError(config, ERR_PATH);
24
- const path = config.path;
25
- const strategy = config.strategy;
26
- switch (strategy) {
27
- case 'name~version': {
28
- const namePath = config.namePath;
29
- if (!isNonEmptyString(namePath))
30
- return createError(config, ERR_NAME_PATH);
31
- return Effect.succeed(new NameAndVersionPropsStrategy(name, path, namePath));
32
- }
33
- case 'name@version': {
34
- return Effect.succeed(new NamedVersionStringStrategy(name, path));
35
- }
36
- case 'version': {
37
- return Effect.succeed(new UnnamedVersionStringStrategy(name, path));
38
- }
39
- case 'versionsByName': {
40
- return Effect.succeed(new VersionsByNameStrategy(name, path));
41
- }
42
- default: {
43
- return createError(config, ERR_STRATEGY);
44
- }
45
- }
46
- }));
47
- }
48
- function createError(config, reason) {
49
- return Effect.fail(new InvalidCustomTypeError({ config, reason }));
50
- }
@@ -1,17 +0,0 @@
1
- import { Effect } from 'effect';
2
- import type { Ctx } from '../get-context/index.js';
3
- import type { InvalidCustomTypeError, Strategy } from './get-custom-types.js';
4
- declare const DeprecatedTypesError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
5
- readonly _tag: "DeprecatedTypesError";
6
- };
7
- export declare class DeprecatedTypesError extends DeprecatedTypesError_base<{
8
- readonly types: string[];
9
- }> {
10
- }
11
- declare const RenamedWorkspaceTypeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
12
- readonly _tag: "RenamedWorkspaceTypeError";
13
- };
14
- export declare class RenamedWorkspaceTypeError extends RenamedWorkspaceTypeError_base<Record<string, never>> {
15
- }
16
- export declare function getEnabledTypes({ cli, rcFile, }: Ctx['config']): Effect.Effect<Strategy.Any[], DeprecatedTypesError | InvalidCustomTypeError | RenamedWorkspaceTypeError>;
17
- export {};
@@ -1,94 +0,0 @@
1
- import { Data, Effect, pipe } from 'effect';
2
- import { isArrayOfStrings } from 'tightrope/guard/is-array-of-strings.js';
3
- import { isBoolean } from 'tightrope/guard/is-boolean.js';
4
- import { isEmptyArray } from 'tightrope/guard/is-empty-array.js';
5
- import { isNonEmptyArray } from 'tightrope/guard/is-non-empty-array.js';
6
- import { isNonEmptyString } from 'tightrope/guard/is-non-empty-string.js';
7
- import { INTERNAL_TYPES } from '../constants.js';
8
- import { NameAndVersionPropsStrategy } from '../strategy/name-and-version-props.js';
9
- import { VersionsByNameStrategy } from '../strategy/versions-by-name.js';
10
- import { getCustomTypes } from './get-custom-types.js';
11
- export class DeprecatedTypesError extends Data.TaggedClass('DeprecatedTypesError') {
12
- }
13
- export class RenamedWorkspaceTypeError extends Data.TaggedClass('RenamedWorkspaceTypeError') {
14
- }
15
- export function getEnabledTypes({ cli, rcFile, }) {
16
- return pipe(
17
- // Look for dependency types defined using the old `{ prod: true }` syntax
18
- // deprecated in syncpack@9.0.0
19
- Effect.succeed(INTERNAL_TYPES.filter((key) => isBoolean(rcFile[key]))),
20
- // Short-circuit and quit if deprecated config is used
21
- Effect.flatMap((deprecatedTypeProps) => deprecatedTypeProps.length > 0
22
- ? Effect.fail(new DeprecatedTypesError({ types: deprecatedTypeProps }))
23
- : Effect.void), Effect.flatMap(() => pipe(Effect.Do,
24
- // Get index of every available strategy, keyed by their names as
25
- // they're referred to in config
26
- Effect.bind('allStrategiesByName', () => pipe(
27
- // Get custom types if any are defined, short-circuit and quit if
28
- // any are invalid
29
- getCustomTypes({ cli, rcFile }),
30
- // Combine them with the default/internal dependency types
31
- Effect.map((customTypes) => Object.fromEntries([
32
- ['dev', new VersionsByNameStrategy('dev', 'devDependencies')],
33
- ['local', new NameAndVersionPropsStrategy('local', 'version', 'name')],
34
- ['overrides', new VersionsByNameStrategy('overrides', 'overrides')],
35
- ['peer', new VersionsByNameStrategy('peer', 'peerDependencies')],
36
- ['pnpmOverrides', new VersionsByNameStrategy('pnpmOverrides', 'pnpm.overrides')],
37
- ['prod', new VersionsByNameStrategy('prod', 'dependencies')],
38
- ['resolutions', new VersionsByNameStrategy('resolutions', 'resolutions')],
39
- ...customTypes.map((type) => [type.name, type]),
40
- ])))),
41
- // The names of every available strategy
42
- Effect.bind('allStrategyNames', ({ allStrategiesByName }) => Effect.succeed(Object.keys(allStrategiesByName))),
43
- // Create groupings to assign each provided dependencyType to
44
- Effect.bind('strategyNamesByStatus', () => Effect.succeed({
45
- provided: (isNonEmptyString(cli.types)
46
- ? cli.types.split(',')
47
- : isArrayOfStrings(rcFile.dependencyTypes)
48
- ? rcFile.dependencyTypes
49
- : []).filter(isNonEmptyString),
50
- enabled: [],
51
- positive: [],
52
- negative: [],
53
- })))), Effect.tap(({ strategyNamesByStatus }) => Effect.logDebug(`dependency types provided by user: ${JSON.stringify(strategyNamesByStatus.provided)}`)),
54
- // Determine which dependencyTypes should be enabled based on:
55
- // * which are defined
56
- // * which were listed to be enabled
57
- // * which were listed but !negated
58
- // * etc.
59
- Effect.flatMap(({ allStrategiesByName, allStrategyNames, strategyNamesByStatus }) => {
60
- if (isEmptyArray(strategyNamesByStatus.provided) ||
61
- strategyNamesByStatus.provided.join('') === '**') {
62
- return Effect.succeed(allStrategyNames.map(getStrategyByName));
63
- }
64
- strategyNamesByStatus.provided.forEach((name) => {
65
- if (name.startsWith('!')) {
66
- strategyNamesByStatus.negative.push(name.replace('!', ''));
67
- }
68
- else {
69
- strategyNamesByStatus.positive.push(name);
70
- }
71
- });
72
- if (isNonEmptyArray(strategyNamesByStatus.negative)) {
73
- allStrategyNames.forEach((name) => {
74
- if (!strategyNamesByStatus.negative.includes(name)) {
75
- strategyNamesByStatus.enabled.push(name);
76
- }
77
- });
78
- }
79
- if (isNonEmptyArray(strategyNamesByStatus.positive)) {
80
- strategyNamesByStatus.positive.forEach((name) => {
81
- if (!strategyNamesByStatus.enabled.includes(name)) {
82
- strategyNamesByStatus.enabled.push(name);
83
- }
84
- });
85
- }
86
- if (strategyNamesByStatus.enabled.includes('workspace')) {
87
- return Effect.fail(new RenamedWorkspaceTypeError({}));
88
- }
89
- return Effect.succeed(strategyNamesByStatus.enabled.map(getStrategyByName));
90
- function getStrategyByName(type) {
91
- return allStrategiesByName[type];
92
- }
93
- }), Effect.tap((enabledTypes) => Effect.logDebug(`enabled dependency types determined to be: ${JSON.stringify(enabledTypes)}`)));
94
- }
@@ -1,2 +0,0 @@
1
- import type { Ctx } from '../get-context/index.js';
2
- export declare function getFilter({ cli, rcFile }: Ctx['config']): string;
@@ -1,10 +0,0 @@
1
- import { isNonEmptyString } from 'tightrope/guard/is-non-empty-string.js';
2
- import { DEFAULT_CONFIG } from '../constants.js';
3
- export function getFilter({ cli, rcFile }) {
4
- // @TODO Deprecate `filter` in .syncpackrc
5
- return isNonEmptyString(cli.filter)
6
- ? cli.filter
7
- : isNonEmptyString(rcFile.filter)
8
- ? rcFile.filter
9
- : DEFAULT_CONFIG.filter;
10
- }
@@ -1,2 +0,0 @@
1
- import type { Ctx } from '../get-context/index.js';
2
- export declare function getIndent({ cli, rcFile }: Ctx['config']): string;
@@ -1,9 +0,0 @@
1
- import { isNonEmptyString } from 'tightrope/guard/is-non-empty-string.js';
2
- import { DEFAULT_CONFIG } from '../constants.js';
3
- export function getIndent({ cli, rcFile }) {
4
- return isNonEmptyString(cli.indent)
5
- ? cli.indent.replaceAll('\\t', '\t')
6
- : isNonEmptyString(rcFile.indent)
7
- ? rcFile.indent
8
- : DEFAULT_CONFIG.indent;
9
- }
@@ -1,2 +0,0 @@
1
- import type { Ctx } from '../get-context/index.js';
2
- export declare function getSortAz({ rcFile }: Ctx['config']): string[];