typesync 0.14.2 → 0.14.3

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.
package/dist/cli.js CHANGED
@@ -1,14 +1,14 @@
1
- import { createConfigService, createPackageSource, createTypeSyncer, uniq } from "./type-syncer-CLrmNiXL.js";
1
+ import { createConfigService, createPackageSource, createTypeSyncer, uniq } from "./type-syncer-D40qMMFq.js";
2
2
  import * as path$1 from "node:path";
3
3
  import * as path from "node:path";
4
4
  import { InjectionMode, asFunction, createContainer } from "awilix";
5
- import chalk from "chalk";
6
- import { oraPromise } from "ora";
5
+ import { blue, bold, cyan, gray, green, magenta, red, white } from "ansis";
6
+ import { Spinner } from "picospinner";
7
+ import * as yaml from "yaml";
7
8
  import { glob } from "tinyglobby";
8
9
  import * as fsp from "node:fs/promises";
9
10
  import { readFile } from "node:fs/promises";
10
11
  import detectIndent from "detect-indent";
11
- import yaml from "js-yaml";
12
12
 
13
13
  //#region rolldown:runtime
14
14
  var __defProp = Object.defineProperty;
@@ -22,18 +22,25 @@ var __export = (target, all) => {
22
22
  //#endregion
23
23
  //#region src/cli-util.ts
24
24
  function log(message) {
25
- console.log(`${chalk.white("»")} ${chalk.gray(message)}`);
25
+ console.log(`${white`»`} ${gray(message)}`);
26
26
  }
27
27
  function success(text) {
28
- console.log(`${chalk.green("✔")} ${chalk.white(text)}`);
28
+ console.log(`${green`✔`} ${white(text)}`);
29
29
  }
30
30
  function error(err) {
31
31
  const msg = err instanceof Error ? err.message : err;
32
32
  const stack = err instanceof Error ? `\nStack:\n${err.stack}` : "";
33
- console.log(`${chalk.red("✖")} ${chalk.bgRed(chalk.white(msg))}${stack}`);
33
+ console.log(`${red`✖`} ${white.bgRed(msg)}${stack}`);
34
34
  }
35
35
  async function spinWhile(text, fn) {
36
- return await oraPromise(fn(), { text: ` ${chalk.gray(text)}` });
36
+ const spinner = new Spinner({
37
+ text: gray` ${text}`,
38
+ symbolFormatter: blue
39
+ });
40
+ spinner.start();
41
+ return await fn().finally(() => {
42
+ spinner.stop();
43
+ });
37
44
  }
38
45
  function parseArguments(argv) {
39
46
  const flags = {};
@@ -110,7 +117,7 @@ function createWorkspaceResolverService({ readFileContents: readFileContents$1 }
110
117
  try {
111
118
  const filePath = path$1.join(root, "pnpm-workspace.yaml");
112
119
  const contents = await readFileContents$1(filePath);
113
- const pnpmWorkspaces = yaml.load(contents);
120
+ const pnpmWorkspaces = yaml.parse(contents);
114
121
  return pnpmWorkspaces.packages;
115
122
  } catch {
116
123
  return void 0;
@@ -127,7 +134,7 @@ function ensureWorkspacesArray(data) {
127
134
  //#endregion
128
135
  //#region package.json
129
136
  var name = "typesync";
130
- var version = "0.14.2";
137
+ var version = "0.14.3";
131
138
  var type = "module";
132
139
  var description = "Install missing TypeScript typings for your dependencies.";
133
140
  var engines = { "node": "^18.20.0 || ^20.10.0 || >=22.0.0" };
@@ -147,7 +154,7 @@ var scripts = {
147
154
  "lint:watch": "nodemon --exec npm run lint",
148
155
  "build": "tsdown",
149
156
  "build:watch": "tsdown --watch",
150
- "run-cli": "npm run build && node bin/typesync",
157
+ "run-cli": "npm run build -- --silent && node bin/typesync",
151
158
  "run-cli:dry": "npm run run-cli -- --dry",
152
159
  "do:publish": "npm run lint && npm run test && npm run build && npm publish",
153
160
  "release:patch": "npm version patch && npm run do:publish && git push --follow-tags",
@@ -163,21 +170,20 @@ var license = "MIT";
163
170
  var bugs = { "url": "https://github.com/jeffijoe/typesync/issues" };
164
171
  var homepage = "https://github.com/jeffijoe/typesync#readme";
165
172
  var dependencies = {
173
+ "ansis": "^3.17.0",
166
174
  "awilix": "^12.0.5",
167
- "chalk": "^5.4.1",
168
- "cosmiconfig": "^9.0.0",
169
175
  "detect-indent": "^7.0.1",
170
- "js-yaml": "^4.1.0",
176
+ "lilconfig": "^3.1.3",
171
177
  "npm-registry-fetch": "^18.0.2",
172
- "ora": "^8.1.1",
178
+ "picospinner": "^3.0.0",
173
179
  "semver": "^7.7.0",
174
- "tinyglobby": "^0.2.12"
180
+ "tinyglobby": "^0.2.12",
181
+ "yaml": "^2.7.1"
175
182
  };
176
183
  var devDependencies = {
177
184
  "@eslint/js": "^9.23.0",
178
- "@types/js-yaml": "~4.0.9 || ~4.1.0",
179
185
  "@types/node": "^22.13.17",
180
- "@types/npm-registry-fetch": "^8.0.7 || ~17.1.0",
186
+ "@types/npm-registry-fetch": "^8.0.7 || ~18.0.0",
181
187
  "@types/semver": "~7.7.0",
182
188
  "@vitest/coverage-v8": "^3.1.1",
183
189
  "@vitest/ui": "^3.1.1",
@@ -242,19 +248,19 @@ async function run(syncer) {
242
248
  printHelp();
243
249
  return;
244
250
  }
245
- log(`TypeSync v${chalk.white(package_default.version)}`);
251
+ log(`TypeSync v${white(package_default.version)}`);
246
252
  if (flags.dry) log("—— DRY RUN — will not modify file ——");
247
- const result = await spinWhile(`Syncing type definitions in ${chalk.cyan(filePath)}...`, async () => await syncer.sync(filePath, flags));
253
+ const result = await spinWhile(`Syncing type definitions in ${cyan(filePath)}...`, async () => await syncer.sync(filePath, flags));
248
254
  const syncedFilesOutput = result.syncedFiles.map(renderSyncedFile).join("\n\n");
249
255
  const totals = result.syncedFiles.reduce((accum, f) => ({ newTypings: accum.newTypings + f.newTypings.length }), { newTypings: 0 });
250
- const syncMessage = `\n\n${syncedFilesOutput}\n\n✨ Run ${chalk.green("typesync")} again without the ${chalk.gray("--dry")} flag to update your ${chalk.gray("package.json")}.`;
256
+ const syncMessage = `\n\n${syncedFilesOutput}\n\n✨ Run ${green`typesync`} again without the ${gray`--dry`} flag to update your ${gray`package.json`}.`;
251
257
  if (flags.dry === "fail" && totals.newTypings > 0) {
252
258
  error("Typings changed; check failed.");
253
259
  log(syncMessage);
254
260
  process.exitCode = 1;
255
261
  return;
256
262
  }
257
- success(totals.newTypings === 0 ? `No new typings to add, looks like you're all synced up!` : flags.dry ? `${totals.newTypings.toString()} new typings can be added.${syncMessage}` : `${totals.newTypings.toString()} new typings added.\n\n${syncedFilesOutput}\n\n✨ Go ahead and run ${chalk.green("npm install")}, ${chalk.green("yarn")}, or ${chalk.green("pnpm i")} to install the packages that were added.`);
263
+ success(totals.newTypings === 0 ? `No new typings to add, looks like you're all synced up!` : flags.dry ? `${totals.newTypings.toString()} new typings can be added.${syncMessage}` : `${totals.newTypings.toString()} new typings added.\n\n${syncedFilesOutput}\n\n✨ Go ahead and run ${green`npm install`}, ${green`yarn`}, or ${green`pnpm i`} to install the packages that were added.`);
258
264
  }
259
265
  /**
260
266
  * Renders a type definition.
@@ -263,7 +269,7 @@ async function run(syncer) {
263
269
  */
264
270
  function renderTypeDef(typeDef, isLast) {
265
271
  const treeNode = isLast ? "└─" : "├─";
266
- return `${treeNode} ${chalk.green.bold("+")} ${chalk.gray("@types/")}${chalk.bold.blue(typeDef.typingsName)}`;
272
+ return `${treeNode} ${green.bold`+`} ${gray`@types/`}${bold.blue(typeDef.typingsName)}`;
267
273
  }
268
274
  /**
269
275
  * Renders a synced file.
@@ -271,9 +277,9 @@ function renderTypeDef(typeDef, isLast) {
271
277
  * @param file
272
278
  */
273
279
  function renderSyncedFile(file) {
274
- const badge = file.newTypings.length === 0 ? chalk.blue.bold("(no new typings added)") : chalk.green.bold(`(${file.newTypings.length.toString()} new typings added)`);
280
+ const badge = file.newTypings.length === 0 ? blue.bold`(no new typings added)` : green.bold`(${file.newTypings.length.toString()} new typings added)`;
275
281
  const dirName = path.basename(path.dirname(path.resolve(file.filePath)));
276
- const title = `📦 ${file.package.name ?? dirName} ${chalk.gray.italic(`— ${file.filePath}`)} ${badge}`;
282
+ const title = `📦 ${file.package.name ?? dirName} ${gray.italic`— ${file.filePath}`} ${badge}`;
277
283
  const nl = "\n";
278
284
  const combined = [...file.newTypings.map((t) => ({
279
285
  ...t,
@@ -287,12 +293,12 @@ function renderSyncedFile(file) {
287
293
  */
288
294
  function printHelp() {
289
295
  console.log(`
290
- ${chalk.blue.bold("typesync")} - adds missing TypeScript definitions to package.json
296
+ ${blue.bold`typesync`} - adds missing TypeScript definitions to package.json
291
297
 
292
298
  Options
293
- ${chalk.magenta.bold("--dry")} dry run, won't save the package.json
294
- ${chalk.magenta.bold("--ignoredeps=<deps|dev|peer|optional>")} ignores dependencies in the specified sections (comma separate for multiple). Example: ${chalk.magenta("ignoredeps=dev,peer")}
295
- ${chalk.magenta.bold("--help")} shows this help menu
299
+ ${magenta.bold`--dry`} dry run, won't save the package.json
300
+ ${magenta.bold`--ignoredeps=<deps|dev|peer|optional>`} ignores dependencies in the specified sections (comma separate for multiple). Example: ${magenta`ignoredeps=dev,peer`}
301
+ ${magenta.bold`--help`} shows this help menu
296
302
  `.trim());
297
303
  }
298
304
 
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":["message: string","text: string","err: Error | string","fn: () => Promise<T>","argv: Array<string>","flags: ICLIArguments['flags']","args: Array<string>","filePath: string","packageJson: IPackageFile","root: string","data?: IWorkspacesSection","syncer: ITypeSyncer","typeDef: IPackageTypingDescriptor","isLast: boolean","file: ISyncedFile"],"sources":["../src/cli-util.ts","../src/globber.ts","../src/fs-utils.ts","../src/package-json-file-service.ts","../src/workspace-resolver.ts","../package.json","../src/cli.ts"],"sourcesContent":["import chalk from 'chalk'\nimport { oraPromise } from 'ora'\nimport type { ICLIArguments } from './types'\n\n/**\n * Like regular console.log, but better.\n * @param message\n */\nexport function log(message: string): void {\n console.log(`${chalk.white('»')} ${chalk.gray(message)}`)\n}\n\n/**\n * Makes success feel even sweeter.\n * @param text\n */\nexport function success(text: string): void {\n console.log(`${chalk.green('✔')} ${chalk.white(text)}`)\n}\n\n/**\n * Logs an error all pretty.\n * @param err\n */\nexport function error(err: Error | string): void {\n const msg = err instanceof Error ? err.message : err\n const stack = err instanceof Error ? `\\nStack:\\n${err.stack}` : ''\n console.log(`${chalk.red('✖')} ${chalk.bgRed(chalk.white(msg))}${stack}`)\n}\n\n/**\n * Spins while doing work. Stops when done.\n * @param text\n * @param fn\n */\nexport async function spinWhile<T>(\n text: string,\n fn: () => Promise<T>,\n): Promise<T> {\n return await oraPromise(fn(), {\n text: ` ${chalk.gray(text)}`,\n })\n}\n\n/**\n * Super simple argument parser.\n * @param argv\n */\nexport function parseArguments(argv: Array<string>): ICLIArguments {\n const flags: ICLIArguments['flags'] = {}\n const args: Array<string> = []\n for (const arg of argv) {\n if (arg.startsWith('--')) {\n if (arg.includes('=')) {\n const idx = arg.indexOf('=')\n const afterEq = arg.substring(idx + 1)\n flags[arg.substring(2, idx)] = afterEq\n } else {\n flags[arg.substring(2)] = true\n }\n } else {\n args.push(arg)\n }\n }\n return { flags, args }\n}\n","import { glob } from 'tinyglobby'\nimport { uniq } from './util'\n\n/**\n * Globber interface.\n */\nexport interface IGlobber {\n /**\n * Globs for directory names.\n *\n * @param root\n */\n globDirs(\n this: void,\n root: string,\n patterns: Array<string>,\n ignore?: Array<string>,\n ): Promise<Array<string>>\n}\n\n/**\n * Creates a globber.\n */\nexport function createGlobber(): IGlobber {\n return {\n async globDirs(root, patterns, ignore = []): Promise<Array<string>> {\n const source = await glob(patterns, {\n cwd: root,\n ignore: ['**/node_modules/**', ...ignore],\n onlyDirectories: true,\n })\n\n return uniq(source)\n },\n }\n}\n","import { readFile } from 'node:fs/promises'\n\nexport async function readFileContents(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8')\n /* v8 ignore next */\n } catch (err) {\n /* v8 ignore next 3 */\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`${filePath} does not exist.`)\n }\n\n /* v8 ignore next 2 */\n throw err\n }\n}\n","import * as fsp from 'node:fs/promises'\nimport detectIndent from 'detect-indent'\nimport { readFileContents } from './fs-utils'\nimport type { IPackageFile } from './types'\n\n/**\n * File service.\n */\nexport interface IPackageJSONService {\n /**\n * Reads and parses JSON from the specified file. Path is relative to the current working directory.\n */\n readPackageFile(this: void, filePath: string): Promise<IPackageFile>\n /**\n * Writes the JSON to the specified file.\n */\n writePackageFile(\n this: void,\n filePath: string,\n fileContents: IPackageFile,\n ): Promise<void>\n}\n\nexport function createPackageJSONFileService(): IPackageJSONService {\n return {\n readPackageFile: async (filePath) => {\n const contents = await readFileContents(filePath)\n return JSON.parse(contents) as IPackageFile\n },\n writePackageFile: async (filePath, fileContent) => {\n const contents = await readFileContents(filePath)\n const { indent } = detectIndent(contents)\n const trailingNewline = contents.length ? contents.endsWith('\\n') : false\n const data = JSON.stringify(\n fileContent,\n null,\n indent /* v8 ignore next */ || ' ',\n )\n await fsp.writeFile(filePath, data + (trailingNewline ? '\\n' : ''))\n },\n }\n}\n","import * as path from 'node:path'\nimport yaml from 'js-yaml'\nimport type * as fsUtils from './fs-utils'\nimport type { IGlobber } from './globber'\nimport type { IPackageFile } from './types'\n\n/**\n * Service for fetching monorepo workspaces in a standardized format agnostic of the package manager used.\n * It is used to allow syncing all types in a workspace when run from the root of a monorepo.\n */\nexport interface IWorkspaceResolverService {\n /**\n * Reads, parses, and normalizes a workspaces configuration from the following files, in this order:\n * - `package.json` `workspaces` field, as an array of globs.\n * - `package.json` `workspaces` field, as an object with a `packages` field, which is an array of globs.\n * - `pnpm-workspace.yaml` `packages` field, as an array of globs.\n *\n * Path is relative to the current working directory.\n * Note that this returns a list of directories, not paths to the manifests themselves.\n */\n getWorkspaces(\n this: void,\n packageJson: IPackageFile,\n root: string,\n globber: IGlobber,\n ignored: IWorkspacesArray,\n ): Promise<IWorkspacesArray>\n}\n\n/**\n * @example\n * ```json\n * \"workspaces\": [\n * \"packages/*\",\n * ]\n * ```\n */\nexport type IWorkspacesArray = Array<string>\n\n/**\n * @example\n * ```yaml\n * packages:\n * - 'packages/*'\n * ```\n */\nexport interface IWorkspacesObject {\n packages?: IWorkspacesArray\n}\n\n/**\n * @see {@link IWorkspacesArray}\n */\nexport type NpmWorkspacesConfig = IWorkspacesArray\n\n/**\n * Yarn is a special snowflake.\n *\n * @example\n * ```json\n * \"workspaces\": {\n * \"packages\": [\n * \"packages/*\",\n * ],\n * \"nohoist\": []\n * }\n * ```\n */\nexport type YarnWorkspacesConfig =\n | IWorkspacesArray\n | (IWorkspacesObject & { nohoist?: Array<string> })\n\n/**\n * The contents of a `pnpm-workspace.yaml` file.\n *\n * @example\n * ```yaml\n * packages:\n * - 'packages/*'\n * ```\n */\nexport type PnpmWorkspacesConfig = IWorkspacesObject\n\n/**\n * @see {@link IWorkspacesArray}\n */\nexport type BunWorkspacesConfig = IWorkspacesArray\n\n/**\n * Section in `package.json` representing workspaces.\n */\nexport type IWorkspacesSection =\n | NpmWorkspacesConfig\n | YarnWorkspacesConfig\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents -- We want to explicitly enumerate each package manager's options.\n | BunWorkspacesConfig\n\nexport function createWorkspaceResolverService({\n readFileContents,\n}: {\n readFileContents: typeof fsUtils.readFileContents\n}): IWorkspaceResolverService {\n return {\n getWorkspaces: async (packageJson, root, globber, ignored) => {\n const workspaces = await getWorkspaces(packageJson, root)\n\n return await globber.globDirs(\n root,\n ensureWorkspacesArray(workspaces),\n ignored,\n )\n },\n }\n\n async function getWorkspaces(\n packageJson: IPackageFile,\n root: string,\n ): Promise<IWorkspacesSection | undefined> {\n const packageJsonWorkspaces = packageJson.workspaces\n if (packageJsonWorkspaces !== undefined) {\n return packageJsonWorkspaces\n }\n\n return await getPnpmWorkspaces(root)\n }\n\n async function getPnpmWorkspaces(\n root: string,\n ): Promise<IWorkspacesArray | undefined> {\n try {\n const filePath = path.join(root, 'pnpm-workspace.yaml')\n const contents = await readFileContents(filePath)\n const pnpmWorkspaces = yaml.load(contents) as PnpmWorkspacesConfig\n\n return pnpmWorkspaces.packages\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Ensures that we have a valid workspaces array.\n *\n * @param data\n */\nexport function ensureWorkspacesArray(\n data?: IWorkspacesSection,\n): IWorkspacesArray {\n if (!data) {\n return []\n }\n\n if (!Array.isArray(data)) {\n return ensureWorkspacesArray(data.packages)\n }\n\n if (!data.every((s) => typeof s === 'string')) {\n return []\n }\n\n return data\n}\n","{\n \"name\": \"typesync\",\n \"version\": \"0.14.2\",\n \"type\": \"module\",\n \"description\": \"Install missing TypeScript typings for your dependencies.\",\n \"engines\": {\n \"node\": \"^18.20.0 || ^20.10.0 || >=22.0.0\"\n },\n \"files\": [\n \"dist\",\n \"bin\"\n ],\n \"bin\": {\n \"typesync\": \"./bin/typesync\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest --ui\",\n \"fix\": \"eslint --fix && npm run format\",\n \"lint\": \"eslint && tsc && npm run format:check\",\n \"format\": \"prettier --write 'src/**/*.ts'\",\n \"format:check\": \"prettier --check 'src/**/*.ts'\",\n \"lint:watch\": \"nodemon --exec npm run lint\",\n \"build\": \"tsdown\",\n \"build:watch\": \"tsdown --watch\",\n \"run-cli\": \"npm run build && node bin/typesync\",\n \"run-cli:dry\": \"npm run run-cli -- --dry\",\n \"do:publish\": \"npm run lint && npm run test && npm run build && npm publish\",\n \"release:patch\": \"npm version patch && npm run do:publish && git push --follow-tags\",\n \"release:minor\": \"npm version minor && npm run do:publish && git push --follow-tags\",\n \"release:prerelease\": \"npm version prerelease && npm run do:publish && git push --follow-tags\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jeffijoe/typesync.git\"\n },\n \"author\": \"Jeff Hansen <jeff@jeffijoe.com>\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/jeffijoe/typesync/issues\"\n },\n \"homepage\": \"https://github.com/jeffijoe/typesync#readme\",\n \"dependencies\": {\n \"awilix\": \"^12.0.5\",\n \"chalk\": \"^5.4.1\",\n \"cosmiconfig\": \"^9.0.0\",\n \"detect-indent\": \"^7.0.1\",\n \"js-yaml\": \"^4.1.0\",\n \"npm-registry-fetch\": \"^18.0.2\",\n \"ora\": \"^8.1.1\",\n \"semver\": \"^7.7.0\",\n \"tinyglobby\": \"^0.2.12\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.23.0\",\n \"@types/js-yaml\": \"~4.0.9 || ~4.1.0\",\n \"@types/node\": \"^22.13.17\",\n \"@types/npm-registry-fetch\": \"^8.0.7 || ~17.1.0\",\n \"@types/semver\": \"~7.7.0\",\n \"@vitest/coverage-v8\": \"^3.1.1\",\n \"@vitest/ui\": \"^3.1.1\",\n \"eslint\": \"^9.23.0\",\n \"globals\": \"^16.0.0\",\n \"nodemon\": \"^3.1.9\",\n \"prettier\": \"^3.5.3\",\n \"publint\": \"^0.3.9\",\n \"tsdown\": \"^0.7.2\",\n \"typescript\": \"^5.8.2\",\n \"typescript-eslint\": \"^8.29.0\",\n \"unplugin-unused\": \"^0.4.4\",\n \"vitest\": \"^3.1.1\"\n },\n \"packageManager\": \"npm@10.8.2\"\n}\n","import * as path from 'node:path'\nimport { asFunction, createContainer, InjectionMode } from 'awilix'\nimport chalk from 'chalk'\nimport * as C from './cli-util'\nimport { createConfigService } from './config-service'\nimport { createGlobber } from './globber'\nimport { createPackageJSONFileService } from './package-json-file-service'\nimport { createPackageSource } from './package-source'\nimport { createTypeSyncer } from './type-syncer'\nimport type {\n IPackageTypingDescriptor,\n ISyncedFile,\n ITypeSyncer,\n} from './types'\nimport { createWorkspaceResolverService } from './workspace-resolver'\nimport * as fsUtils from './fs-utils'\nimport packageJson from '../package.json' with { type: 'json' }\n\n/**\n * Starts the TypeSync CLI.\n */\nexport async function startCli(): Promise<void> {\n try {\n // Awilix is a dependency injection container.\n const container = createContainer({\n injectionMode: InjectionMode.CLASSIC,\n }).register({\n packageJSONService: asFunction(createPackageJSONFileService).singleton(),\n workspaceResolverService: asFunction(() =>\n createWorkspaceResolverService(fsUtils),\n ).singleton(),\n packageSource: asFunction(createPackageSource).singleton(),\n configService: asFunction(createConfigService).singleton(),\n globber: asFunction(createGlobber).singleton(),\n typeSyncer: asFunction(createTypeSyncer),\n })\n await run(container.resolve<ITypeSyncer>('typeSyncer'))\n } catch (err) {\n C.error(err as any)\n process.exitCode = 1\n }\n}\n\n/**\n * Actual CLI runner. Uses the `syncer` instance to sync.\n * @param syncer\n */\nasync function run(syncer: ITypeSyncer) {\n const { args, flags } = C.parseArguments(process.argv.slice(2))\n const [filePath = 'package.json'] = args\n if (flags.help) {\n printHelp()\n return\n }\n\n C.log(`TypeSync v${chalk.white(packageJson.version)}`)\n if (flags.dry) {\n C.log('—— DRY RUN — will not modify file ——')\n }\n const result = await C.spinWhile(\n `Syncing type definitions in ${chalk.cyan(filePath)}...`,\n async () => await syncer.sync(filePath, flags),\n )\n\n const syncedFilesOutput = result.syncedFiles\n .map(renderSyncedFile)\n .join('\\n\\n')\n const totals = result.syncedFiles.reduce(\n (accum, f) => ({\n newTypings: accum.newTypings + f.newTypings.length,\n }),\n { newTypings: 0 },\n )\n\n const syncMessage = `\\n\\n${syncedFilesOutput}\\n\\n✨ Run ${chalk.green('typesync')} again without the ${chalk.gray('--dry')} flag to update your ${chalk.gray('package.json')}.`\n if (flags.dry === 'fail' && totals.newTypings > 0) {\n C.error('Typings changed; check failed.')\n C.log(syncMessage)\n process.exitCode = 1\n return\n }\n C.success(\n totals.newTypings === 0\n ? `No new typings to add, looks like you're all synced up!`\n : flags.dry\n ? `${totals.newTypings.toString()} new typings can be added.${syncMessage}`\n : `${totals.newTypings.toString()} new typings added.\\n\\n${syncedFilesOutput}\\n\\n✨ Go ahead and run ${chalk.green('npm install')}, ${chalk.green('yarn')}, or ${chalk.green('pnpm i')} to install the packages that were added.`,\n )\n}\n\n/**\n * Renders a type definition.\n * @param typeDef\n * @param isLast\n */\nfunction renderTypeDef(typeDef: IPackageTypingDescriptor, isLast: boolean) {\n const treeNode = isLast ? '└─' : '├─'\n return `${treeNode} ${chalk.green.bold('+')} ${chalk.gray('@types/')}${chalk.bold.blue(typeDef.typingsName)}`\n}\n\n/**\n * Renders a synced file.\n *\n * @param file\n */\nfunction renderSyncedFile(file: ISyncedFile) {\n const badge =\n file.newTypings.length === 0\n ? chalk.blue.bold('(no new typings added)')\n : chalk.green.bold(\n `(${file.newTypings.length.toString()} new typings added)`,\n )\n\n const dirName = path.basename(path.dirname(path.resolve(file.filePath)))\n const title = `📦 ${file.package.name ?? dirName} ${chalk.gray.italic(\n `— ${file.filePath}`,\n )} ${badge}`\n\n const nl = '\\n'\n const combined = [...file.newTypings.map((t) => ({ ...t, action: 'add' }))]\n const rendered =\n title +\n nl +\n combined\n .map((t) => renderTypeDef(t, combined[combined.length - 1] === t))\n .join(nl)\n\n return rendered\n}\n\n/**\n * Prints the help text.\n */\nfunction printHelp() {\n console.log(\n `\n${chalk.blue.bold('typesync')} - adds missing TypeScript definitions to package.json\n\nOptions\n ${chalk.magenta.bold('--dry')} dry run, won't save the package.json\n ${chalk.magenta.bold('--ignoredeps=<deps|dev|peer|optional>')} ignores dependencies in the specified sections (comma separate for multiple). Example: ${chalk.magenta('ignoredeps=dev,peer')}\n ${chalk.magenta.bold('--help')} shows this help menu\n `.trim(),\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":["message: string","text: string","err: Error | string","fn: () => Promise<T>","argv: Array<string>","flags: ICLIArguments['flags']","args: Array<string>","filePath: string","packageJson: IPackageFile","root: string","data?: IWorkspacesSection","syncer: ITypeSyncer","typeDef: IPackageTypingDescriptor","isLast: boolean","file: ISyncedFile"],"sources":["../src/cli-util.ts","../src/globber.ts","../src/fs-utils.ts","../src/package-json-file-service.ts","../src/workspace-resolver.ts","../package.json","../src/cli.ts"],"sourcesContent":["import { white, gray, green, red, blue } from 'ansis'\nimport { Spinner } from 'picospinner'\nimport type { ICLIArguments } from './types'\n\n/**\n * Like regular console.log, but better.\n * @param message\n */\nexport function log(message: string): void {\n console.log(`${white`»`} ${gray(message)}`)\n}\n\n/**\n * Makes success feel even sweeter.\n * @param text\n */\nexport function success(text: string): void {\n console.log(`${green`✔`} ${white(text)}`)\n}\n\n/**\n * Logs an error all pretty.\n * @param err\n */\nexport function error(err: Error | string): void {\n const msg = err instanceof Error ? err.message : err\n const stack = err instanceof Error ? `\\nStack:\\n${err.stack}` : ''\n console.log(`${red`✖`} ${white.bgRed(msg)}${stack}`)\n}\n\n/**\n * Spins while doing work. Stops when done.\n * @param text\n * @param fn\n */\nexport async function spinWhile<T>(\n text: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const spinner = new Spinner({ text: gray` ${text}`, symbolFormatter: blue })\n spinner.start()\n\n return await fn().finally(() => {\n spinner.stop()\n })\n}\n\n/**\n * Super simple argument parser.\n * @param argv\n */\nexport function parseArguments(argv: Array<string>): ICLIArguments {\n const flags: ICLIArguments['flags'] = {}\n const args: Array<string> = []\n for (const arg of argv) {\n if (arg.startsWith('--')) {\n if (arg.includes('=')) {\n const idx = arg.indexOf('=')\n const afterEq = arg.substring(idx + 1)\n flags[arg.substring(2, idx)] = afterEq\n } else {\n flags[arg.substring(2)] = true\n }\n } else {\n args.push(arg)\n }\n }\n return { flags, args }\n}\n","import { glob } from 'tinyglobby'\nimport { uniq } from './util'\n\n/**\n * Globber interface.\n */\nexport interface IGlobber {\n /**\n * Globs for directory names.\n *\n * @param root\n */\n globDirs(\n this: void,\n root: string,\n patterns: Array<string>,\n ignore?: Array<string>,\n ): Promise<Array<string>>\n}\n\n/**\n * Creates a globber.\n */\nexport function createGlobber(): IGlobber {\n return {\n async globDirs(root, patterns, ignore = []): Promise<Array<string>> {\n const source = await glob(patterns, {\n cwd: root,\n ignore: ['**/node_modules/**', ...ignore],\n onlyDirectories: true,\n })\n\n return uniq(source)\n },\n }\n}\n","import { readFile } from 'node:fs/promises'\n\nexport async function readFileContents(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8')\n /* v8 ignore next */\n } catch (err) {\n /* v8 ignore next 3 */\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`${filePath} does not exist.`)\n }\n\n /* v8 ignore next 2 */\n throw err\n }\n}\n","import * as fsp from 'node:fs/promises'\nimport detectIndent from 'detect-indent'\nimport { readFileContents } from './fs-utils'\nimport type { IPackageFile } from './types'\n\n/**\n * File service.\n */\nexport interface IPackageJSONService {\n /**\n * Reads and parses JSON from the specified file. Path is relative to the current working directory.\n */\n readPackageFile(this: void, filePath: string): Promise<IPackageFile>\n /**\n * Writes the JSON to the specified file.\n */\n writePackageFile(\n this: void,\n filePath: string,\n fileContents: IPackageFile,\n ): Promise<void>\n}\n\nexport function createPackageJSONFileService(): IPackageJSONService {\n return {\n readPackageFile: async (filePath) => {\n const contents = await readFileContents(filePath)\n return JSON.parse(contents) as IPackageFile\n },\n writePackageFile: async (filePath, fileContent) => {\n const contents = await readFileContents(filePath)\n const { indent } = detectIndent(contents)\n const trailingNewline = contents.length ? contents.endsWith('\\n') : false\n const data = JSON.stringify(\n fileContent,\n null,\n indent /* v8 ignore next */ || ' ',\n )\n await fsp.writeFile(filePath, data + (trailingNewline ? '\\n' : ''))\n },\n }\n}\n","import * as path from 'node:path'\nimport * as yaml from 'yaml'\nimport type * as fsUtils from './fs-utils'\nimport type { IGlobber } from './globber'\nimport type { IPackageFile } from './types'\n\n/**\n * Service for fetching monorepo workspaces in a standardized format agnostic of the package manager used.\n * It is used to allow syncing all types in a workspace when run from the root of a monorepo.\n */\nexport interface IWorkspaceResolverService {\n /**\n * Reads, parses, and normalizes a workspaces configuration from the following files, in this order:\n * - `package.json` `workspaces` field, as an array of globs.\n * - `package.json` `workspaces` field, as an object with a `packages` field, which is an array of globs.\n * - `pnpm-workspace.yaml` `packages` field, as an array of globs.\n *\n * Path is relative to the current working directory.\n * Note that this returns a list of directories, not paths to the manifests themselves.\n */\n getWorkspaces(\n this: void,\n packageJson: IPackageFile,\n root: string,\n globber: IGlobber,\n ignored: IWorkspacesArray,\n ): Promise<IWorkspacesArray>\n}\n\n/**\n * @example\n * ```json\n * \"workspaces\": [\n * \"packages/*\",\n * ]\n * ```\n */\nexport type IWorkspacesArray = Array<string>\n\n/**\n * @example\n * ```yaml\n * packages:\n * - 'packages/*'\n * ```\n */\nexport interface IWorkspacesObject {\n packages?: IWorkspacesArray\n}\n\n/**\n * @see {@link IWorkspacesArray}\n */\nexport type NpmWorkspacesConfig = IWorkspacesArray\n\n/**\n * Yarn is a special snowflake.\n *\n * @example\n * ```json\n * \"workspaces\": {\n * \"packages\": [\n * \"packages/*\",\n * ],\n * \"nohoist\": []\n * }\n * ```\n */\nexport type YarnWorkspacesConfig =\n | IWorkspacesArray\n | (IWorkspacesObject & { nohoist?: Array<string> })\n\n/**\n * The contents of a `pnpm-workspace.yaml` file.\n *\n * @example\n * ```yaml\n * packages:\n * - 'packages/*'\n * ```\n */\nexport type PnpmWorkspacesConfig = IWorkspacesObject\n\n/**\n * @see {@link IWorkspacesArray}\n */\nexport type BunWorkspacesConfig = IWorkspacesArray\n\n/**\n * Section in `package.json` representing workspaces.\n */\nexport type IWorkspacesSection =\n | NpmWorkspacesConfig\n | YarnWorkspacesConfig\n // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents -- We want to explicitly enumerate each package manager's options.\n | BunWorkspacesConfig\n\nexport function createWorkspaceResolverService({\n readFileContents,\n}: {\n readFileContents: typeof fsUtils.readFileContents\n}): IWorkspaceResolverService {\n return {\n getWorkspaces: async (packageJson, root, globber, ignored) => {\n const workspaces = await getWorkspaces(packageJson, root)\n\n return await globber.globDirs(\n root,\n ensureWorkspacesArray(workspaces),\n ignored,\n )\n },\n }\n\n async function getWorkspaces(\n packageJson: IPackageFile,\n root: string,\n ): Promise<IWorkspacesSection | undefined> {\n const packageJsonWorkspaces = packageJson.workspaces\n if (packageJsonWorkspaces !== undefined) {\n return packageJsonWorkspaces\n }\n\n return await getPnpmWorkspaces(root)\n }\n\n async function getPnpmWorkspaces(\n root: string,\n ): Promise<IWorkspacesArray | undefined> {\n try {\n const filePath = path.join(root, 'pnpm-workspace.yaml')\n const contents = await readFileContents(filePath)\n const pnpmWorkspaces = yaml.parse(\n contents,\n ) as unknown as PnpmWorkspacesConfig\n\n return pnpmWorkspaces.packages\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Ensures that we have a valid workspaces array.\n *\n * @param data\n */\nexport function ensureWorkspacesArray(\n data?: IWorkspacesSection,\n): IWorkspacesArray {\n if (!data) {\n return []\n }\n\n if (!Array.isArray(data)) {\n return ensureWorkspacesArray(data.packages)\n }\n\n if (!data.every((s) => typeof s === 'string')) {\n return []\n }\n\n return data\n}\n","{\n \"name\": \"typesync\",\n \"version\": \"0.14.3\",\n \"type\": \"module\",\n \"description\": \"Install missing TypeScript typings for your dependencies.\",\n \"engines\": {\n \"node\": \"^18.20.0 || ^20.10.0 || >=22.0.0\"\n },\n \"files\": [\n \"dist\",\n \"bin\"\n ],\n \"bin\": {\n \"typesync\": \"./bin/typesync\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest --ui\",\n \"fix\": \"eslint --fix && npm run format\",\n \"lint\": \"eslint && tsc && npm run format:check\",\n \"format\": \"prettier --write 'src/**/*.ts'\",\n \"format:check\": \"prettier --check 'src/**/*.ts'\",\n \"lint:watch\": \"nodemon --exec npm run lint\",\n \"build\": \"tsdown\",\n \"build:watch\": \"tsdown --watch\",\n \"run-cli\": \"npm run build -- --silent && node bin/typesync\",\n \"run-cli:dry\": \"npm run run-cli -- --dry\",\n \"do:publish\": \"npm run lint && npm run test && npm run build && npm publish\",\n \"release:patch\": \"npm version patch && npm run do:publish && git push --follow-tags\",\n \"release:minor\": \"npm version minor && npm run do:publish && git push --follow-tags\",\n \"release:prerelease\": \"npm version prerelease && npm run do:publish && git push --follow-tags\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jeffijoe/typesync.git\"\n },\n \"author\": \"Jeff Hansen <jeff@jeffijoe.com>\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/jeffijoe/typesync/issues\"\n },\n \"homepage\": \"https://github.com/jeffijoe/typesync#readme\",\n \"dependencies\": {\n \"ansis\": \"^3.17.0\",\n \"awilix\": \"^12.0.5\",\n \"detect-indent\": \"^7.0.1\",\n \"lilconfig\": \"^3.1.3\",\n \"npm-registry-fetch\": \"^18.0.2\",\n \"picospinner\": \"^3.0.0\",\n \"semver\": \"^7.7.0\",\n \"tinyglobby\": \"^0.2.12\",\n \"yaml\": \"^2.7.1\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.23.0\",\n \"@types/node\": \"^22.13.17\",\n \"@types/npm-registry-fetch\": \"^8.0.7 || ~18.0.0\",\n \"@types/semver\": \"~7.7.0\",\n \"@vitest/coverage-v8\": \"^3.1.1\",\n \"@vitest/ui\": \"^3.1.1\",\n \"eslint\": \"^9.23.0\",\n \"globals\": \"^16.0.0\",\n \"nodemon\": \"^3.1.9\",\n \"prettier\": \"^3.5.3\",\n \"publint\": \"^0.3.9\",\n \"tsdown\": \"^0.7.2\",\n \"typescript\": \"^5.8.2\",\n \"typescript-eslint\": \"^8.29.0\",\n \"unplugin-unused\": \"^0.4.4\",\n \"vitest\": \"^3.1.1\"\n },\n \"packageManager\": \"npm@10.8.2\"\n}\n","import * as path from 'node:path'\nimport { asFunction, createContainer, InjectionMode } from 'awilix'\nimport { blue, bold, cyan, gray, green, magenta, white } from 'ansis'\nimport * as C from './cli-util'\nimport { createConfigService } from './config-service'\nimport { createGlobber } from './globber'\nimport { createPackageJSONFileService } from './package-json-file-service'\nimport { createPackageSource } from './package-source'\nimport { createTypeSyncer } from './type-syncer'\nimport type {\n IPackageTypingDescriptor,\n ISyncedFile,\n ITypeSyncer,\n} from './types'\nimport { createWorkspaceResolverService } from './workspace-resolver'\nimport * as fsUtils from './fs-utils'\nimport packageJson from '../package.json' with { type: 'json' }\n\n/**\n * Starts the TypeSync CLI.\n */\nexport async function startCli(): Promise<void> {\n try {\n // Awilix is a dependency injection container.\n const container = createContainer({\n injectionMode: InjectionMode.CLASSIC,\n }).register({\n packageJSONService: asFunction(createPackageJSONFileService).singleton(),\n workspaceResolverService: asFunction(() =>\n createWorkspaceResolverService(fsUtils),\n ).singleton(),\n packageSource: asFunction(createPackageSource).singleton(),\n configService: asFunction(createConfigService).singleton(),\n globber: asFunction(createGlobber).singleton(),\n typeSyncer: asFunction(createTypeSyncer),\n })\n await run(container.resolve<ITypeSyncer>('typeSyncer'))\n } catch (err) {\n C.error(err as any)\n process.exitCode = 1\n }\n}\n\n/**\n * Actual CLI runner. Uses the `syncer` instance to sync.\n * @param syncer\n */\nasync function run(syncer: ITypeSyncer) {\n const { args, flags } = C.parseArguments(process.argv.slice(2))\n const [filePath = 'package.json'] = args\n if (flags.help) {\n printHelp()\n return\n }\n\n C.log(`TypeSync v${white(packageJson.version)}`)\n if (flags.dry) {\n C.log('—— DRY RUN — will not modify file ——')\n }\n const result = await C.spinWhile(\n `Syncing type definitions in ${cyan(filePath)}...`,\n async () => await syncer.sync(filePath, flags),\n )\n\n const syncedFilesOutput = result.syncedFiles\n .map(renderSyncedFile)\n .join('\\n\\n')\n const totals = result.syncedFiles.reduce(\n (accum, f) => ({\n newTypings: accum.newTypings + f.newTypings.length,\n }),\n { newTypings: 0 },\n )\n\n const syncMessage = `\\n\\n${syncedFilesOutput}\\n\\n✨ Run ${green`typesync`} again without the ${gray`--dry`} flag to update your ${gray`package.json`}.`\n if (flags.dry === 'fail' && totals.newTypings > 0) {\n C.error('Typings changed; check failed.')\n C.log(syncMessage)\n process.exitCode = 1\n return\n }\n C.success(\n totals.newTypings === 0\n ? `No new typings to add, looks like you're all synced up!`\n : flags.dry\n ? `${totals.newTypings.toString()} new typings can be added.${syncMessage}`\n : `${totals.newTypings.toString()} new typings added.\\n\\n${syncedFilesOutput}\\n\\n✨ Go ahead and run ${green`npm install`}, ${green`yarn`}, or ${green`pnpm i`} to install the packages that were added.`,\n )\n}\n\n/**\n * Renders a type definition.\n * @param typeDef\n * @param isLast\n */\nfunction renderTypeDef(typeDef: IPackageTypingDescriptor, isLast: boolean) {\n const treeNode = isLast ? '└─' : '├─'\n return `${treeNode} ${green.bold`+`} ${gray`@types/`}${bold.blue(typeDef.typingsName)}`\n}\n\n/**\n * Renders a synced file.\n *\n * @param file\n */\nfunction renderSyncedFile(file: ISyncedFile) {\n const badge =\n file.newTypings.length === 0\n ? blue.bold`(no new typings added)`\n : green.bold`(${file.newTypings.length.toString()} new typings added)`\n\n const dirName = path.basename(path.dirname(path.resolve(file.filePath)))\n const title = `📦 ${file.package.name ?? dirName} ${gray.italic`— ${file.filePath}`} ${badge}`\n\n const nl = '\\n'\n const combined = [...file.newTypings.map((t) => ({ ...t, action: 'add' }))]\n const rendered =\n title +\n nl +\n combined\n .map((t) => renderTypeDef(t, combined[combined.length - 1] === t))\n .join(nl)\n\n return rendered\n}\n\n/**\n * Prints the help text.\n */\nfunction printHelp() {\n console.log(\n `\n${blue.bold`typesync`} - adds missing TypeScript definitions to package.json\n\nOptions\n ${magenta.bold`--dry`} dry run, won't save the package.json\n ${magenta.bold`--ignoredeps=<deps|dev|peer|optional>`} ignores dependencies in the specified sections (comma separate for multiple). Example: ${magenta`ignoredeps=dev,peer`}\n ${magenta.bold`--help`} shows this help menu\n `.trim(),\n )\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-CLrmNiXL.js";
1
+ import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-D40qMMFq.js";
2
2
 
3
3
  export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer };
@@ -1,6 +1,7 @@
1
1
  import * as path$1 from "node:path";
2
2
  import * as path from "node:path";
3
- import { cosmiconfig } from "cosmiconfig";
3
+ import { defaultLoaders, lilconfig } from "lilconfig";
4
+ import * as yaml from "yaml";
4
5
  import fetch from "npm-registry-fetch";
5
6
  import { compare, parse } from "semver";
6
7
 
@@ -63,7 +64,37 @@ function memoizeAsync(fn) {
63
64
 
64
65
  //#endregion
65
66
  //#region src/config-service.ts
66
- const explorer = cosmiconfig("typesync");
67
+ async function loadYaml(_filepath, content) {
68
+ return await yaml.parse(content);
69
+ }
70
+ function searchPlaces(moduleName) {
71
+ const rcs = [
72
+ `.${moduleName}rc`,
73
+ `.${moduleName}rc.json`,
74
+ `.${moduleName}rc.yaml`,
75
+ `.${moduleName}rc.yml`,
76
+ `.${moduleName}rc.js`,
77
+ `.${moduleName}rc.mjs`,
78
+ `.${moduleName}rc.cjs`
79
+ ];
80
+ return [
81
+ "package.json",
82
+ ...rcs,
83
+ ...rcs.map((rc) => `.config/${rc}`),
84
+ `${moduleName}.config.js`,
85
+ `${moduleName}.config.mjs`,
86
+ `${moduleName}.config.cjs`
87
+ ];
88
+ }
89
+ const explorer = lilconfig("typesync", {
90
+ searchPlaces: searchPlaces("typesync"),
91
+ loaders: {
92
+ ...defaultLoaders,
93
+ ".yml": loadYaml,
94
+ ".yaml": loadYaml,
95
+ noExt: loadYaml
96
+ }
97
+ });
67
98
  function createConfigService() {
68
99
  return { readConfig: async (filePath, flags) => {
69
100
  const fileConfig = await explorer.search(path$1.dirname(filePath)).then((result) => result?.config ?? {});
@@ -312,4 +343,4 @@ function getDependenciesBySection(file, section) {
312
343
 
313
344
  //#endregion
314
345
  export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer, uniq };
315
- //# sourceMappingURL=type-syncer-CLrmNiXL.js.map
346
+ //# sourceMappingURL=type-syncer-D40qMMFq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-syncer-D40qMMFq.js","names":["source: Array<T>","source: T","object: Partial<T>","name: string","comparer?: (a: string, b: string) => number","result: Record<string, U>","fn: (...args: U) => Promise<V>","_filepath: string","content: string","moduleName: string","filePath: string","flags: ICLIArguments['flags']","fileConfig: ISyncOptions","key: string","validator?: (value: string) => boolean","value: string","availableVersions: Array<IPackageVersionInfo>","version: string","packageJSONService: IPackageJSONService","workspaceResolverService: IWorkspaceResolverService","packageSource: IPackageSource","configService: IConfigService","globber: IGlobber","filePath: string","flags: ICLIArguments['flags']","syncedFiles: Array<ISyncedFile>","ignoredWorkspaces: IWorkspacesArray","file: IPackageFile","opts: ISyncOptions","dryRun: boolean","used: ReturnType<typeof getPotentiallyUntypedPackages>","newPackageFile: IPackageFile","allPackageNames: Array<string>","packageName: string","section: IDependenciesSection","ignoredSection?: boolean","ignorePackages?: Array<string>","section: IDependencySection"],"sources":["../src/types.ts","../src/util.ts","../src/config-service.ts","../src/package-source.ts","../src/versioning.ts","../src/type-syncer.ts"],"sourcesContent":["import type { IWorkspacesArray, IWorkspacesSection } from './workspace-resolver'\n\n/**\n * The guts of the program.\n */\nexport interface ITypeSyncer {\n sync(\n this: void,\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncResult>\n}\n\n/**\n * Sync options.\n */\nexport interface ISyncOptions {\n /**\n * Ignore certain deps.\n */\n ignoreDeps?: Array<IDependencySection>\n\n /**\n * Ignore certain packages.\n */\n ignorePackages?: Array<string>\n\n /**\n * Skip resolution of certain projects in the workspace.\n */\n ignoreProjects?: IWorkspacesArray\n}\n\n/**\n * Package.json file.\n */\nexport interface IPackageFile {\n name?: string\n dependencies?: IDependenciesSection\n devDependencies?: IDependenciesSection\n peerDependencies?: IDependenciesSection\n optionalDependencies?: IDependenciesSection\n workspaces?: IWorkspacesSection\n [key: string]: unknown\n}\n\n/**\n * Section in package.json representing dependencies.\n */\nexport type IDependenciesSection = Record<string, string>\n\n/**\n * Package + version record, collected from the {\"package\": \"^1.2.3\"} sections.\n */\nexport interface IPackageVersion {\n name: string\n version: string\n}\n\n/**\n * Describes how a package may be typed.\n */\nexport interface IPackageTypingDescriptor {\n typingsName: string\n codePackageName: string\n typesPackageName: string\n}\n\n/**\n * A type definition with the corresponding code package name.\n */\nexport interface ISyncedTypeDefinition extends IPackageTypingDescriptor {\n codePackageName: string\n}\n\n/**\n * Sync result.\n */\nexport interface ISyncResult {\n /**\n * The files that were synced.\n */\n syncedFiles: Array<ISyncedFile>\n}\n\n/**\n * A file that was synced.\n */\nexport interface ISyncedFile {\n /**\n * The cwd-relative path to the synced file.\n */\n filePath: string\n /**\n * The package file that was synced.\n */\n package: IPackageFile\n /**\n * The new typings that were added.\n */\n newTypings: Array<ISyncedTypeDefinition>\n}\n\n/**\n * Dependency sections.\n */\nexport enum IDependencySection {\n dev = 'dev',\n deps = 'deps',\n optional = 'optional',\n peer = 'peer',\n}\n\n/**\n * CLI arguments.\n */\nexport interface ICLIArguments {\n flags: Record<string, boolean | string | undefined>\n args: Array<string>\n}\n","/**\n * Returns unique items.\n *\n * @param source The source to filter\n */\nexport function uniq<T>(source: Array<T>): Array<T> {\n return [...new Set(source)]\n}\n\n/**\n * Remove blank attributes in a object.\n *\n * @param source\n */\nexport function shrinkObject<T extends object>(source: T): Partial<T> {\n const object: Partial<T> = {}\n\n for (const key in source) {\n if (source[key] !== undefined) {\n object[key] = source[key]\n }\n }\n\n return object\n}\n\n/**\n * Merges a sequence of objects into a single object using `reduce`.\n *\n * @param source An array of objects to merge.\n */\nexport function mergeObjects<T>(source: Array<T>): T {\n return source.reduce((accum, next) => ({ ...accum, ...next }), {} as T)\n}\n\n/**\n * Returns the assumed types package name.\n * @param name Package name\n */\nexport function typed(name: string): string {\n // If the package is scoped, the typings scheme is slightly different.\n if (/^@.*?\\//i.test(name)) {\n const splat = name.split('/')\n return `@types/${splat[0].slice(1)}__${splat[1]}`\n }\n\n return `@types/${name}`\n}\n\n/**\n * Returns the assumed code package name based on a types package name.\n * @param name\n */\nexport function untyped(name: string): string {\n const prefix = '@types/'\n if (!name.startsWith(prefix)) {\n return name\n }\n name = name.substring(prefix.length)\n const splat = name.split('__')\n if (splat.length === 2) {\n return `@${splat[0]}/${splat[1]}`\n }\n return name\n}\n\n/**\n * Orders an object.\n * @param source\n */\nexport function orderObject<T extends Record<string | number | symbol, U>, U>(\n source: T,\n comparer?: (a: string, b: string) => number,\n): T {\n const keys = Object.keys(source).sort(comparer)\n const result: Record<string, U> = {}\n for (const key of keys) {\n result[key] = source[key]\n }\n\n return result as T\n}\n\n/**\n * Async memoize.\n *\n * @param fn\n */\nexport function memoizeAsync<U extends Array<W>, V, W>(\n fn: (...args: U) => Promise<V>,\n) {\n const cache = new Map<W, Promise<V>>()\n\n async function run(...args: U): Promise<V> {\n try {\n return await fn(...args)\n } catch (err) {\n cache.delete(args[0])\n throw err\n }\n }\n\n return async function (...args: U): Promise<V> {\n const key = args[0]\n if (cache.has(key)) {\n return await cache.get(key)!\n }\n\n const p = run(...args)\n cache.set(key, p)\n return await p\n }\n}\n","import * as path from 'node:path'\nimport { defaultLoaders, lilconfig } from 'lilconfig'\nimport {\n type ICLIArguments,\n IDependencySection,\n type ISyncOptions,\n} from './types'\nimport { shrinkObject } from './util'\nimport * as yaml from 'yaml'\n\n/**\n * Config Service.\n */\nexport interface IConfigService {\n /**\n * Get typesync config.\n */\n readConfig(\n this: void,\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncOptions>\n}\n\nasync function loadYaml(_filepath: string, content: string): Promise<unknown> {\n return await yaml.parse(content)\n}\n\n// Based on Cosmiconfig readme.\nfunction searchPlaces(moduleName: string) {\n const rcs = [\n `.${moduleName}rc`,\n `.${moduleName}rc.json`,\n `.${moduleName}rc.yaml`,\n `.${moduleName}rc.yml`,\n `.${moduleName}rc.js`,\n `.${moduleName}rc.mjs`,\n `.${moduleName}rc.cjs`,\n ]\n\n return [\n 'package.json',\n ...rcs,\n ...rcs.map((rc) => `.config/${rc}`),\n `${moduleName}.config.js`,\n `${moduleName}.config.mjs`,\n `${moduleName}.config.cjs`,\n ]\n}\n\nconst explorer = lilconfig('typesync', {\n searchPlaces: searchPlaces('typesync'),\n loaders: {\n ...defaultLoaders,\n '.yml': loadYaml,\n '.yaml': loadYaml,\n noExt: loadYaml,\n },\n})\n\nexport function createConfigService(): IConfigService {\n return {\n readConfig: async (filePath: string, flags: ICLIArguments['flags']) => {\n const fileConfig: ISyncOptions = await explorer\n .search(path.dirname(filePath))\n .then((result) => /* v8 ignore next */ result?.config ?? {})\n\n const cliConfig = readCliConfig(flags)\n\n return { ...shrinkObject(fileConfig), ...shrinkObject(cliConfig) }\n },\n }\n}\n\nfunction readCliConfig(flags: ICLIArguments['flags']): ISyncOptions {\n const readValues = <T extends string>(\n key: string,\n validator?: (value: string) => boolean,\n ): Array<T> | undefined => {\n const values = flags[key]\n return typeof values === 'string'\n ? values\n .split(',')\n .filter((value): value is T => (validator ? validator(value) : true))\n : undefined\n }\n\n return {\n ignoreDeps: readValues('ignoredeps', isIgnoreDepConfigValue),\n ignorePackages: readValues('ignorepackages'),\n ignoreProjects: readValues('ignoreprojects'),\n }\n}\n\nfunction isIgnoreDepConfigValue(value: string): value is IDependencySection {\n return Object.keys(IDependencySection).includes(value)\n}\n","import fetch from 'npm-registry-fetch'\nimport { compare } from 'semver'\nimport type { IPackageVersionInfo } from './versioning'\n\n/**\n * Fetches info about a package.\n */\nexport interface IPackageSource {\n /**\n * Fetches package info from an external source.\n *\n * @param packageName\n */\n fetch(this: void, packageName: string): Promise<IPackageInfo | null>\n}\n\n/**\n * Interface for the Package Info structure.\n */\nexport interface IPackageInfo {\n name: string\n latestVersion: string\n deprecated: boolean\n versions: Array<IPackageVersionInfo>\n}\n\n/**\n * Creates a package source.\n */\nexport function createPackageSource(): IPackageSource {\n return {\n /**\n * Fetches info about a package, or `null` if not found.\n */\n fetch: async (name) => {\n const response = await fetch(encodeURI(name)).catch((err) => {\n if (err.statusCode === 404) {\n return null\n /* v8 ignore next */\n }\n\n /* v8 ignore next */\n throw err\n })\n\n const data = await response?.json()\n\n if (!data?.versions) {\n return null\n }\n\n const versionIdentifiers = Object.keys(data.versions)\n .sort(compare)\n .reverse()\n const versions = versionIdentifiers.map<IPackageVersionInfo>((v) => {\n const item = data.versions[v]\n return {\n version: item.version,\n containsInternalTypings: !!item.types || !!item.typings,\n }\n })\n\n return {\n name: data.name,\n deprecated: Boolean(data.versions[versionIdentifiers[0]].deprecated),\n latestVersion: data['dist-tags'].latest,\n // Sort by version, highest version first.\n versions: versions,\n }\n },\n }\n}\n","import { parse } from 'semver'\n\n/**\n * Version descriptor for versions returned in remote package info.\n */\nexport interface IPackageVersionInfo {\n version: string\n containsInternalTypings: boolean\n}\n\n/**\n * Gets the closest matching package version info.\n *\n * @param availableVersions\n * @param version\n */\nexport function getClosestMatchingVersion(\n availableVersions: Array<IPackageVersionInfo>,\n version: string,\n): IPackageVersionInfo {\n const parsedVersion = parseVersion(version)\n if (!parsedVersion) {\n return availableVersions[0]\n }\n\n const bestMatch = availableVersions.find((v) => {\n const parsedAvailableVersion = parseVersion(v.version)\n if (!parsedAvailableVersion) {\n return false\n }\n\n if (parsedVersion.major !== parsedAvailableVersion.major) {\n return false\n }\n\n if (parsedVersion.minor !== parsedAvailableVersion.minor) {\n return false\n }\n\n return true\n })\n\n return bestMatch ?? availableVersions[0]\n}\n\n/**\n * Parses the version if possible.\n *\n * @param version\n * @returns\n */\nfunction parseVersion(version: string) {\n return parse(cleanVersion(version))\n}\n\n/**\n * Cleans the version of any semver range specifiers.\n * @param version\n * @returns\n */\nfunction cleanVersion(version: string) {\n return version.replace(/^[\\^~=\\s]/, '')\n}\n","import * as path from 'node:path'\nimport type { IConfigService } from './config-service'\nimport type { IGlobber } from './globber'\nimport type { IPackageJSONService } from './package-json-file-service'\nimport type { IPackageSource } from './package-source'\nimport {\n type ICLIArguments,\n type IDependenciesSection,\n IDependencySection,\n type IPackageFile,\n type IPackageTypingDescriptor,\n type IPackageVersion,\n type ISyncOptions,\n type ISyncResult,\n type ISyncedFile,\n type ITypeSyncer,\n} from './types'\nimport { memoizeAsync, mergeObjects, orderObject, typed, uniq } from './util'\nimport { getClosestMatchingVersion } from './versioning'\nimport type {\n IWorkspaceResolverService,\n IWorkspacesArray,\n} from './workspace-resolver'\n\n/**\n * Creates a type syncer.\n *\n * @param packageJSONservice\n * @param typeDefinitionSource\n */\nexport function createTypeSyncer(\n packageJSONService: IPackageJSONService,\n workspaceResolverService: IWorkspaceResolverService,\n packageSource: IPackageSource,\n configService: IConfigService,\n globber: IGlobber,\n): ITypeSyncer {\n const fetchPackageInfo = memoizeAsync(packageSource.fetch)\n\n return {\n sync,\n }\n\n /**\n * Syncs typings in the specified package.json.\n */\n async function sync(\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncResult> {\n const dryRun = !!flags.dry\n const syncOpts = await configService.readConfig(filePath, flags)\n const { file, subManifests } = await getManifests(\n filePath,\n globber,\n syncOpts.ignoreProjects ?? [],\n )\n\n const syncedFiles: Array<ISyncedFile> = await Promise.all([\n syncFile(filePath, file, syncOpts, dryRun),\n ...subManifests.map(\n async (p) =>\n await syncFile(\n p,\n await packageJSONService.readPackageFile(p),\n syncOpts,\n dryRun,\n ),\n ),\n ])\n\n return {\n syncedFiles,\n }\n }\n\n /**\n * Get the `package.json` files and sub-packages.\n *\n * @param filePath\n * @param globber\n */\n async function getManifests(\n filePath: string,\n globber: IGlobber,\n ignoredWorkspaces: IWorkspacesArray,\n ) {\n const root = path.dirname(filePath)\n const file = await packageJSONService.readPackageFile(filePath)\n const subPackages = await workspaceResolverService.getWorkspaces(\n file,\n root,\n globber,\n ignoredWorkspaces,\n )\n const subManifests = subPackages.map((p) =>\n path.join(root, p, 'package.json'),\n )\n\n return {\n file,\n subManifests,\n }\n }\n\n /**\n * Syncs a single file.\n *\n * @param filePath\n * @param file\n * @param allTypings\n * @param opts\n */\n async function syncFile(\n filePath: string,\n file: IPackageFile,\n opts: ISyncOptions,\n dryRun: boolean,\n ): Promise<ISyncedFile> {\n const { ignoreDeps, ignorePackages } = opts\n\n const allLocalPackages = Object.values(IDependencySection)\n .map((dep) => {\n const section = getDependenciesBySection(file, dep)\n if (!section) return []\n\n const ignoredSection = ignoreDeps?.includes(dep)\n return getPackagesFromSection(section, ignoredSection, ignorePackages)\n })\n .flat()\n const allPackageNames = uniq(allLocalPackages.map((p) => p.name))\n const potentiallyUntypedPackages =\n getPotentiallyUntypedPackages(allPackageNames)\n\n // This is pushed to in the inner `map`, because packages that have DT-typings\n // *as well* as internal typings should be excluded.\n const used: ReturnType<typeof getPotentiallyUntypedPackages> = []\n const devDepsToAdd = await Promise.all(\n potentiallyUntypedPackages.map(async (t) => {\n // Fetch the code package from the source.\n const typePackageInfoPromise = fetchPackageInfo(t.typesPackageName)\n const codePackageInfo = await fetchPackageInfo(t.codePackageName)\n\n // If the code package was not found, there's nothing else to do.\n if (!codePackageInfo) {\n return {}\n }\n\n const localCodePackage = allLocalPackages.find(\n (p) => p.name === t.codePackageName,\n )!\n\n // Find the closest matching code package version relative to what's in our package.json\n const closestMatchingCodeVersion = getClosestMatchingVersion(\n codePackageInfo.versions,\n localCodePackage.version,\n )\n\n // If the closest matching version contains internal typings, don't include it.\n if (closestMatchingCodeVersion.containsInternalTypings) {\n return {}\n }\n\n // Look for the closest matching typings package.\n const typePackageInfo = await typePackageInfoPromise\n\n // If the types package was not found, or if it was deprecated, there's nothing else to do.\n if (!typePackageInfo || typePackageInfo.deprecated) {\n return {}\n }\n\n // Gets the closest matching typings version, or the newest one.\n const closestMatchingTypingsVersion = getClosestMatchingVersion(\n typePackageInfo.versions,\n localCodePackage.version,\n )\n\n const version = closestMatchingTypingsVersion.version\n const semverRangeSpecifier = '~'\n used.push(t)\n return {\n [t.typesPackageName]: semverRangeSpecifier + version,\n }\n }),\n ).then(mergeObjects)\n const devDeps = file.devDependencies\n if (!dryRun) {\n const newPackageFile: IPackageFile = { ...file }\n\n if (Object.keys(devDepsToAdd).length > 0) {\n newPackageFile.devDependencies = orderObject({\n ...devDepsToAdd,\n ...devDeps,\n })\n\n await packageJSONService.writePackageFile(filePath, newPackageFile)\n }\n }\n\n return {\n filePath,\n newTypings: used,\n package: file,\n }\n }\n}\n\n/**\n * Returns an array of packages that do not have a `@types/` package.\n *\n * @param allPackageNames Used to filter the typings that are new.\n * @param allTypings All typings available\n */\nfunction getPotentiallyUntypedPackages(\n allPackageNames: Array<string>,\n): Array<IPackageTypingDescriptor> {\n const existingTypings = allPackageNames.filter((x) => x.startsWith('@types/'))\n\n return allPackageNames.flatMap((p) => {\n // Ignore typings packages themselves.\n if (p.startsWith('@types/')) {\n return []\n }\n\n const typingsName = getTypingsName(p)\n const fullTypingsPackage = typed(p)\n const alreadyHasTyping = existingTypings.includes(fullTypingsPackage)\n if (alreadyHasTyping) {\n return []\n }\n\n return [\n {\n typingsName: typingsName,\n typesPackageName: fullTypingsPackage,\n codePackageName: p,\n },\n ]\n })\n}\n\n/**\n * Gets the typings name for the specified package name.\n * For example, `koa` would be `koa`, but `@koa/router` would be `koa__router`.\n *\n * @param packageName the package name to generate the typings name for\n */\nfunction getTypingsName(packageName: string) {\n const scopeInfo = getPackageScope(packageName)\n\n return scopeInfo && scopeInfo[0] !== 'types'\n ? `${scopeInfo[0]}__${scopeInfo[1]}`\n : packageName\n}\n\n/**\n * If a package is scoped, returns the scope + package as a tuple, otherwise null.\n *\n * @param packageName Package name to check scope for.\n */\nfunction getPackageScope(packageName: string): [string, string] | null {\n const EXPR = /^@([^/]+)\\/(.*)$/i\n const matches = EXPR.exec(packageName)\n if (!matches) {\n return null\n }\n\n return [matches[1], matches[2]]\n}\n\n/**\n * Get packages from a dependency section\n *\n * @param section\n * @param ignoredSection\n * @param ignorePackages\n */\nfunction getPackagesFromSection(\n section: IDependenciesSection,\n ignoredSection?: boolean,\n ignorePackages?: Array<string>,\n): Array<IPackageVersion> {\n return Object.keys(section).flatMap((name) => {\n const isTyping = name.startsWith('@types/')\n\n // Never ignore `@types` packages.\n if (!isTyping) {\n // If it's not a `@types` package, check whether the section or package is ignored.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- We want to check for false as well.\n if (ignoredSection || ignorePackages?.includes(name)) {\n return []\n }\n }\n\n return [{ name, version: section[name] }]\n })\n}\n\n/**\n * Get dependencies from a package section\n *\n * @param file Package file\n * @param section Package section, eg: dev, peer\n */\nfunction getDependenciesBySection(\n file: IPackageFile,\n section: IDependencySection,\n): IDependenciesSection | undefined {\n const dependenciesSection = (() => {\n switch (section) {\n case IDependencySection.deps:\n return file.dependencies\n case IDependencySection.dev:\n return file.devDependencies\n case IDependencySection.optional:\n return file.optionalDependencies\n case IDependencySection.peer:\n return file.peerDependencies\n }\n })()\n return dependenciesSection\n}\n"],"mappings":";;;;;;;;IA0GY,qCAAA,SAAA,sBAAL;AACL,sBAAA,SAAA;AACA,sBAAA,UAAA;AACA,sBAAA,cAAA;AACA,sBAAA,UAAA;;AACD,EAAA,CAAA,EAAA;;;;AC1GM,SAAS,KAAQA,QAA4B;AAClD,QAAO,CAAC,GAAG,IAAI,IAAI,OAAQ;AAC5B;AAOM,SAAS,aAA+BC,QAAuB;CACpE,MAAMC,SAAqB,CAAE;AAE7B,MAAK,MAAM,OAAO,OAChB,KAAI,OAAO,gBACT,QAAO,OAAO,OAAO;AAIzB,QAAO;AACR;AAOM,SAAS,aAAgBF,QAAqB;AACnD,QAAO,OAAO,OAAO,CAAC,OAAO,UAAU;EAAE,GAAG;EAAO,GAAG;CAAM,IAAG,CAAE,EAAM;AACxE;AAMM,SAAS,MAAMG,MAAsB;AAE1C,KAAI,WAAW,KAAK,KAAK,EAAE;EACzB,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,MAAM,GAAG;CACjD;AAED,SAAQ,SAAS,KAAK;AACvB;AAuBM,SAAS,YACdF,QACAG,UACG;CACH,MAAM,OAAO,OAAO,KAAK,OAAO,CAAC,KAAK,SAAS;CAC/C,MAAMC,SAA4B,CAAE;AACpC,MAAK,MAAM,OAAO,KAChB,QAAO,OAAO,OAAO;AAGvB,QAAO;AACR;AAOM,SAAS,aACdC,IACA;CACA,MAAM,QAAQ,IAAI;CAElB,eAAe,IAAI,GAAG,MAAqB;AACzC,MAAI;AACF,UAAO,MAAM,GAAG,GAAG,KAAK;EACzB,SAAQ,KAAK;AACZ,SAAM,OAAO,KAAK,GAAG;AACrB,SAAM;EACP;CACF;AAED,QAAO,eAAgB,GAAG,MAAqB;EAC7C,MAAM,MAAM,KAAK;AACjB,MAAI,MAAM,IAAI,IAAI,CAChB,QAAO,MAAM,MAAM,IAAI,IAAI;EAG7B,MAAM,IAAI,IAAI,GAAG,KAAK;AACtB,QAAM,IAAI,KAAK,EAAE;AACjB,SAAO,MAAM;CACd;AACF;;;;ACxFD,eAAe,SAASC,WAAmBC,SAAmC;AAC5E,QAAO,MAAM,KAAK,MAAM,QAAQ;AACjC;AAGD,SAAS,aAAaC,YAAoB;CACxC,MAAM,MAAM;GACT,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG,WAAW;CAChB;AAED,QAAO;EACL;EACA,GAAG;EACH,GAAG,IAAI,IAAI,CAAC,QAAQ,UAAU,GAAG,EAAE;GAClC,EAAE,WAAW;GACb,EAAE,WAAW;GACb,EAAE,WAAW;CACf;AACF;AAED,MAAM,WAAW,UAAU,YAAY;CACrC,cAAc,aAAa,WAAW;CACtC,SAAS;EACP,GAAG;EACH,QAAQ;EACR,SAAS;EACT,OAAO;CACR;AACF,EAAC;AAEK,SAAS,sBAAsC;AACpD,QAAO,EACL,YAAY,OAAOC,UAAkBC,UAAkC;EACrE,MAAMC,aAA2B,MAAM,SACpC,OAAO,OAAK,QAAQ,SAAS,CAAC,CAC9B,KAAK,CAAC,WAAgC,QAAQ,UAAU,CAAE,EAAC;EAE9D,MAAM,YAAY,cAAc,MAAM;AAEtC,SAAO;GAAE,GAAG,aAAa,WAAW;GAAE,GAAG,aAAa,UAAU;EAAE;CACnE,EACF;AACF;AAED,SAAS,cAAcD,OAA6C;CAClE,MAAM,aAAa,CACjBE,KACAC,cACyB;EACzB,MAAM,SAAS,MAAM;AACrB,gBAAc,WAAW,WACrB,OACG,MAAM,IAAI,CACV,OAAO,CAAC,UAAuB,YAAY,UAAU,MAAM,GAAG,KAAM;CAE5E;AAED,QAAO;EACL,YAAY,WAAW,cAAc,uBAAuB;EAC5D,gBAAgB,WAAW,iBAAiB;EAC5C,gBAAgB,WAAW,iBAAiB;CAC7C;AACF;AAED,SAAS,uBAAuBC,OAA4C;AAC1E,QAAO,OAAO,KAAK,mBAAmB,CAAC,SAAS,MAAM;AACvD;;;;ACnEM,SAAS,sBAAsC;AACpD,QAAO,EAIL,OAAO,OAAO,SAAS;EACrB,MAAM,WAAW,MAAM,MAAM,UAAU,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ;AAC3D,OAAI,IAAI,eAAe,IACrB,QAAO;AAKT,SAAM;EACP,EAAC;EAEF,MAAM,OAAO,MAAM,UAAU,MAAM;AAEnC,OAAK,MAAM,SACT,QAAO;EAGT,MAAM,qBAAqB,OAAO,KAAK,KAAK,SAAS,CAClD,KAAK,QAAQ,CACb,SAAS;EACZ,MAAM,WAAW,mBAAmB,IAAyB,CAAC,MAAM;GAClE,MAAM,OAAO,KAAK,SAAS;AAC3B,UAAO;IACL,SAAS,KAAK;IACd,2BAA2B,KAAK,WAAW,KAAK;GACjD;EACF,EAAC;AAEF,SAAO;GACL,MAAM,KAAK;GACX,YAAY,QAAQ,KAAK,SAAS,mBAAmB,IAAI,WAAW;GACpE,eAAe,KAAK,aAAa;GAEvB;EACX;CACF,EACF;AACF;;;;ACvDM,SAAS,0BACdC,mBACAC,SACqB;CACrB,MAAM,gBAAgB,aAAa,QAAQ;AAC3C,MAAK,cACH,QAAO,kBAAkB;CAG3B,MAAM,YAAY,kBAAkB,KAAK,CAAC,MAAM;EAC9C,MAAM,yBAAyB,aAAa,EAAE,QAAQ;AACtD,OAAK,uBACH,QAAO;AAGT,MAAI,cAAc,UAAU,uBAAuB,MACjD,QAAO;AAGT,MAAI,cAAc,UAAU,uBAAuB,MACjD,QAAO;AAGT,SAAO;CACR,EAAC;AAEF,QAAO,aAAa,kBAAkB;AACvC;;;;;;;AAQD,SAAS,aAAaA,SAAiB;AACrC,QAAO,MAAM,aAAa,QAAQ,CAAC;AACpC;;;;;;AAOD,SAAS,aAAaA,SAAiB;AACrC,QAAO,QAAQ,QAAQ,aAAa,GAAG;AACxC;;;;AChCM,SAAS,iBACdC,oBACAC,0BACAC,eACAC,eACAC,SACa;CACb,MAAM,mBAAmB,aAAa,cAAc,MAAM;AAE1D,QAAO,EACL,KACD;;;;CAKD,eAAe,KACbC,UACAC,OACsB;EACtB,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,MAAM,cAAc,WAAW,UAAU,MAAM;EAChE,MAAM,EAAE,MAAM,cAAc,GAAG,MAAM,aACnC,UACA,SACA,SAAS,kBAAkB,CAAE,EAC9B;EAED,MAAMC,cAAkC,MAAM,QAAQ,IAAI,CACxD,SAAS,UAAU,MAAM,UAAU,OAAO,EAC1C,GAAG,aAAa,IACd,OAAO,MACL,MAAM,SACJ,GACA,MAAM,mBAAmB,gBAAgB,EAAE,EAC3C,UACA,OACD,CACJ,AACF,EAAC;AAEF,SAAO,EACL,YACD;CACF;;;;;;;CAQD,eAAe,aACbF,UACAD,WACAI,mBACA;EACA,MAAM,OAAO,KAAK,QAAQ,SAAS;EACnC,MAAM,OAAO,MAAM,mBAAmB,gBAAgB,SAAS;EAC/D,MAAM,cAAc,MAAM,yBAAyB,cACjD,MACA,MACA,WACA,kBACD;EACD,MAAM,eAAe,YAAY,IAAI,CAAC,MACpC,KAAK,KAAK,MAAM,GAAG,eAAe,CACnC;AAED,SAAO;GACL;GACA;EACD;CACF;;;;;;;;;CAUD,eAAe,SACbH,UACAI,MACAC,MACAC,QACsB;EACtB,MAAM,EAAE,YAAY,gBAAgB,GAAG;EAEvC,MAAM,mBAAmB,OAAO,OAAO,mBAAmB,CACvD,IAAI,CAAC,QAAQ;GACZ,MAAM,UAAU,yBAAyB,MAAM,IAAI;AACnD,QAAK,QAAS,QAAO,CAAE;GAEvB,MAAM,iBAAiB,YAAY,SAAS,IAAI;AAChD,UAAO,uBAAuB,SAAS,gBAAgB,eAAe;EACvE,EAAC,CACD,MAAM;EACT,MAAM,kBAAkB,KAAK,iBAAiB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;EACjE,MAAM,6BACJ,8BAA8B,gBAAgB;EAIhD,MAAMC,OAAyD,CAAE;EACjE,MAAM,eAAe,MAAM,QAAQ,IACjC,2BAA2B,IAAI,OAAO,MAAM;GAE1C,MAAM,yBAAyB,iBAAiB,EAAE,iBAAiB;GACnE,MAAM,kBAAkB,MAAM,iBAAiB,EAAE,gBAAgB;AAGjE,QAAK,gBACH,QAAO,CAAE;GAGX,MAAM,mBAAmB,iBAAiB,KACxC,CAAC,MAAM,EAAE,SAAS,EAAE,gBACrB;GAGD,MAAM,6BAA6B,0BACjC,gBAAgB,UAChB,iBAAiB,QAClB;AAGD,OAAI,2BAA2B,wBAC7B,QAAO,CAAE;GAIX,MAAM,kBAAkB,MAAM;AAG9B,QAAK,mBAAmB,gBAAgB,WACtC,QAAO,CAAE;GAIX,MAAM,gCAAgC,0BACpC,gBAAgB,UAChB,iBAAiB,QAClB;GAED,MAAM,UAAU,8BAA8B;GAC9C,MAAM,uBAAuB;AAC7B,QAAK,KAAK,EAAE;AACZ,UAAO,GACJ,EAAE,mBAAmB,uBAAuB,QAC9C;EACF,EAAC,CACH,CAAC,KAAK,aAAa;EACpB,MAAM,UAAU,KAAK;AACrB,OAAK,QAAQ;GACX,MAAMC,iBAA+B,EAAE,GAAG,KAAM;AAEhD,OAAI,OAAO,KAAK,aAAa,CAAC,SAAS,GAAG;AACxC,mBAAe,kBAAkB,YAAY;KAC3C,GAAG;KACH,GAAG;IACJ,EAAC;AAEF,UAAM,mBAAmB,iBAAiB,UAAU,eAAe;GACpE;EACF;AAED,SAAO;GACL;GACA,YAAY;GACZ,SAAS;EACV;CACF;AACF;;;;;;;AAQD,SAAS,8BACPC,iBACiC;CACjC,MAAM,kBAAkB,gBAAgB,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,CAAC;AAE9E,QAAO,gBAAgB,QAAQ,CAAC,MAAM;AAEpC,MAAI,EAAE,WAAW,UAAU,CACzB,QAAO,CAAE;EAGX,MAAM,cAAc,eAAe,EAAE;EACrC,MAAM,qBAAqB,MAAM,EAAE;EACnC,MAAM,mBAAmB,gBAAgB,SAAS,mBAAmB;AACrE,MAAI,iBACF,QAAO,CAAE;AAGX,SAAO,CACL;GACe;GACb,kBAAkB;GAClB,iBAAiB;EAEpB,CAAA;CACF,EAAC;AACH;;;;;;;AAQD,SAAS,eAAeC,aAAqB;CAC3C,MAAM,YAAY,gBAAgB,YAAY;AAE9C,QAAO,aAAa,UAAU,OAAO,WAChC,EAAE,UAAU,GAAG,IAAI,UAAU,GAAG,IACjC;AACL;;;;;;AAOD,SAAS,gBAAgBA,aAA8C;CACrE,MAAM,OAAO;CACb,MAAM,UAAU,KAAK,KAAK,YAAY;AACtC,MAAK,QACH,QAAO;AAGT,QAAO,CAAC,QAAQ,IAAI,QAAQ,EAAG;AAChC;;;;;;;;AASD,SAAS,uBACPC,SACAC,gBACAC,gBACwB;AACxB,QAAO,OAAO,KAAK,QAAQ,CAAC,QAAQ,CAAC,SAAS;EAC5C,MAAM,WAAW,KAAK,WAAW,UAAU;AAG3C,OAAK,UAGH;OAAI,kBAAkB,gBAAgB,SAAS,KAAK,CAClD,QAAO,CAAE;EACV;AAGH,SAAO,CAAC;GAAE;GAAM,SAAS,QAAQ;EAAQ,CAAA;CAC1C,EAAC;AACH;;;;;;;AAQD,SAAS,yBACPT,MACAU,SACkC;CAClC,MAAM,sBAAsB,CAAC,MAAM;AACjC,UAAQ,SAAR;GACE,KAAK,mBAAmB,KACtB,QAAO,KAAK;GACd,KAAK,mBAAmB,IACtB,QAAO,KAAK;GACd,KAAK,mBAAmB,SACtB,QAAO,KAAK;GACd,KAAK,mBAAmB,KACtB,QAAO,KAAK;EACf;CACF,IAAG;AACJ,QAAO;AACR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typesync",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "type": "module",
5
5
  "description": "Install missing TypeScript typings for your dependencies.",
6
6
  "engines": {
@@ -29,7 +29,7 @@
29
29
  "lint:watch": "nodemon --exec npm run lint",
30
30
  "build": "tsdown",
31
31
  "build:watch": "tsdown --watch",
32
- "run-cli": "npm run build && node bin/typesync",
32
+ "run-cli": "npm run build -- --silent && node bin/typesync",
33
33
  "run-cli:dry": "npm run run-cli -- --dry",
34
34
  "do:publish": "npm run lint && npm run test && npm run build && npm publish",
35
35
  "release:patch": "npm version patch && npm run do:publish && git push --follow-tags",
@@ -47,21 +47,20 @@
47
47
  },
48
48
  "homepage": "https://github.com/jeffijoe/typesync#readme",
49
49
  "dependencies": {
50
+ "ansis": "^3.17.0",
50
51
  "awilix": "^12.0.5",
51
- "chalk": "^5.4.1",
52
- "cosmiconfig": "^9.0.0",
53
52
  "detect-indent": "^7.0.1",
54
- "js-yaml": "^4.1.0",
53
+ "lilconfig": "^3.1.3",
55
54
  "npm-registry-fetch": "^18.0.2",
56
- "ora": "^8.1.1",
55
+ "picospinner": "^3.0.0",
57
56
  "semver": "^7.7.0",
58
- "tinyglobby": "^0.2.12"
57
+ "tinyglobby": "^0.2.12",
58
+ "yaml": "^2.7.1"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@eslint/js": "^9.23.0",
62
- "@types/js-yaml": "~4.0.9 || ~4.1.0",
63
62
  "@types/node": "^22.13.17",
64
- "@types/npm-registry-fetch": "^8.0.7 || ~17.1.0",
63
+ "@types/npm-registry-fetch": "^8.0.7 || ~18.0.0",
65
64
  "@types/semver": "~7.7.0",
66
65
  "@vitest/coverage-v8": "^3.1.1",
67
66
  "@vitest/ui": "^3.1.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-syncer-CLrmNiXL.js","names":["source: Array<T>","source: T","object: Partial<T>","name: string","comparer?: (a: string, b: string) => number","result: Record<string, U>","fn: (...args: U) => Promise<V>","filePath: string","flags: ICLIArguments['flags']","fileConfig: ISyncOptions","key: string","validator?: (value: string) => boolean","value: string","availableVersions: Array<IPackageVersionInfo>","version: string","packageJSONService: IPackageJSONService","workspaceResolverService: IWorkspaceResolverService","packageSource: IPackageSource","configService: IConfigService","globber: IGlobber","filePath: string","flags: ICLIArguments['flags']","syncedFiles: Array<ISyncedFile>","ignoredWorkspaces: IWorkspacesArray","file: IPackageFile","opts: ISyncOptions","dryRun: boolean","used: ReturnType<typeof getPotentiallyUntypedPackages>","newPackageFile: IPackageFile","allPackageNames: Array<string>","packageName: string","section: IDependenciesSection","ignoredSection?: boolean","ignorePackages?: Array<string>","section: IDependencySection"],"sources":["../src/types.ts","../src/util.ts","../src/config-service.ts","../src/package-source.ts","../src/versioning.ts","../src/type-syncer.ts"],"sourcesContent":["import type { IWorkspacesArray, IWorkspacesSection } from './workspace-resolver'\n\n/**\n * The guts of the program.\n */\nexport interface ITypeSyncer {\n sync(\n this: void,\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncResult>\n}\n\n/**\n * Sync options.\n */\nexport interface ISyncOptions {\n /**\n * Ignore certain deps.\n */\n ignoreDeps?: Array<IDependencySection>\n\n /**\n * Ignore certain packages.\n */\n ignorePackages?: Array<string>\n\n /**\n * Skip resolution of certain projects in the workspace.\n */\n ignoreProjects?: IWorkspacesArray\n}\n\n/**\n * Package.json file.\n */\nexport interface IPackageFile {\n name?: string\n dependencies?: IDependenciesSection\n devDependencies?: IDependenciesSection\n peerDependencies?: IDependenciesSection\n optionalDependencies?: IDependenciesSection\n workspaces?: IWorkspacesSection\n [key: string]: unknown\n}\n\n/**\n * Section in package.json representing dependencies.\n */\nexport type IDependenciesSection = Record<string, string>\n\n/**\n * Package + version record, collected from the {\"package\": \"^1.2.3\"} sections.\n */\nexport interface IPackageVersion {\n name: string\n version: string\n}\n\n/**\n * Describes how a package may be typed.\n */\nexport interface IPackageTypingDescriptor {\n typingsName: string\n codePackageName: string\n typesPackageName: string\n}\n\n/**\n * A type definition with the corresponding code package name.\n */\nexport interface ISyncedTypeDefinition extends IPackageTypingDescriptor {\n codePackageName: string\n}\n\n/**\n * Sync result.\n */\nexport interface ISyncResult {\n /**\n * The files that were synced.\n */\n syncedFiles: Array<ISyncedFile>\n}\n\n/**\n * A file that was synced.\n */\nexport interface ISyncedFile {\n /**\n * The cwd-relative path to the synced file.\n */\n filePath: string\n /**\n * The package file that was synced.\n */\n package: IPackageFile\n /**\n * The new typings that were added.\n */\n newTypings: Array<ISyncedTypeDefinition>\n}\n\n/**\n * Dependency sections.\n */\nexport enum IDependencySection {\n dev = 'dev',\n deps = 'deps',\n optional = 'optional',\n peer = 'peer',\n}\n\n/**\n * CLI arguments.\n */\nexport interface ICLIArguments {\n flags: Record<string, boolean | string | undefined>\n args: Array<string>\n}\n","/**\n * Returns unique items.\n *\n * @param source The source to filter\n */\nexport function uniq<T>(source: Array<T>): Array<T> {\n return [...new Set(source)]\n}\n\n/**\n * Remove blank attributes in a object.\n *\n * @param source\n */\nexport function shrinkObject<T extends object>(source: T): Partial<T> {\n const object: Partial<T> = {}\n\n for (const key in source) {\n if (source[key] !== undefined) {\n object[key] = source[key]\n }\n }\n\n return object\n}\n\n/**\n * Merges a sequence of objects into a single object using `reduce`.\n *\n * @param source An array of objects to merge.\n */\nexport function mergeObjects<T>(source: Array<T>): T {\n return source.reduce((accum, next) => ({ ...accum, ...next }), {} as T)\n}\n\n/**\n * Returns the assumed types package name.\n * @param name Package name\n */\nexport function typed(name: string): string {\n // If the package is scoped, the typings scheme is slightly different.\n if (/^@.*?\\//i.test(name)) {\n const splat = name.split('/')\n return `@types/${splat[0].slice(1)}__${splat[1]}`\n }\n\n return `@types/${name}`\n}\n\n/**\n * Returns the assumed code package name based on a types package name.\n * @param name\n */\nexport function untyped(name: string): string {\n const prefix = '@types/'\n if (!name.startsWith(prefix)) {\n return name\n }\n name = name.substring(prefix.length)\n const splat = name.split('__')\n if (splat.length === 2) {\n return `@${splat[0]}/${splat[1]}`\n }\n return name\n}\n\n/**\n * Orders an object.\n * @param source\n */\nexport function orderObject<T extends Record<string | number | symbol, U>, U>(\n source: T,\n comparer?: (a: string, b: string) => number,\n): T {\n const keys = Object.keys(source).sort(comparer)\n const result: Record<string, U> = {}\n for (const key of keys) {\n result[key] = source[key]\n }\n\n return result as T\n}\n\n/**\n * Async memoize.\n *\n * @param fn\n */\nexport function memoizeAsync<U extends Array<W>, V, W>(\n fn: (...args: U) => Promise<V>,\n) {\n const cache = new Map<W, Promise<V>>()\n\n async function run(...args: U): Promise<V> {\n try {\n return await fn(...args)\n } catch (err) {\n cache.delete(args[0])\n throw err\n }\n }\n\n return async function (...args: U): Promise<V> {\n const key = args[0]\n if (cache.has(key)) {\n return await cache.get(key)!\n }\n\n const p = run(...args)\n cache.set(key, p)\n return await p\n }\n}\n","import * as path from 'node:path'\nimport { cosmiconfig } from 'cosmiconfig'\nimport {\n type ICLIArguments,\n IDependencySection,\n type ISyncOptions,\n} from './types'\nimport { shrinkObject } from './util'\n\n/**\n * Config Service.\n */\nexport interface IConfigService {\n /**\n * Get typesync config.\n */\n readConfig(\n this: void,\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncOptions>\n}\n\nconst explorer = cosmiconfig('typesync')\n\nexport function createConfigService(): IConfigService {\n return {\n readConfig: async (filePath: string, flags: ICLIArguments['flags']) => {\n const fileConfig: ISyncOptions = await explorer\n .search(path.dirname(filePath))\n .then((result) => /* v8 ignore next */ result?.config ?? {})\n\n const cliConfig = readCliConfig(flags)\n\n return { ...shrinkObject(fileConfig), ...shrinkObject(cliConfig) }\n },\n }\n}\n\nfunction readCliConfig(flags: ICLIArguments['flags']): ISyncOptions {\n const readValues = <T extends string>(\n key: string,\n validator?: (value: string) => boolean,\n ): Array<T> | undefined => {\n const values = flags[key]\n return typeof values === 'string'\n ? values\n .split(',')\n .filter((value): value is T => (validator ? validator(value) : true))\n : undefined\n }\n\n return {\n ignoreDeps: readValues('ignoredeps', isIgnoreDepConfigValue),\n ignorePackages: readValues('ignorepackages'),\n ignoreProjects: readValues('ignoreprojects'),\n }\n}\n\nfunction isIgnoreDepConfigValue(value: string): value is IDependencySection {\n return Object.keys(IDependencySection).includes(value)\n}\n","import fetch from 'npm-registry-fetch'\nimport { compare } from 'semver'\nimport type { IPackageVersionInfo } from './versioning'\n\n/**\n * Fetches info about a package.\n */\nexport interface IPackageSource {\n /**\n * Fetches package info from an external source.\n *\n * @param packageName\n */\n fetch(this: void, packageName: string): Promise<IPackageInfo | null>\n}\n\n/**\n * Interface for the Package Info structure.\n */\nexport interface IPackageInfo {\n name: string\n latestVersion: string\n deprecated: boolean\n versions: Array<IPackageVersionInfo>\n}\n\n/**\n * Creates a package source.\n */\nexport function createPackageSource(): IPackageSource {\n return {\n /**\n * Fetches info about a package, or `null` if not found.\n */\n fetch: async (name) => {\n const response = await fetch(encodeURI(name)).catch((err) => {\n if (err.statusCode === 404) {\n return null\n /* v8 ignore next */\n }\n\n /* v8 ignore next */\n throw err\n })\n\n const data = await response?.json()\n\n if (!data?.versions) {\n return null\n }\n\n const versionIdentifiers = Object.keys(data.versions)\n .sort(compare)\n .reverse()\n const versions = versionIdentifiers.map<IPackageVersionInfo>((v) => {\n const item = data.versions[v]\n return {\n version: item.version,\n containsInternalTypings: !!item.types || !!item.typings,\n }\n })\n\n return {\n name: data.name,\n deprecated: Boolean(data.versions[versionIdentifiers[0]].deprecated),\n latestVersion: data['dist-tags'].latest,\n // Sort by version, highest version first.\n versions: versions,\n }\n },\n }\n}\n","import { parse } from 'semver'\n\n/**\n * Version descriptor for versions returned in remote package info.\n */\nexport interface IPackageVersionInfo {\n version: string\n containsInternalTypings: boolean\n}\n\n/**\n * Gets the closest matching package version info.\n *\n * @param availableVersions\n * @param version\n */\nexport function getClosestMatchingVersion(\n availableVersions: Array<IPackageVersionInfo>,\n version: string,\n): IPackageVersionInfo {\n const parsedVersion = parseVersion(version)\n if (!parsedVersion) {\n return availableVersions[0]\n }\n\n const bestMatch = availableVersions.find((v) => {\n const parsedAvailableVersion = parseVersion(v.version)\n if (!parsedAvailableVersion) {\n return false\n }\n\n if (parsedVersion.major !== parsedAvailableVersion.major) {\n return false\n }\n\n if (parsedVersion.minor !== parsedAvailableVersion.minor) {\n return false\n }\n\n return true\n })\n\n return bestMatch ?? availableVersions[0]\n}\n\n/**\n * Parses the version if possible.\n *\n * @param version\n * @returns\n */\nfunction parseVersion(version: string) {\n return parse(cleanVersion(version))\n}\n\n/**\n * Cleans the version of any semver range specifiers.\n * @param version\n * @returns\n */\nfunction cleanVersion(version: string) {\n return version.replace(/^[\\^~=\\s]/, '')\n}\n","import * as path from 'node:path'\nimport type { IConfigService } from './config-service'\nimport type { IGlobber } from './globber'\nimport type { IPackageJSONService } from './package-json-file-service'\nimport type { IPackageSource } from './package-source'\nimport {\n type ICLIArguments,\n type IDependenciesSection,\n IDependencySection,\n type IPackageFile,\n type IPackageTypingDescriptor,\n type IPackageVersion,\n type ISyncOptions,\n type ISyncResult,\n type ISyncedFile,\n type ITypeSyncer,\n} from './types'\nimport { memoizeAsync, mergeObjects, orderObject, typed, uniq } from './util'\nimport { getClosestMatchingVersion } from './versioning'\nimport type {\n IWorkspaceResolverService,\n IWorkspacesArray,\n} from './workspace-resolver'\n\n/**\n * Creates a type syncer.\n *\n * @param packageJSONservice\n * @param typeDefinitionSource\n */\nexport function createTypeSyncer(\n packageJSONService: IPackageJSONService,\n workspaceResolverService: IWorkspaceResolverService,\n packageSource: IPackageSource,\n configService: IConfigService,\n globber: IGlobber,\n): ITypeSyncer {\n const fetchPackageInfo = memoizeAsync(packageSource.fetch)\n\n return {\n sync,\n }\n\n /**\n * Syncs typings in the specified package.json.\n */\n async function sync(\n filePath: string,\n flags: ICLIArguments['flags'],\n ): Promise<ISyncResult> {\n const dryRun = !!flags.dry\n const syncOpts = await configService.readConfig(filePath, flags)\n const { file, subManifests } = await getManifests(\n filePath,\n globber,\n syncOpts.ignoreProjects ?? [],\n )\n\n const syncedFiles: Array<ISyncedFile> = await Promise.all([\n syncFile(filePath, file, syncOpts, dryRun),\n ...subManifests.map(\n async (p) =>\n await syncFile(\n p,\n await packageJSONService.readPackageFile(p),\n syncOpts,\n dryRun,\n ),\n ),\n ])\n\n return {\n syncedFiles,\n }\n }\n\n /**\n * Get the `package.json` files and sub-packages.\n *\n * @param filePath\n * @param globber\n */\n async function getManifests(\n filePath: string,\n globber: IGlobber,\n ignoredWorkspaces: IWorkspacesArray,\n ) {\n const root = path.dirname(filePath)\n const file = await packageJSONService.readPackageFile(filePath)\n const subPackages = await workspaceResolverService.getWorkspaces(\n file,\n root,\n globber,\n ignoredWorkspaces,\n )\n const subManifests = subPackages.map((p) =>\n path.join(root, p, 'package.json'),\n )\n\n return {\n file,\n subManifests,\n }\n }\n\n /**\n * Syncs a single file.\n *\n * @param filePath\n * @param file\n * @param allTypings\n * @param opts\n */\n async function syncFile(\n filePath: string,\n file: IPackageFile,\n opts: ISyncOptions,\n dryRun: boolean,\n ): Promise<ISyncedFile> {\n const { ignoreDeps, ignorePackages } = opts\n\n const allLocalPackages = Object.values(IDependencySection)\n .map((dep) => {\n const section = getDependenciesBySection(file, dep)\n if (!section) return []\n\n const ignoredSection = ignoreDeps?.includes(dep)\n return getPackagesFromSection(section, ignoredSection, ignorePackages)\n })\n .flat()\n const allPackageNames = uniq(allLocalPackages.map((p) => p.name))\n const potentiallyUntypedPackages =\n getPotentiallyUntypedPackages(allPackageNames)\n\n // This is pushed to in the inner `map`, because packages that have DT-typings\n // *as well* as internal typings should be excluded.\n const used: ReturnType<typeof getPotentiallyUntypedPackages> = []\n const devDepsToAdd = await Promise.all(\n potentiallyUntypedPackages.map(async (t) => {\n // Fetch the code package from the source.\n const typePackageInfoPromise = fetchPackageInfo(t.typesPackageName)\n const codePackageInfo = await fetchPackageInfo(t.codePackageName)\n\n // If the code package was not found, there's nothing else to do.\n if (!codePackageInfo) {\n return {}\n }\n\n const localCodePackage = allLocalPackages.find(\n (p) => p.name === t.codePackageName,\n )!\n\n // Find the closest matching code package version relative to what's in our package.json\n const closestMatchingCodeVersion = getClosestMatchingVersion(\n codePackageInfo.versions,\n localCodePackage.version,\n )\n\n // If the closest matching version contains internal typings, don't include it.\n if (closestMatchingCodeVersion.containsInternalTypings) {\n return {}\n }\n\n // Look for the closest matching typings package.\n const typePackageInfo = await typePackageInfoPromise\n\n // If the types package was not found, or if it was deprecated, there's nothing else to do.\n if (!typePackageInfo || typePackageInfo.deprecated) {\n return {}\n }\n\n // Gets the closest matching typings version, or the newest one.\n const closestMatchingTypingsVersion = getClosestMatchingVersion(\n typePackageInfo.versions,\n localCodePackage.version,\n )\n\n const version = closestMatchingTypingsVersion.version\n const semverRangeSpecifier = '~'\n used.push(t)\n return {\n [t.typesPackageName]: semverRangeSpecifier + version,\n }\n }),\n ).then(mergeObjects)\n const devDeps = file.devDependencies\n if (!dryRun) {\n const newPackageFile: IPackageFile = { ...file }\n\n if (Object.keys(devDepsToAdd).length > 0) {\n newPackageFile.devDependencies = orderObject({\n ...devDepsToAdd,\n ...devDeps,\n })\n\n await packageJSONService.writePackageFile(filePath, newPackageFile)\n }\n }\n\n return {\n filePath,\n newTypings: used,\n package: file,\n }\n }\n}\n\n/**\n * Returns an array of packages that do not have a `@types/` package.\n *\n * @param allPackageNames Used to filter the typings that are new.\n * @param allTypings All typings available\n */\nfunction getPotentiallyUntypedPackages(\n allPackageNames: Array<string>,\n): Array<IPackageTypingDescriptor> {\n const existingTypings = allPackageNames.filter((x) => x.startsWith('@types/'))\n\n return allPackageNames.flatMap((p) => {\n // Ignore typings packages themselves.\n if (p.startsWith('@types/')) {\n return []\n }\n\n const typingsName = getTypingsName(p)\n const fullTypingsPackage = typed(p)\n const alreadyHasTyping = existingTypings.includes(fullTypingsPackage)\n if (alreadyHasTyping) {\n return []\n }\n\n return [\n {\n typingsName: typingsName,\n typesPackageName: fullTypingsPackage,\n codePackageName: p,\n },\n ]\n })\n}\n\n/**\n * Gets the typings name for the specified package name.\n * For example, `koa` would be `koa`, but `@koa/router` would be `koa__router`.\n *\n * @param packageName the package name to generate the typings name for\n */\nfunction getTypingsName(packageName: string) {\n const scopeInfo = getPackageScope(packageName)\n\n return scopeInfo && scopeInfo[0] !== 'types'\n ? `${scopeInfo[0]}__${scopeInfo[1]}`\n : packageName\n}\n\n/**\n * If a package is scoped, returns the scope + package as a tuple, otherwise null.\n *\n * @param packageName Package name to check scope for.\n */\nfunction getPackageScope(packageName: string): [string, string] | null {\n const EXPR = /^@([^/]+)\\/(.*)$/i\n const matches = EXPR.exec(packageName)\n if (!matches) {\n return null\n }\n\n return [matches[1], matches[2]]\n}\n\n/**\n * Get packages from a dependency section\n *\n * @param section\n * @param ignoredSection\n * @param ignorePackages\n */\nfunction getPackagesFromSection(\n section: IDependenciesSection,\n ignoredSection?: boolean,\n ignorePackages?: Array<string>,\n): Array<IPackageVersion> {\n return Object.keys(section).flatMap((name) => {\n const isTyping = name.startsWith('@types/')\n\n // Never ignore `@types` packages.\n if (!isTyping) {\n // If it's not a `@types` package, check whether the section or package is ignored.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- We want to check for false as well.\n if (ignoredSection || ignorePackages?.includes(name)) {\n return []\n }\n }\n\n return [{ name, version: section[name] }]\n })\n}\n\n/**\n * Get dependencies from a package section\n *\n * @param file Package file\n * @param section Package section, eg: dev, peer\n */\nfunction getDependenciesBySection(\n file: IPackageFile,\n section: IDependencySection,\n): IDependenciesSection | undefined {\n const dependenciesSection = (() => {\n switch (section) {\n case IDependencySection.deps:\n return file.dependencies\n case IDependencySection.dev:\n return file.devDependencies\n case IDependencySection.optional:\n return file.optionalDependencies\n case IDependencySection.peer:\n return file.peerDependencies\n }\n })()\n return dependenciesSection\n}\n"],"mappings":"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"}