typesync 0.14.1 → 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.d.ts +4 -4
- package/dist/cli.js +52 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +18 -102
- package/dist/index.js +1 -1
- package/dist/{type-syncer-D93oGCvC.js → type-syncer-D40qMMFq.js} +37 -6
- package/dist/type-syncer-D40qMMFq.js.map +1 -0
- package/package.json +23 -23
- package/dist/type-syncer-D93oGCvC.js.map +0 -1
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { createConfigService, createPackageSource, createTypeSyncer, uniq } from "./type-syncer-
|
|
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
|
|
6
|
-
import {
|
|
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(`${
|
|
25
|
+
console.log(`${white`»`} ${gray(message)}`);
|
|
26
26
|
}
|
|
27
27
|
function success(text) {
|
|
28
|
-
console.log(`${
|
|
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(`${
|
|
33
|
+
console.log(`${red`✖`} ${white.bgRed(msg)}${stack}`);
|
|
34
34
|
}
|
|
35
35
|
async function spinWhile(text, fn) {
|
|
36
|
-
|
|
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 = {};
|
|
@@ -103,17 +110,17 @@ function createWorkspaceResolverService({ readFileContents: readFileContents$1 }
|
|
|
103
110
|
} };
|
|
104
111
|
async function getWorkspaces(packageJson, root) {
|
|
105
112
|
const packageJsonWorkspaces = packageJson.workspaces;
|
|
106
|
-
if (packageJsonWorkspaces !==
|
|
113
|
+
if (packageJsonWorkspaces !== void 0) return packageJsonWorkspaces;
|
|
107
114
|
return await getPnpmWorkspaces(root);
|
|
108
115
|
}
|
|
109
116
|
async function getPnpmWorkspaces(root) {
|
|
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.
|
|
120
|
+
const pnpmWorkspaces = yaml.parse(contents);
|
|
114
121
|
return pnpmWorkspaces.packages;
|
|
115
122
|
} catch {
|
|
116
|
-
return
|
|
123
|
+
return void 0;
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
126
|
}
|
|
@@ -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.
|
|
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,33 +170,33 @@ 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 = {
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"cosmiconfig": "^9.0.0",
|
|
173
|
+
"ansis": "^3.17.0",
|
|
174
|
+
"awilix": "^12.0.5",
|
|
169
175
|
"detect-indent": "^7.0.1",
|
|
170
|
-
"
|
|
176
|
+
"lilconfig": "^3.1.3",
|
|
171
177
|
"npm-registry-fetch": "^18.0.2",
|
|
172
|
-
"
|
|
178
|
+
"picospinner": "^3.0.0",
|
|
173
179
|
"semver": "^7.7.0",
|
|
174
|
-
"tinyglobby": "^0.2.
|
|
180
|
+
"tinyglobby": "^0.2.12",
|
|
181
|
+
"yaml": "^2.7.1"
|
|
175
182
|
};
|
|
176
183
|
var devDependencies = {
|
|
177
|
-
"@eslint/js": "^9.
|
|
178
|
-
"@types/
|
|
179
|
-
"@types/
|
|
180
|
-
"@types/
|
|
181
|
-
"@
|
|
182
|
-
"@vitest/
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
"globals": "^15.14.0",
|
|
184
|
+
"@eslint/js": "^9.23.0",
|
|
185
|
+
"@types/node": "^22.13.17",
|
|
186
|
+
"@types/npm-registry-fetch": "^8.0.7 || ~18.0.0",
|
|
187
|
+
"@types/semver": "~7.7.0",
|
|
188
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
189
|
+
"@vitest/ui": "^3.1.1",
|
|
190
|
+
"eslint": "^9.23.0",
|
|
191
|
+
"globals": "^16.0.0",
|
|
186
192
|
"nodemon": "^3.1.9",
|
|
187
|
-
"
|
|
188
|
-
"
|
|
189
|
-
"tsdown": "^0.
|
|
190
|
-
"typescript": "^5.
|
|
191
|
-
"typescript-eslint": "^8.
|
|
192
|
-
"
|
|
193
|
+
"prettier": "^3.5.3",
|
|
194
|
+
"publint": "^0.3.9",
|
|
195
|
+
"tsdown": "^0.7.2",
|
|
196
|
+
"typescript": "^5.8.2",
|
|
197
|
+
"typescript-eslint": "^8.29.0",
|
|
198
|
+
"unplugin-unused": "^0.4.4",
|
|
199
|
+
"vitest": "^3.1.1"
|
|
193
200
|
};
|
|
194
201
|
var packageManager = "npm@10.8.2";
|
|
195
202
|
var package_default = {
|
|
@@ -241,19 +248,19 @@ async function run(syncer) {
|
|
|
241
248
|
printHelp();
|
|
242
249
|
return;
|
|
243
250
|
}
|
|
244
|
-
log(`TypeSync v${
|
|
251
|
+
log(`TypeSync v${white(package_default.version)}`);
|
|
245
252
|
if (flags.dry) log("—— DRY RUN — will not modify file ——");
|
|
246
|
-
const result = await spinWhile(`Syncing type definitions in ${
|
|
253
|
+
const result = await spinWhile(`Syncing type definitions in ${cyan(filePath)}...`, async () => await syncer.sync(filePath, flags));
|
|
247
254
|
const syncedFilesOutput = result.syncedFiles.map(renderSyncedFile).join("\n\n");
|
|
248
255
|
const totals = result.syncedFiles.reduce((accum, f) => ({ newTypings: accum.newTypings + f.newTypings.length }), { newTypings: 0 });
|
|
249
|
-
const syncMessage = `\n\n${syncedFilesOutput}\n\n✨ Run ${
|
|
256
|
+
const syncMessage = `\n\n${syncedFilesOutput}\n\n✨ Run ${green`typesync`} again without the ${gray`--dry`} flag to update your ${gray`package.json`}.`;
|
|
250
257
|
if (flags.dry === "fail" && totals.newTypings > 0) {
|
|
251
258
|
error("Typings changed; check failed.");
|
|
252
259
|
log(syncMessage);
|
|
253
260
|
process.exitCode = 1;
|
|
254
261
|
return;
|
|
255
262
|
}
|
|
256
|
-
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 ${
|
|
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.`);
|
|
257
264
|
}
|
|
258
265
|
/**
|
|
259
266
|
* Renders a type definition.
|
|
@@ -262,7 +269,7 @@ async function run(syncer) {
|
|
|
262
269
|
*/
|
|
263
270
|
function renderTypeDef(typeDef, isLast) {
|
|
264
271
|
const treeNode = isLast ? "└─" : "├─";
|
|
265
|
-
return `${treeNode} ${
|
|
272
|
+
return `${treeNode} ${green.bold`+`} ${gray`@types/`}${bold.blue(typeDef.typingsName)}`;
|
|
266
273
|
}
|
|
267
274
|
/**
|
|
268
275
|
* Renders a synced file.
|
|
@@ -270,9 +277,9 @@ function renderTypeDef(typeDef, isLast) {
|
|
|
270
277
|
* @param file
|
|
271
278
|
*/
|
|
272
279
|
function renderSyncedFile(file) {
|
|
273
|
-
const badge = file.newTypings.length === 0 ?
|
|
280
|
+
const badge = file.newTypings.length === 0 ? blue.bold`(no new typings added)` : green.bold`(${file.newTypings.length.toString()} new typings added)`;
|
|
274
281
|
const dirName = path.basename(path.dirname(path.resolve(file.filePath)));
|
|
275
|
-
const title = `📦 ${file.package.name ?? dirName} ${
|
|
282
|
+
const title = `📦 ${file.package.name ?? dirName} ${gray.italic`— ${file.filePath}`} ${badge}`;
|
|
276
283
|
const nl = "\n";
|
|
277
284
|
const combined = [...file.newTypings.map((t) => ({
|
|
278
285
|
...t,
|
|
@@ -286,12 +293,12 @@ function renderSyncedFile(file) {
|
|
|
286
293
|
*/
|
|
287
294
|
function printHelp() {
|
|
288
295
|
console.log(`
|
|
289
|
-
${
|
|
296
|
+
${blue.bold`typesync`} - adds missing TypeScript definitions to package.json
|
|
290
297
|
|
|
291
298
|
Options
|
|
292
|
-
${
|
|
293
|
-
${
|
|
294
|
-
${
|
|
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
|
|
295
302
|
`.trim());
|
|
296
303
|
}
|
|
297
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","fsUtils","syncer: ITypeSyncer","packageJson","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.1\",\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.4\",\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.10\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.19.0\",\n \"@types/js-yaml\": \"~4.0.9 || ~4.1.0\",\n \"@types/node\": \"^22.13.0\",\n \"@types/npm-registry-fetch\": \"^8.0.7 || ~17.1.0\",\n \"@types/semver\": \"~7.5.8 || ~7.6.0\",\n \"@vitest/coverage-v8\": \"^3.0.4\",\n \"@vitest/ui\": \"^3.0.4\",\n \"eslint\": \"^9.19.0\",\n \"globals\": \"^15.14.0\",\n \"nodemon\": \"^3.1.9\",\n \"oxc-transform\": \"^0.48.1\",\n \"prettier\": \"^3.4.2\",\n \"tsdown\": \"^0.5.6\",\n \"typescript\": \"^5.7.3\",\n \"typescript-eslint\": \"^8.22.0\",\n \"vitest\": \"^3.0.4\"\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.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
1
|
+
|
|
2
|
+
//#region dist/.tsdown-types-es/globber.d.ts
|
|
4
3
|
interface IGlobber {
|
|
5
4
|
/**
|
|
6
5
|
* Globs for directory names.
|
|
@@ -10,10 +9,8 @@ interface IGlobber {
|
|
|
10
9
|
globDirs(this: void, root: string, patterns: Array<string>, ignore?: Array<string>): Promise<Array<string>>;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* It is used to allow syncing all types in a workspace when run from the root of a monorepo.
|
|
16
|
-
*/
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region dist/.tsdown-types-es/workspace-resolver.d.ts
|
|
17
14
|
interface IWorkspaceResolverService {
|
|
18
15
|
/**
|
|
19
16
|
* Reads, parses, and normalizes a workspaces configuration from the following files, in this order:
|
|
@@ -26,63 +23,22 @@ interface IWorkspaceResolverService {
|
|
|
26
23
|
*/
|
|
27
24
|
getWorkspaces(this: void, packageJson: IPackageFile, root: string, globber: IGlobber, ignored: IWorkspacesArray): Promise<IWorkspacesArray>;
|
|
28
25
|
}
|
|
29
|
-
/**
|
|
30
|
-
* @example
|
|
31
|
-
* ```json
|
|
32
|
-
* "workspaces": [
|
|
33
|
-
* "packages/*",
|
|
34
|
-
* ]
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
26
|
type IWorkspacesArray = Array<string>;
|
|
38
|
-
/**
|
|
39
|
-
* @example
|
|
40
|
-
* ```yaml
|
|
41
|
-
* packages:
|
|
42
|
-
* - 'packages/*'
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
27
|
interface IWorkspacesObject {
|
|
46
28
|
packages?: IWorkspacesArray;
|
|
47
29
|
}
|
|
48
|
-
/**
|
|
49
|
-
* @see {@link IWorkspacesArray}
|
|
50
|
-
*/
|
|
51
30
|
type NpmWorkspacesConfig = IWorkspacesArray;
|
|
52
|
-
/**
|
|
53
|
-
* Yarn is a special snowflake.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```json
|
|
57
|
-
* "workspaces": {
|
|
58
|
-
* "packages": [
|
|
59
|
-
* "packages/*",
|
|
60
|
-
* ],
|
|
61
|
-
* "nohoist": []
|
|
62
|
-
* }
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
31
|
type YarnWorkspacesConfig = IWorkspacesArray | (IWorkspacesObject & {
|
|
66
32
|
nohoist?: Array<string>
|
|
67
33
|
});
|
|
68
|
-
/**
|
|
69
|
-
* @see {@link IWorkspacesArray}
|
|
70
|
-
*/
|
|
71
34
|
type BunWorkspacesConfig = IWorkspacesArray;
|
|
72
|
-
/**
|
|
73
|
-
* Section in `package.json` representing workspaces.
|
|
74
|
-
*/
|
|
75
35
|
type IWorkspacesSection = NpmWorkspacesConfig | YarnWorkspacesConfig | BunWorkspacesConfig;
|
|
76
36
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*/
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region dist/.tsdown-types-es/types.d.ts
|
|
80
39
|
interface ITypeSyncer {
|
|
81
40
|
sync(this: void, filePath: string, flags: ICLIArguments["flags"]): Promise<ISyncResult>;
|
|
82
41
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Sync options.
|
|
85
|
-
*/
|
|
86
42
|
interface ISyncOptions {
|
|
87
43
|
/**
|
|
88
44
|
* Ignore certain deps.
|
|
@@ -97,9 +53,6 @@ interface ISyncOptions {
|
|
|
97
53
|
*/
|
|
98
54
|
ignoreProjects?: IWorkspacesArray;
|
|
99
55
|
}
|
|
100
|
-
/**
|
|
101
|
-
* Package.json file.
|
|
102
|
-
*/
|
|
103
56
|
interface IPackageFile {
|
|
104
57
|
name?: string;
|
|
105
58
|
dependencies?: IDependenciesSection;
|
|
@@ -109,43 +62,25 @@ interface IPackageFile {
|
|
|
109
62
|
workspaces?: IWorkspacesSection;
|
|
110
63
|
[key: string]: unknown;
|
|
111
64
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Section in package.json representing dependencies.
|
|
114
|
-
*/
|
|
115
65
|
type IDependenciesSection = Record<string, string>;
|
|
116
|
-
/**
|
|
117
|
-
* Package + version record, collected from the {"package": "^1.2.3"} sections.
|
|
118
|
-
*/
|
|
119
66
|
interface IPackageVersion {
|
|
120
67
|
name: string;
|
|
121
68
|
version: string;
|
|
122
69
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Describes how a package may be typed.
|
|
125
|
-
*/
|
|
126
70
|
interface IPackageTypingDescriptor {
|
|
127
71
|
typingsName: string;
|
|
128
72
|
codePackageName: string;
|
|
129
73
|
typesPackageName: string;
|
|
130
74
|
}
|
|
131
|
-
/**
|
|
132
|
-
* A type definition with the corresponding code package name.
|
|
133
|
-
*/
|
|
134
75
|
interface ISyncedTypeDefinition extends IPackageTypingDescriptor {
|
|
135
76
|
codePackageName: string;
|
|
136
77
|
}
|
|
137
|
-
/**
|
|
138
|
-
* Sync result.
|
|
139
|
-
*/
|
|
140
78
|
interface ISyncResult {
|
|
141
79
|
/**
|
|
142
80
|
* The files that were synced.
|
|
143
81
|
*/
|
|
144
82
|
syncedFiles: Array<ISyncedFile>;
|
|
145
83
|
}
|
|
146
|
-
/**
|
|
147
|
-
* A file that was synced.
|
|
148
|
-
*/
|
|
149
84
|
interface ISyncedFile {
|
|
150
85
|
/**
|
|
151
86
|
* The cwd-relative path to the synced file.
|
|
@@ -160,26 +95,19 @@ interface ISyncedFile {
|
|
|
160
95
|
*/
|
|
161
96
|
newTypings: Array<ISyncedTypeDefinition>;
|
|
162
97
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Dependency sections.
|
|
165
|
-
*/
|
|
166
98
|
declare enum IDependencySection {
|
|
167
99
|
dev = "dev",
|
|
168
100
|
deps = "deps",
|
|
169
101
|
optional = "optional",
|
|
170
102
|
peer = "peer",
|
|
171
103
|
}
|
|
172
|
-
/**
|
|
173
|
-
* CLI arguments.
|
|
174
|
-
*/
|
|
175
104
|
interface ICLIArguments {
|
|
176
105
|
flags: Record<string, boolean | string | undefined>;
|
|
177
106
|
args: Array<string>;
|
|
178
107
|
}
|
|
179
108
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
*/
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region dist/.tsdown-types-es/config-service.d.ts
|
|
183
111
|
interface IConfigService {
|
|
184
112
|
/**
|
|
185
113
|
* Get typesync config.
|
|
@@ -188,17 +116,15 @@ interface IConfigService {
|
|
|
188
116
|
}
|
|
189
117
|
declare function createConfigService(): IConfigService;
|
|
190
118
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
*/
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region dist/.tsdown-types-es/versioning.d.ts
|
|
194
121
|
interface IPackageVersionInfo {
|
|
195
122
|
version: string;
|
|
196
123
|
containsInternalTypings: boolean;
|
|
197
124
|
}
|
|
198
125
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
*/
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region dist/.tsdown-types-es/package-source.d.ts
|
|
202
128
|
interface IPackageSource {
|
|
203
129
|
/**
|
|
204
130
|
* Fetches package info from an external source.
|
|
@@ -207,23 +133,16 @@ interface IPackageSource {
|
|
|
207
133
|
*/
|
|
208
134
|
fetch(this: void, packageName: string): Promise<IPackageInfo | null>;
|
|
209
135
|
}
|
|
210
|
-
/**
|
|
211
|
-
* Interface for the Package Info structure.
|
|
212
|
-
*/
|
|
213
136
|
interface IPackageInfo {
|
|
214
137
|
name: string;
|
|
215
138
|
latestVersion: string;
|
|
216
139
|
deprecated: boolean;
|
|
217
140
|
versions: Array<IPackageVersionInfo>;
|
|
218
141
|
}
|
|
219
|
-
/**
|
|
220
|
-
* Creates a package source.
|
|
221
|
-
*/
|
|
222
142
|
declare function createPackageSource(): IPackageSource;
|
|
223
143
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
*/
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region dist/.tsdown-types-es/package-json-file-service.d.ts
|
|
227
146
|
interface IPackageJSONService {
|
|
228
147
|
/**
|
|
229
148
|
* Reads and parses JSON from the specified file. Path is relative to the current working directory.
|
|
@@ -235,12 +154,9 @@ interface IPackageJSONService {
|
|
|
235
154
|
writePackageFile(this: void, filePath: string, fileContents: IPackageFile): Promise<void>;
|
|
236
155
|
}
|
|
237
156
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
*
|
|
241
|
-
* @param packageJSONservice
|
|
242
|
-
* @param typeDefinitionSource
|
|
243
|
-
*/
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region dist/.tsdown-types-es/type-syncer.d.ts
|
|
244
159
|
declare function createTypeSyncer(packageJSONService: IPackageJSONService, workspaceResolverService: IWorkspaceResolverService, packageSource: IPackageSource, configService: IConfigService, globber: IGlobber): ITypeSyncer;
|
|
245
160
|
|
|
246
|
-
|
|
161
|
+
//#endregion
|
|
162
|
+
export { ICLIArguments, IConfigService, IDependenciesSection, IDependencySection, IPackageFile, IPackageInfo, IPackageSource, IPackageTypingDescriptor, IPackageVersion, ISyncOptions, ISyncResult, ISyncedFile, ISyncedTypeDefinition, ITypeSyncer, createConfigService, createPackageSource, createTypeSyncer };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-
|
|
1
|
+
import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-D40qMMFq.js";
|
|
2
2
|
|
|
3
3
|
export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as path$1 from "node:path";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import {
|
|
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
|
|
|
7
8
|
//#region src/types.ts
|
|
8
|
-
let IDependencySection = function(IDependencySection$1) {
|
|
9
|
+
let IDependencySection = /* @__PURE__ */ function(IDependencySection$1) {
|
|
9
10
|
IDependencySection$1["dev"] = "dev";
|
|
10
11
|
IDependencySection$1["deps"] = "deps";
|
|
11
12
|
IDependencySection$1["optional"] = "optional";
|
|
@@ -20,7 +21,7 @@ function uniq(source) {
|
|
|
20
21
|
}
|
|
21
22
|
function shrinkObject(source) {
|
|
22
23
|
const object = {};
|
|
23
|
-
for (const key in source) if (source[key] !==
|
|
24
|
+
for (const key in source) if (source[key] !== void 0) object[key] = source[key];
|
|
24
25
|
return object;
|
|
25
26
|
}
|
|
26
27
|
function mergeObjects(source) {
|
|
@@ -63,7 +64,37 @@ function memoizeAsync(fn) {
|
|
|
63
64
|
|
|
64
65
|
//#endregion
|
|
65
66
|
//#region src/config-service.ts
|
|
66
|
-
|
|
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 ?? {});
|
|
@@ -77,7 +108,7 @@ function createConfigService() {
|
|
|
77
108
|
function readCliConfig(flags) {
|
|
78
109
|
const readValues = (key, validator) => {
|
|
79
110
|
const values = flags[key];
|
|
80
|
-
return typeof values === "string" ? values.split(",").filter((value) => validator ? validator(value) : true) :
|
|
111
|
+
return typeof values === "string" ? values.split(",").filter((value) => validator ? validator(value) : true) : void 0;
|
|
81
112
|
};
|
|
82
113
|
return {
|
|
83
114
|
ignoreDeps: readValues("ignoredeps", isIgnoreDepConfigValue),
|
|
@@ -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-
|
|
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.
|
|
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,33 +47,33 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/jeffijoe/typesync#readme",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"cosmiconfig": "^9.0.0",
|
|
50
|
+
"ansis": "^3.17.0",
|
|
51
|
+
"awilix": "^12.0.5",
|
|
53
52
|
"detect-indent": "^7.0.1",
|
|
54
|
-
"
|
|
53
|
+
"lilconfig": "^3.1.3",
|
|
55
54
|
"npm-registry-fetch": "^18.0.2",
|
|
56
|
-
"
|
|
55
|
+
"picospinner": "^3.0.0",
|
|
57
56
|
"semver": "^7.7.0",
|
|
58
|
-
"tinyglobby": "^0.2.
|
|
57
|
+
"tinyglobby": "^0.2.12",
|
|
58
|
+
"yaml": "^2.7.1"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@eslint/js": "^9.
|
|
62
|
-
"@types/
|
|
63
|
-
"@types/
|
|
64
|
-
"@types/
|
|
65
|
-
"@
|
|
66
|
-
"@vitest/
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"globals": "^15.14.0",
|
|
61
|
+
"@eslint/js": "^9.23.0",
|
|
62
|
+
"@types/node": "^22.13.17",
|
|
63
|
+
"@types/npm-registry-fetch": "^8.0.7 || ~18.0.0",
|
|
64
|
+
"@types/semver": "~7.7.0",
|
|
65
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
66
|
+
"@vitest/ui": "^3.1.1",
|
|
67
|
+
"eslint": "^9.23.0",
|
|
68
|
+
"globals": "^16.0.0",
|
|
70
69
|
"nodemon": "^3.1.9",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"tsdown": "^0.
|
|
74
|
-
"typescript": "^5.
|
|
75
|
-
"typescript-eslint": "^8.
|
|
76
|
-
"
|
|
70
|
+
"prettier": "^3.5.3",
|
|
71
|
+
"publint": "^0.3.9",
|
|
72
|
+
"tsdown": "^0.7.2",
|
|
73
|
+
"typescript": "^5.8.2",
|
|
74
|
+
"typescript-eslint": "^8.29.0",
|
|
75
|
+
"unplugin-unused": "^0.4.4",
|
|
76
|
+
"vitest": "^3.1.1"
|
|
77
77
|
},
|
|
78
78
|
"packageManager": "npm@10.8.2"
|
|
79
79
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"type-syncer-D93oGCvC.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","globber","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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"}
|