typesync 0.13.5-0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  /**
2
2
  * Starts the TypeSync CLI.
3
3
  */
4
- export declare function startCli(): Promise<void>;
4
+ declare function startCli(): Promise<void>;
5
+
6
+ export { startCli };
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
- import { createConfigService, createPackageSource, createTypeSyncer, ensureWorkspacesArray, uniq } from "./type-syncer-C_rkDNfx.js";
1
+ import { createConfigService, createPackageSource, createTypeSyncer, uniq } from "./type-syncer-D93oGCvC.js";
2
2
  import * as path$1 from "node:path";
3
3
  import * as path from "node:path";
4
4
  import { InjectionMode, asFunction, createContainer } from "awilix";
5
- import chalk, { default as chalk$1 } from "chalk";
5
+ import chalk from "chalk";
6
6
  import { oraPromise } from "ora";
7
7
  import { glob } from "tinyglobby";
8
8
  import * as fsp from "node:fs/promises";
@@ -22,18 +22,18 @@ var __export = (target, all) => {
22
22
  //#endregion
23
23
  //#region src/cli-util.ts
24
24
  function log(message) {
25
- console.log(`${chalk$1.white("»")} ${chalk$1.gray(message)}`);
25
+ console.log(`${chalk.white("»")} ${chalk.gray(message)}`);
26
26
  }
27
27
  function success(text) {
28
- console.log(`${chalk$1.green("✔")} ${chalk$1.white(text)}`);
28
+ console.log(`${chalk.green("✔")} ${chalk.white(text)}`);
29
29
  }
30
30
  function error(err) {
31
31
  const msg = err instanceof Error ? err.message : err;
32
32
  const stack = err instanceof Error ? `\nStack:\n${err.stack}` : "";
33
- console.log(`${chalk$1.red("✖")} ${chalk$1.bgRed(chalk$1.white(msg))}${stack}`);
33
+ console.log(`${chalk.red("✖")} ${chalk.bgRed(chalk.white(msg))}${stack}`);
34
34
  }
35
35
  async function spinWhile(text, fn) {
36
- return await oraPromise(fn(), { text: ` ${chalk$1.gray(text)}` });
36
+ return await oraPromise(fn(), { text: ` ${chalk.gray(text)}` });
37
37
  }
38
38
  function parseArguments(argv) {
39
39
  const flags = {};
@@ -43,7 +43,7 @@ function parseArguments(argv) {
43
43
  const afterEq = arg.substring(idx + 1);
44
44
  flags[arg.substring(2, idx)] = afterEq;
45
45
  } else flags[arg.substring(2)] = true;
46
- else args.push(arg);
46
+ else args.push(arg);
47
47
  return {
48
48
  flags,
49
49
  args
@@ -53,10 +53,11 @@ else args.push(arg);
53
53
  //#endregion
54
54
  //#region src/globber.ts
55
55
  function createGlobber() {
56
- return { async glob(root, filenames, ignore = []) {
57
- const source = await glob(filenames, {
56
+ return { async globDirs(root, patterns, ignore = []) {
57
+ const source = await glob(patterns, {
58
58
  cwd: root,
59
- ignore: ["**/node_modules/**", ...ignore]
59
+ ignore: ["**/node_modules/**", ...ignore],
60
+ onlyDirectories: true
60
61
  });
61
62
  return uniq(source);
62
63
  } };
@@ -68,7 +69,7 @@ var fs_utils_exports = {};
68
69
  __export(fs_utils_exports, { readFileContents: () => readFileContents });
69
70
  async function readFileContents(filePath) {
70
71
  try {
71
- return readFile(filePath, "utf-8");
72
+ return await readFile(filePath, "utf-8");
72
73
  } catch (err) {
73
74
  if (err.code === "ENOENT") throw new Error(`${filePath} does not exist.`);
74
75
  throw err;
@@ -97,8 +98,8 @@ function createPackageJSONFileService() {
97
98
  //#region src/workspace-resolver.ts
98
99
  function createWorkspaceResolverService({ readFileContents: readFileContents$1 }) {
99
100
  return { getWorkspaces: async (packageJson, root, globber, ignored) => {
100
- const [workspaces, ignoredWorkspaces] = await Promise.all([getWorkspaces(packageJson, root), globber.glob(root, ignored)]);
101
- return await globber.glob(root, ensureWorkspacesArray(workspaces), ignoredWorkspaces);
101
+ const workspaces = await getWorkspaces(packageJson, root);
102
+ return await globber.globDirs(root, ensureWorkspacesArray(workspaces), ignored);
102
103
  } };
103
104
  async function getWorkspaces(packageJson, root) {
104
105
  const packageJsonWorkspaces = packageJson.workspaces;
@@ -107,7 +108,7 @@ function createWorkspaceResolverService({ readFileContents: readFileContents$1 }
107
108
  }
108
109
  async function getPnpmWorkspaces(root) {
109
110
  try {
110
- const filePath = path$1.relative(root, "pnpm-workspace.yaml");
111
+ const filePath = path$1.join(root, "pnpm-workspace.yaml");
111
112
  const contents = await readFileContents$1(filePath);
112
113
  const pnpmWorkspaces = yaml.load(contents);
113
114
  return pnpmWorkspaces.packages;
@@ -116,11 +117,17 @@ function createWorkspaceResolverService({ readFileContents: readFileContents$1 }
116
117
  }
117
118
  }
118
119
  }
120
+ function ensureWorkspacesArray(data) {
121
+ if (!data) return [];
122
+ if (!Array.isArray(data)) return ensureWorkspacesArray(data.packages);
123
+ if (!data.every((s) => typeof s === "string")) return [];
124
+ return data;
125
+ }
119
126
 
120
127
  //#endregion
121
128
  //#region package.json
122
129
  var name = "typesync";
123
- var version = "0.13.5-0";
130
+ var version = "0.14.1";
124
131
  var type = "module";
125
132
  var description = "Install missing TypeScript typings for your dependencies.";
126
133
  var engines = { "node": "^18.20.0 || ^20.10.0 || >=22.0.0" };
@@ -133,23 +140,20 @@ var exports = { ".": {
133
140
  var scripts = {
134
141
  "test": "vitest run",
135
142
  "test:watch": "vitest --ui",
136
- "lint": "eslint --fix && tsc && npm run format",
143
+ "fix": "eslint --fix && npm run format",
144
+ "lint": "eslint && tsc && npm run format:check",
137
145
  "format": "prettier --write 'src/**/*.ts'",
138
- "lint:watch": "nodemon --exec npm run lint -e ts,js",
146
+ "format:check": "prettier --check 'src/**/*.ts'",
147
+ "lint:watch": "nodemon --exec npm run lint",
139
148
  "build": "tsdown",
149
+ "build:watch": "tsdown --watch",
140
150
  "run-cli": "npm run build && node bin/typesync",
141
151
  "run-cli:dry": "npm run run-cli -- --dry",
142
- "precommit": "lint-staged",
143
152
  "do:publish": "npm run lint && npm run test && npm run build && npm publish",
144
153
  "release:patch": "npm version patch && npm run do:publish && git push --follow-tags",
145
154
  "release:minor": "npm version minor && npm run do:publish && git push --follow-tags",
146
155
  "release:prerelease": "npm version prerelease && npm run do:publish && git push --follow-tags"
147
156
  };
148
- var lint_staged = { "*.ts": [
149
- "eslint --fix",
150
- "prettier --write",
151
- "git add"
152
- ] };
153
157
  var repository = {
154
158
  "type": "git",
155
159
  "url": "git+https://github.com/jeffijoe/typesync.git"
@@ -159,35 +163,35 @@ var license = "MIT";
159
163
  var bugs = { "url": "https://github.com/jeffijoe/typesync/issues" };
160
164
  var homepage = "https://github.com/jeffijoe/typesync#readme";
161
165
  var dependencies = {
162
- "awilix": "^10.0.2",
163
- "chalk": "^5.3.0",
166
+ "awilix": "^12.0.4",
167
+ "chalk": "^5.4.1",
164
168
  "cosmiconfig": "^9.0.0",
165
169
  "detect-indent": "^7.0.1",
166
170
  "js-yaml": "^4.1.0",
167
- "npm-registry-fetch": "^17.1.0",
171
+ "npm-registry-fetch": "^18.0.2",
168
172
  "ora": "^8.1.1",
169
- "semver": "^7.6.2",
173
+ "semver": "^7.7.0",
170
174
  "tinyglobby": "^0.2.10"
171
175
  };
172
176
  var devDependencies = {
173
- "@eslint/js": "^9.16.0",
177
+ "@eslint/js": "^9.19.0",
174
178
  "@types/js-yaml": "~4.0.9 || ~4.1.0",
175
- "@types/node": "~18.19.67",
179
+ "@types/node": "^22.13.0",
176
180
  "@types/npm-registry-fetch": "^8.0.7 || ~17.1.0",
177
181
  "@types/semver": "~7.5.8 || ~7.6.0",
178
- "@vitest/coverage-v8": "^2.1.6",
179
- "@vitest/ui": "^2.1.6",
180
- "eslint": "^9.16.0",
181
- "globals": "^15.12.0",
182
- "nodemon": "^3.1.4",
183
- "oxc-transform": "^0.38.0",
184
- "prettier": "^3.3.2",
185
- "tsdown": "^0.3.1",
186
- "typescript": "^5.5.3",
187
- "typescript-eslint": "^8.16.0",
188
- "vitest": "^2.1.6"
182
+ "@vitest/coverage-v8": "^3.0.4",
183
+ "@vitest/ui": "^3.0.4",
184
+ "eslint": "^9.19.0",
185
+ "globals": "^15.14.0",
186
+ "nodemon": "^3.1.9",
187
+ "oxc-transform": "^0.48.1",
188
+ "prettier": "^3.4.2",
189
+ "tsdown": "^0.5.6",
190
+ "typescript": "^5.7.3",
191
+ "typescript-eslint": "^8.22.0",
192
+ "vitest": "^3.0.4"
189
193
  };
190
- var packageManager = "npm@8.19.4";
194
+ var packageManager = "npm@10.8.2";
191
195
  var package_default = {
192
196
  name,
193
197
  version,
@@ -198,7 +202,6 @@ var package_default = {
198
202
  bin,
199
203
  exports,
200
204
  scripts,
201
- "lint-staged": lint_staged,
202
205
  repository,
203
206
  author,
204
207
  license,
@@ -240,7 +243,7 @@ async function run(syncer) {
240
243
  }
241
244
  log(`TypeSync v${chalk.white(package_default.version)}`);
242
245
  if (flags.dry) log("—— DRY RUN — will not modify file ——");
243
- const result = await spinWhile(`Syncing type definitions in ${chalk.cyan(filePath)}...`, () => syncer.sync(filePath, flags));
246
+ const result = await spinWhile(`Syncing type definitions in ${chalk.cyan(filePath)}...`, async () => await syncer.sync(filePath, flags));
244
247
  const syncedFilesOutput = result.syncedFiles.map(renderSyncedFile).join("\n\n");
245
248
  const totals = result.syncedFiles.reduce((accum, f) => ({ newTypings: accum.newTypings + f.newTypings.length }), { newTypings: 0 });
246
249
  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")}.`;
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","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 filenames.\n *\n * @param root\n */\n glob(\n this: void,\n root: string,\n filenames: 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 glob(root, filenames, ignore = []): Promise<Array<string>> {\n const source = await glob(filenames, {\n cwd: root,\n ignore: ['**/node_modules/**', ...ignore],\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 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 { ensureWorkspacesArray } from './util'\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, ignoredWorkspaces] = await Promise.all([\n getWorkspaces(packageJson, root),\n globber.glob(root, ignored),\n ])\n\n return await globber.glob(\n root,\n ensureWorkspacesArray(workspaces),\n ignoredWorkspaces,\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.relative(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 \"name\": \"typesync\",\n \"version\": \"0.13.5-0\",\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 \"lint\": \"eslint --fix && tsc && npm run format\",\n \"format\": \"prettier --write 'src/**/*.ts'\",\n \"lint:watch\": \"nodemon --exec npm run lint -e ts,js\",\n \"build\": \"tsdown\",\n \"run-cli\": \"npm run build && node bin/typesync\",\n \"run-cli:dry\": \"npm run run-cli -- --dry\",\n \"precommit\": \"lint-staged\",\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 \"lint-staged\": {\n \"*.ts\": [\n \"eslint --fix\",\n \"prettier --write\",\n \"git add\"\n ]\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\": \"^10.0.2\",\n \"chalk\": \"^5.3.0\",\n \"cosmiconfig\": \"^9.0.0\",\n \"detect-indent\": \"^7.0.1\",\n \"js-yaml\": \"^4.1.0\",\n \"npm-registry-fetch\": \"^17.1.0\",\n \"ora\": \"^8.1.1\",\n \"semver\": \"^7.6.2\",\n \"tinyglobby\": \"^0.2.10\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.16.0\",\n \"@types/js-yaml\": \"~4.0.9 || ~4.1.0\",\n \"@types/node\": \"~18.19.67\",\n \"@types/npm-registry-fetch\": \"^8.0.7 || ~17.1.0\",\n \"@types/semver\": \"~7.5.8 || ~7.6.0\",\n \"@vitest/coverage-v8\": \"^2.1.6\",\n \"@vitest/ui\": \"^2.1.6\",\n \"eslint\": \"^9.16.0\",\n \"globals\": \"^15.12.0\",\n \"nodemon\": \"^3.1.4\",\n \"oxc-transform\": \"^0.38.0\",\n \"prettier\": \"^3.3.2\",\n \"tsdown\": \"^0.3.1\",\n \"typescript\": \"^5.5.3\",\n \"typescript-eslint\": \"^8.16.0\",\n \"vitest\": \"^2.1.6\"\n },\n \"packageManager\": \"npm@8.19.4\"\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 () => 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","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":";;;;;;;;;;;;;;;;;;;;;;;AAQO,SAAS,IAAIA,SAAuB;AACzC,SAAQ,KAAK,EAAE,MAAM,MAAM,IAAI,CAAC,IAAI,MAAM,KAAK,QAAQ,CAAC,EAAE;AAC3D;AAMM,SAAS,QAAQC,MAAoB;AAC1C,SAAQ,KAAK,EAAE,MAAM,MAAM,IAAI,CAAC,IAAI,MAAM,MAAM,KAAK,CAAC,EAAE;AACzD;AAMM,SAAS,MAAMC,KAA2B;CAC/C,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;CACjD,MAAM,QAAQ,eAAe,SAAS,YAAY,IAAI,MAAM,IAAI;AAChE,SAAQ,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE;AAC3E;AAOM,eAAe,UACpBD,MACAE,IACY;AACZ,QAAO,MAAM,WAAW,IAAI,EAAE,EAC5B,OAAO,GAAG,MAAM,KAAK,KAAK,CAAC,EAC5B,EAAC;AACH;AAMM,SAAS,eAAeC,MAAoC;CACjE,MAAMC,QAAgC,CAAE;CACxC,MAAMC,OAAsB,CAAE;AAC9B,MAAK,MAAM,OAAO,KAChB,KAAI,IAAI,WAAW,KAAK,CACtB,KAAI,IAAI,SAAS,IAAI,EAAE;EACrB,MAAM,MAAM,IAAI,QAAQ,IAAI;EAC5B,MAAM,UAAU,IAAI,UAAU,MAAM,EAAE;AACtC,QAAM,IAAI,UAAU,GAAG,IAAI,IAAI;CAChC,MACC,OAAM,IAAI,UAAU,EAAE,IAAI;KAG5B,MAAK,KAAK,IAAI;AAGlB,QAAO;EAAE;EAAO;CAAM;AACvB;;;;AC1CM,SAAS,gBAA0B;AACxC,QAAO,EACL,MAAM,SAAS,MAAM,UAAU,SAAS,CAAE,GAA0B;EAClE,MAAM,SAAS,MAAM,KAAK,UAAU;GAClC,KAAK;GACL,QAAQ,CAAC,sBAAsB,GAAG,MAAO;GACzC,iBAAiB;EAClB,EAAC;AAEF,SAAO,KAAK,OAAO;CACpB,EACF;AACF;;;;;;ACjCM,eAAe,iBAAiBC,UAAmC;AACxE,KAAI;AACF,SAAO,MAAM,SAAS,UAAU,QAAQ;CAEzC,SAAQ,KAAK;AAEZ,MAAK,IAA8B,SAAS,SAC1C,OAAM,IAAI,OAAO,EAAE,SAAS;AAI9B,QAAM;CACP;AACF;;;;ACQM,SAAS,+BAAoD;AAClE,QAAO;EACL,iBAAiB,OAAO,aAAa;GACnC,MAAM,WAAW,MAAM,iBAAiB,SAAS;AACjD,UAAO,KAAK,MAAM,SAAS;EAC5B;EACD,kBAAkB,OAAO,UAAU,gBAAgB;GACjD,MAAM,WAAW,MAAM,iBAAiB,SAAS;GACjD,MAAM,EAAE,QAAQ,GAAG,aAAa,SAAS;GACzC,MAAM,kBAAkB,SAAS,SAAS,SAAS,SAAS,KAAK,GAAG;GACpE,MAAM,OAAO,KAAK,UAChB,aACA,MACA,UAA+B,KAChC;AACD,SAAM,IAAI,UAAU,UAAU,QAAQ,kBAAkB,OAAO,IAAI;EACpE;CACF;AACF;;;;ACwDM,SAAS,+BAA+B,EAC7C,sCAGD,EAA6B;AAC5B,QAAO,EACL,eAAe,OAAO,aAAa,MAAM,SAAS,YAAY;EAC5D,MAAM,aAAa,MAAM,cAAc,aAAa,KAAK;AAEzD,SAAO,MAAM,QAAQ,SACnB,MACA,sBAAsB,WAAW,EACjC,QACD;CACF,EACF;CAED,eAAe,cACbC,aACAC,MACyC;EACzC,MAAM,wBAAwB,YAAY;AAC1C,MAAI,0BAA0B,UAC5B,QAAO;AAGT,SAAO,MAAM,kBAAkB,KAAK;CACrC;CAED,eAAe,kBACbA,MACuC;AACvC,MAAI;GACF,MAAM,WAAW,OAAK,KAAK,MAAM,sBAAsB;GACvD,MAAM,WAAW,MAAM,mBAAiB,SAAS;GACjD,MAAM,iBAAiB,KAAK,KAAK,SAAS;AAE1C,UAAO,eAAe;EACvB,QAAO;AACN,UAAO;EACR;CACF;AACF;AAOM,SAAS,sBACdC,MACkB;AAClB,MAAK,KACH,QAAO,CAAE;AAGX,MAAK,MAAM,QAAQ,KAAK,CACtB,QAAO,sBAAsB,KAAK,SAAS;AAG7C,MAAK,KAAK,MAAM,CAAC,aAAa,MAAM,SAAS,CAC3C,QAAO,CAAE;AAGX,QAAO;AACR;;;;WCjKS;cACG;WACH;kBACO;cACJ,UACD,mCACT;YACQ,CACP,QACA,KACD;UACM,cACO,iBACb;cACU,OACJ;UACM;YACE;AACZ,EACF;cACU;SACD;eACM;QACP;SACC;WACE;iBACM;eACF;UACL;gBACM;YACJ;gBACI;eACD;kBACG;kBACA;uBACK;AACvB;iBACa;SACJ;QACD;AACR;aACS;cACC;WACH,SACC,8CACR;eACW;mBACI;WACJ;UACD;gBACM;kBACE;YACN;uBACW;QACf;WACG;eACI;AACf;sBACkB;eACH;mBACI;gBACH;8BACc;kBACZ;wBACM;eACT;WACJ;YACC;YACA;kBACM;aACL;WACF;eACI;sBACO;WACX;AACX;qBACiB;sBA7EpB;;;;;;;;;;;;;;;;;;AA8EC;;;;ACzDM,eAAe,WAA0B;AAC9C,KAAI;EAEF,MAAM,YAAY,gBAAgB,EAChC,eAAe,cAAc,QAC9B,EAAC,CAAC,SAAS;GACV,oBAAoB,WAAW,6BAA6B,CAAC,WAAW;GACxE,0BAA0B,WAAW,MACnC,+BAA+BC,iBAAQ,CACxC,CAAC,WAAW;GACb,eAAe,WAAW,oBAAoB,CAAC,WAAW;GAC1D,eAAe,WAAW,oBAAoB,CAAC,WAAW;GAC1D,SAAS,WAAW,cAAc,CAAC,WAAW;GAC9C,YAAY,WAAW,iBAAiB;EACzC,EAAC;AACF,QAAM,IAAI,UAAU,QAAqB,aAAa,CAAC;CACxD,SAAQ,KAAK;AACZ,QAAQ,IAAW;AACnB,UAAQ,WAAW;CACpB;AACF;;;;;AAMD,eAAe,IAAIC,QAAqB;CACtC,MAAM,EAAE,MAAM,OAAO,GAAG,eAAiB,QAAQ,KAAK,MAAM,EAAE,CAAC;CAC/D,MAAM,CAAC,WAAW,eAAe,GAAG;AACpC,KAAI,MAAM,MAAM;AACd,aAAW;AACX;CACD;AAED,MAAO,YAAY,MAAM,MAAMC,gBAAY,QAAQ,CAAC,EAAE;AACtD,KAAI,MAAM,IACR,KAAM,uCAAuC;CAE/C,MAAM,SAAS,MAAM,WAClB,8BAA8B,MAAM,KAAK,SAAS,CAAC,MACpD,YAAY,MAAM,OAAO,KAAK,UAAU,MAAM,CAC/C;CAED,MAAM,oBAAoB,OAAO,YAC9B,IAAI,iBAAiB,CACrB,KAAK,OAAO;CACf,MAAM,SAAS,OAAO,YAAY,OAChC,CAAC,OAAO,OAAO,EACb,YAAY,MAAM,aAAa,EAAE,WAAW,OAC7C,IACD,EAAE,YAAY,EAAG,EAClB;CAED,MAAM,eAAe,MAAM,kBAAkB,aAAa,MAAM,MAAM,WAAW,CAAC,qBAAqB,MAAM,KAAK,QAAQ,CAAC,uBAAuB,MAAM,KAAK,eAAe,CAAC;AAC7K,KAAI,MAAM,QAAQ,UAAU,OAAO,aAAa,GAAG;AACjD,QAAQ,iCAAiC;AACzC,MAAM,YAAY;AAClB,UAAQ,WAAW;AACnB;CACD;AACD,SACE,OAAO,eAAe,KACjB,2DACD,MAAM,OACH,EAAE,OAAO,WAAW,UAAU,CAAC,4BAA4B,YAAY,KACvE,EAAE,OAAO,WAAW,UAAU,CAAC,yBAAyB,kBAAkB,0BAA0B,MAAM,MAAM,cAAc,CAAC,IAAI,MAAM,MAAM,OAAO,CAAC,OAAO,MAAM,MAAM,SAAS,CAAC,2CAC5L;AACF;;;;;;AAOD,SAAS,cAAcC,SAAmCC,QAAiB;CACzE,MAAM,WAAW,SAAS,OAAO;AACjC,SAAQ,EAAE,SAAS,GAAG,MAAM,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,UAAU,CAAC,EAAE,MAAM,KAAK,KAAK,QAAQ,YAAY,CAAC;AAC7G;;;;;;AAOD,SAAS,iBAAiBC,MAAmB;CAC3C,MAAM,QACJ,KAAK,WAAW,WAAW,IACvB,MAAM,KAAK,KAAK,yBAAyB,GACzC,MAAM,MAAM,MACT,GAAG,KAAK,WAAW,OAAO,UAAU,CAAC,qBACvC;CAEP,MAAM,UAAU,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,SAAS,CAAC,CAAC;CACxE,MAAM,SAAS,KAAK,KAAK,QAAQ,QAAQ,QAAQ,GAAG,MAAM,KAAK,QAC5D,IAAI,KAAK,SAAS,EACpB,CAAC,GAAG,MAAM;CAEX,MAAM,KAAK;CACX,MAAM,WAAW,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,OAAO;EAAE,GAAG;EAAG,QAAQ;CAAO,GAAE,AAAC;CAC3E,MAAM,WACJ,QACA,KACA,SACG,IAAI,CAAC,MAAM,cAAc,GAAG,SAAS,SAAS,SAAS,OAAO,EAAE,CAAC,CACjE,KAAK,GAAG;AAEb,QAAO;AACR;;;;AAKD,SAAS,YAAY;AACnB,SAAQ,IACN,CAAC;EACH,MAAM,KAAK,KAAK,WAAW,CAAC;;;IAG1B,MAAM,QAAQ,KAAK,QAAQ,CAAC;IAC5B,MAAM,QAAQ,KAAK,wCAAwC,CAAC,4FAA4F,MAAM,QAAQ,sBAAsB,CAAC;IAC7L,MAAM,QAAQ,KAAK,SAAS,CAAC;IAC7B,MAAM,CACP;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,246 @@
1
- export * from "./config-service.js";
2
- export * from "./package-source.js";
3
- export * from "./type-syncer.js";
4
- export * from "./types.js";
1
+ /**
2
+ * Globber interface.
3
+ */
4
+ interface IGlobber {
5
+ /**
6
+ * Globs for directory names.
7
+ *
8
+ * @param root
9
+ */
10
+ globDirs(this: void, root: string, patterns: Array<string>, ignore?: Array<string>): Promise<Array<string>>;
11
+ }
12
+
13
+ /**
14
+ * Service for fetching monorepo workspaces in a standardized format agnostic of the package manager used.
15
+ * It is used to allow syncing all types in a workspace when run from the root of a monorepo.
16
+ */
17
+ interface IWorkspaceResolverService {
18
+ /**
19
+ * Reads, parses, and normalizes a workspaces configuration from the following files, in this order:
20
+ * - `package.json` `workspaces` field, as an array of globs.
21
+ * - `package.json` `workspaces` field, as an object with a `packages` field, which is an array of globs.
22
+ * - `pnpm-workspace.yaml` `packages` field, as an array of globs.
23
+ *
24
+ * Path is relative to the current working directory.
25
+ * Note that this returns a list of directories, not paths to the manifests themselves.
26
+ */
27
+ getWorkspaces(this: void, packageJson: IPackageFile, root: string, globber: IGlobber, ignored: IWorkspacesArray): Promise<IWorkspacesArray>;
28
+ }
29
+ /**
30
+ * @example
31
+ * ```json
32
+ * "workspaces": [
33
+ * "packages/*",
34
+ * ]
35
+ * ```
36
+ */
37
+ type IWorkspacesArray = Array<string>;
38
+ /**
39
+ * @example
40
+ * ```yaml
41
+ * packages:
42
+ * - 'packages/*'
43
+ * ```
44
+ */
45
+ interface IWorkspacesObject {
46
+ packages?: IWorkspacesArray;
47
+ }
48
+ /**
49
+ * @see {@link IWorkspacesArray}
50
+ */
51
+ 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
+ type YarnWorkspacesConfig = IWorkspacesArray | (IWorkspacesObject & {
66
+ nohoist?: Array<string>
67
+ });
68
+ /**
69
+ * @see {@link IWorkspacesArray}
70
+ */
71
+ type BunWorkspacesConfig = IWorkspacesArray;
72
+ /**
73
+ * Section in `package.json` representing workspaces.
74
+ */
75
+ type IWorkspacesSection = NpmWorkspacesConfig | YarnWorkspacesConfig | BunWorkspacesConfig;
76
+
77
+ /**
78
+ * The guts of the program.
79
+ */
80
+ interface ITypeSyncer {
81
+ sync(this: void, filePath: string, flags: ICLIArguments["flags"]): Promise<ISyncResult>;
82
+ }
83
+ /**
84
+ * Sync options.
85
+ */
86
+ interface ISyncOptions {
87
+ /**
88
+ * Ignore certain deps.
89
+ */
90
+ ignoreDeps?: Array<IDependencySection>;
91
+ /**
92
+ * Ignore certain packages.
93
+ */
94
+ ignorePackages?: Array<string>;
95
+ /**
96
+ * Skip resolution of certain projects in the workspace.
97
+ */
98
+ ignoreProjects?: IWorkspacesArray;
99
+ }
100
+ /**
101
+ * Package.json file.
102
+ */
103
+ interface IPackageFile {
104
+ name?: string;
105
+ dependencies?: IDependenciesSection;
106
+ devDependencies?: IDependenciesSection;
107
+ peerDependencies?: IDependenciesSection;
108
+ optionalDependencies?: IDependenciesSection;
109
+ workspaces?: IWorkspacesSection;
110
+ [key: string]: unknown;
111
+ }
112
+ /**
113
+ * Section in package.json representing dependencies.
114
+ */
115
+ type IDependenciesSection = Record<string, string>;
116
+ /**
117
+ * Package + version record, collected from the {"package": "^1.2.3"} sections.
118
+ */
119
+ interface IPackageVersion {
120
+ name: string;
121
+ version: string;
122
+ }
123
+ /**
124
+ * Describes how a package may be typed.
125
+ */
126
+ interface IPackageTypingDescriptor {
127
+ typingsName: string;
128
+ codePackageName: string;
129
+ typesPackageName: string;
130
+ }
131
+ /**
132
+ * A type definition with the corresponding code package name.
133
+ */
134
+ interface ISyncedTypeDefinition extends IPackageTypingDescriptor {
135
+ codePackageName: string;
136
+ }
137
+ /**
138
+ * Sync result.
139
+ */
140
+ interface ISyncResult {
141
+ /**
142
+ * The files that were synced.
143
+ */
144
+ syncedFiles: Array<ISyncedFile>;
145
+ }
146
+ /**
147
+ * A file that was synced.
148
+ */
149
+ interface ISyncedFile {
150
+ /**
151
+ * The cwd-relative path to the synced file.
152
+ */
153
+ filePath: string;
154
+ /**
155
+ * The package file that was synced.
156
+ */
157
+ package: IPackageFile;
158
+ /**
159
+ * The new typings that were added.
160
+ */
161
+ newTypings: Array<ISyncedTypeDefinition>;
162
+ }
163
+ /**
164
+ * Dependency sections.
165
+ */
166
+ declare enum IDependencySection {
167
+ dev = "dev",
168
+ deps = "deps",
169
+ optional = "optional",
170
+ peer = "peer",
171
+ }
172
+ /**
173
+ * CLI arguments.
174
+ */
175
+ interface ICLIArguments {
176
+ flags: Record<string, boolean | string | undefined>;
177
+ args: Array<string>;
178
+ }
179
+
180
+ /**
181
+ * Config Service.
182
+ */
183
+ interface IConfigService {
184
+ /**
185
+ * Get typesync config.
186
+ */
187
+ readConfig(this: void, filePath: string, flags: ICLIArguments["flags"]): Promise<ISyncOptions>;
188
+ }
189
+ declare function createConfigService(): IConfigService;
190
+
191
+ /**
192
+ * Version descriptor for versions returned in remote package info.
193
+ */
194
+ interface IPackageVersionInfo {
195
+ version: string;
196
+ containsInternalTypings: boolean;
197
+ }
198
+
199
+ /**
200
+ * Fetches info about a package.
201
+ */
202
+ interface IPackageSource {
203
+ /**
204
+ * Fetches package info from an external source.
205
+ *
206
+ * @param packageName
207
+ */
208
+ fetch(this: void, packageName: string): Promise<IPackageInfo | null>;
209
+ }
210
+ /**
211
+ * Interface for the Package Info structure.
212
+ */
213
+ interface IPackageInfo {
214
+ name: string;
215
+ latestVersion: string;
216
+ deprecated: boolean;
217
+ versions: Array<IPackageVersionInfo>;
218
+ }
219
+ /**
220
+ * Creates a package source.
221
+ */
222
+ declare function createPackageSource(): IPackageSource;
223
+
224
+ /**
225
+ * File service.
226
+ */
227
+ interface IPackageJSONService {
228
+ /**
229
+ * Reads and parses JSON from the specified file. Path is relative to the current working directory.
230
+ */
231
+ readPackageFile(this: void, filePath: string): Promise<IPackageFile>;
232
+ /**
233
+ * Writes the JSON to the specified file.
234
+ */
235
+ writePackageFile(this: void, filePath: string, fileContents: IPackageFile): Promise<void>;
236
+ }
237
+
238
+ /**
239
+ * Creates a type syncer.
240
+ *
241
+ * @param packageJSONservice
242
+ * @param typeDefinitionSource
243
+ */
244
+ declare function createTypeSyncer(packageJSONService: IPackageJSONService, workspaceResolverService: IWorkspaceResolverService, packageSource: IPackageSource, configService: IConfigService, globber: IGlobber): ITypeSyncer;
245
+
246
+ export { type ICLIArguments, type IConfigService, type IDependenciesSection, IDependencySection, type IPackageFile, type IPackageInfo, type IPackageSource, type IPackageTypingDescriptor, type IPackageVersion, type ISyncOptions, type ISyncResult, type ISyncedFile, type ISyncedTypeDefinition, type ITypeSyncer, createConfigService, createPackageSource, createTypeSyncer };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-C_rkDNfx.js";
1
+ import { IDependencySection, createConfigService, createPackageSource, createTypeSyncer } from "./type-syncer-D93oGCvC.js";
2
2
 
3
3
  export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer };
@@ -54,18 +54,12 @@ function memoizeAsync(fn) {
54
54
  }
55
55
  return async function(...args) {
56
56
  const key = args[0];
57
- if (cache.has(key)) return cache.get(key);
57
+ if (cache.has(key)) return await cache.get(key);
58
58
  const p = run(...args);
59
59
  cache.set(key, p);
60
- return p;
60
+ return await p;
61
61
  };
62
62
  }
63
- function ensureWorkspacesArray(data) {
64
- if (!data) return [];
65
- if (!Array.isArray(data)) return ensureWorkspacesArray(data.packages);
66
- if (!data.every((s) => typeof s === "string")) return [];
67
- return data;
68
- }
69
63
 
70
64
  //#endregion
71
65
  //#region src/config-service.ts
@@ -166,7 +160,7 @@ function createTypeSyncer(packageJSONService, workspaceResolverService, packageS
166
160
  const dryRun = !!flags.dry;
167
161
  const syncOpts = await configService.readConfig(filePath, flags);
168
162
  const { file, subManifests } = await getManifests(filePath, globber, syncOpts.ignoreProjects ?? []);
169
- const syncedFiles = await Promise.all([syncFile(filePath, file, syncOpts, dryRun), ...subManifests.map(async (p) => syncFile(p, await packageJSONService.readPackageFile(p), syncOpts, dryRun))]);
163
+ const syncedFiles = await Promise.all([syncFile(filePath, file, syncOpts, dryRun), ...subManifests.map(async (p) => await syncFile(p, await packageJSONService.readPackageFile(p), syncOpts, dryRun))]);
170
164
  return { syncedFiles };
171
165
  }
172
166
  /**
@@ -176,9 +170,10 @@ function createTypeSyncer(packageJSONService, workspaceResolverService, packageS
176
170
  * @param globber
177
171
  */
178
172
  async function getManifests(filePath, globber$1, ignoredWorkspaces) {
173
+ const root = path.dirname(filePath);
179
174
  const file = await packageJSONService.readPackageFile(filePath);
180
- const subPackages = await workspaceResolverService.getWorkspaces(file, path.dirname(filePath), globber$1, ignoredWorkspaces);
181
- const subManifests = subPackages.map((p) => path.join(p, "package.json"));
175
+ const subPackages = await workspaceResolverService.getWorkspaces(file, root, globber$1, ignoredWorkspaces);
176
+ const subManifests = subPackages.map((p) => path.join(root, p, "package.json"));
182
177
  return {
183
178
  file,
184
179
  subManifests
@@ -316,5 +311,5 @@ function getDependenciesBySection(file, section) {
316
311
  }
317
312
 
318
313
  //#endregion
319
- export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer, ensureWorkspacesArray, uniq };
320
- //# sourceMappingURL=type-syncer-C_rkDNfx.js.map
314
+ export { IDependencySection, createConfigService, createPackageSource, createTypeSyncer, uniq };
315
+ //# sourceMappingURL=type-syncer-D93oGCvC.js.map
@@ -0,0 +1 @@
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typesync",
3
- "version": "0.13.5-0",
3
+ "version": "0.14.1",
4
4
  "type": "module",
5
5
  "description": "Install missing TypeScript typings for your dependencies.",
6
6
  "engines": {
@@ -22,25 +22,20 @@
22
22
  "scripts": {
23
23
  "test": "vitest run",
24
24
  "test:watch": "vitest --ui",
25
- "lint": "eslint --fix && tsc && npm run format",
25
+ "fix": "eslint --fix && npm run format",
26
+ "lint": "eslint && tsc && npm run format:check",
26
27
  "format": "prettier --write 'src/**/*.ts'",
27
- "lint:watch": "nodemon --exec npm run lint -e ts,js",
28
+ "format:check": "prettier --check 'src/**/*.ts'",
29
+ "lint:watch": "nodemon --exec npm run lint",
28
30
  "build": "tsdown",
31
+ "build:watch": "tsdown --watch",
29
32
  "run-cli": "npm run build && node bin/typesync",
30
33
  "run-cli:dry": "npm run run-cli -- --dry",
31
- "precommit": "lint-staged",
32
34
  "do:publish": "npm run lint && npm run test && npm run build && npm publish",
33
35
  "release:patch": "npm version patch && npm run do:publish && git push --follow-tags",
34
36
  "release:minor": "npm version minor && npm run do:publish && git push --follow-tags",
35
37
  "release:prerelease": "npm version prerelease && npm run do:publish && git push --follow-tags"
36
38
  },
37
- "lint-staged": {
38
- "*.ts": [
39
- "eslint --fix",
40
- "prettier --write",
41
- "git add"
42
- ]
43
- },
44
39
  "repository": {
45
40
  "type": "git",
46
41
  "url": "git+https://github.com/jeffijoe/typesync.git"
@@ -52,33 +47,33 @@
52
47
  },
53
48
  "homepage": "https://github.com/jeffijoe/typesync#readme",
54
49
  "dependencies": {
55
- "awilix": "^10.0.2",
56
- "chalk": "^5.3.0",
50
+ "awilix": "^12.0.4",
51
+ "chalk": "^5.4.1",
57
52
  "cosmiconfig": "^9.0.0",
58
53
  "detect-indent": "^7.0.1",
59
54
  "js-yaml": "^4.1.0",
60
- "npm-registry-fetch": "^17.1.0",
55
+ "npm-registry-fetch": "^18.0.2",
61
56
  "ora": "^8.1.1",
62
- "semver": "^7.6.2",
57
+ "semver": "^7.7.0",
63
58
  "tinyglobby": "^0.2.10"
64
59
  },
65
60
  "devDependencies": {
66
- "@eslint/js": "^9.16.0",
61
+ "@eslint/js": "^9.19.0",
67
62
  "@types/js-yaml": "~4.0.9 || ~4.1.0",
68
- "@types/node": "~18.19.67",
63
+ "@types/node": "^22.13.0",
69
64
  "@types/npm-registry-fetch": "^8.0.7 || ~17.1.0",
70
65
  "@types/semver": "~7.5.8 || ~7.6.0",
71
- "@vitest/coverage-v8": "^2.1.6",
72
- "@vitest/ui": "^2.1.6",
73
- "eslint": "^9.16.0",
74
- "globals": "^15.12.0",
75
- "nodemon": "^3.1.4",
76
- "oxc-transform": "^0.38.0",
77
- "prettier": "^3.3.2",
78
- "tsdown": "^0.3.1",
79
- "typescript": "^5.5.3",
80
- "typescript-eslint": "^8.16.0",
81
- "vitest": "^2.1.6"
66
+ "@vitest/coverage-v8": "^3.0.4",
67
+ "@vitest/ui": "^3.0.4",
68
+ "eslint": "^9.19.0",
69
+ "globals": "^15.14.0",
70
+ "nodemon": "^3.1.9",
71
+ "oxc-transform": "^0.48.1",
72
+ "prettier": "^3.4.2",
73
+ "tsdown": "^0.5.6",
74
+ "typescript": "^5.7.3",
75
+ "typescript-eslint": "^8.22.0",
76
+ "vitest": "^3.0.4"
82
77
  },
83
- "packageManager": "npm@8.19.4"
78
+ "packageManager": "npm@10.8.2"
84
79
  }
@@ -1,27 +0,0 @@
1
- import type { ICLIArguments } from "./types.js";
2
- /**
3
- * Like regular console.log, but better.
4
- * @param message
5
- */
6
- export declare function log(message: string): void;
7
- /**
8
- * Makes success feel even sweeter.
9
- * @param text
10
- */
11
- export declare function success(text: string): void;
12
- /**
13
- * Logs an error all pretty.
14
- * @param err
15
- */
16
- export declare function error(err: Error | string): void;
17
- /**
18
- * Spins while doing work. Stops when done.
19
- * @param text
20
- * @param fn
21
- */
22
- export declare function spinWhile<T>(text: string, fn: () => Promise<T>): Promise<T>;
23
- /**
24
- * Super simple argument parser.
25
- * @param argv
26
- */
27
- export declare function parseArguments(argv: Array<string>): ICLIArguments;
@@ -1,11 +0,0 @@
1
- import { type ICLIArguments, type ISyncOptions } from "./types.js";
2
- /**
3
- * Config Service.
4
- */
5
- export interface IConfigService {
6
- /**
7
- * Get typesync config.
8
- */
9
- readConfig(this: void, filePath: string, flags: ICLIArguments["flags"]): Promise<ISyncOptions>;
10
- }
11
- export declare function createConfigService(): IConfigService;
@@ -1 +0,0 @@
1
- export declare function readFileContents(filePath: string): Promise<string>;
package/dist/globber.d.ts DELETED
@@ -1,15 +0,0 @@
1
- /**
2
- * Globber interface.
3
- */
4
- export interface IGlobber {
5
- /**
6
- * Globs for filenames.
7
- *
8
- * @param root
9
- */
10
- glob(this: void, root: string, filenames: Array<string>, ignore?: Array<string>): Promise<Array<string>>;
11
- }
12
- /**
13
- * Creates a globber.
14
- */
15
- export declare function createGlobber(): IGlobber;
@@ -1,15 +0,0 @@
1
- import type { IPackageFile } from "./types.js";
2
- /**
3
- * File service.
4
- */
5
- export interface IPackageJSONService {
6
- /**
7
- * Reads and parses JSON from the specified file. Path is relative to the current working directory.
8
- */
9
- readPackageFile(this: void, filePath: string): Promise<IPackageFile>;
10
- /**
11
- * Writes the JSON to the specified file.
12
- */
13
- writePackageFile(this: void, filePath: string, fileContents: IPackageFile): Promise<void>;
14
- }
15
- export declare function createPackageJSONFileService(): IPackageJSONService;
@@ -1,25 +0,0 @@
1
- import type { IPackageVersionInfo } from "./versioning.js";
2
- /**
3
- * Fetches info about a package.
4
- */
5
- export interface IPackageSource {
6
- /**
7
- * Fetches package info from an external source.
8
- *
9
- * @param packageName
10
- */
11
- fetch(this: void, packageName: string): Promise<IPackageInfo | null>;
12
- }
13
- /**
14
- * Interface for the Package Info structure.
15
- */
16
- export interface IPackageInfo {
17
- name: string;
18
- latestVersion: string;
19
- deprecated: boolean;
20
- versions: Array<IPackageVersionInfo>;
21
- }
22
- /**
23
- * Creates a package source.
24
- */
25
- export declare function createPackageSource(): IPackageSource;
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-syncer-C_rkDNfx.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>","data?: IWorkspacesSection","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","import type { IWorkspacesArray, IWorkspacesSection } from './workspace-resolver'\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 cache.get(key)!\n }\n\n const p = run(...args)\n cache.set(key, p)\n return p\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","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(async (p) =>\n 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 file = await packageJSONService.readPackageFile(filePath)\n const subPackages = await workspaceResolverService.getWorkspaces(\n file,\n path.dirname(filePath),\n globber,\n ignoredWorkspaces,\n )\n const subManifests = subPackages.map((p) => path.join(p, 'package.json'))\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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"}
@@ -1,13 +0,0 @@
1
- import type { IConfigService } from "./config-service.js";
2
- import type { IGlobber } from "./globber.js";
3
- import type { IPackageJSONService } from "./package-json-file-service.js";
4
- import type { IPackageSource } from "./package-source.js";
5
- import { type ITypeSyncer } from "./types.js";
6
- import type { IWorkspaceResolverService } from "./workspace-resolver.js";
7
- /**
8
- * Creates a type syncer.
9
- *
10
- * @param packageJSONservice
11
- * @param typeDefinitionSource
12
- */
13
- export declare function createTypeSyncer(packageJSONService: IPackageJSONService, workspaceResolverService: IWorkspaceResolverService, packageSource: IPackageSource, configService: IConfigService, globber: IGlobber): ITypeSyncer;
package/dist/types.d.ts DELETED
@@ -1,103 +0,0 @@
1
- import type { IWorkspacesArray, IWorkspacesSection } from "./workspace-resolver.js";
2
- /**
3
- * The guts of the program.
4
- */
5
- export interface ITypeSyncer {
6
- sync(this: void, filePath: string, flags: ICLIArguments["flags"]): Promise<ISyncResult>;
7
- }
8
- /**
9
- * Sync options.
10
- */
11
- export interface ISyncOptions {
12
- /**
13
- * Ignore certain deps.
14
- */
15
- ignoreDeps?: Array<IDependencySection>;
16
- /**
17
- * Ignore certain packages.
18
- */
19
- ignorePackages?: Array<string>;
20
- /**
21
- * Skip resolution of certain projects in the workspace.
22
- */
23
- ignoreProjects?: IWorkspacesArray;
24
- }
25
- /**
26
- * Package.json file.
27
- */
28
- export interface IPackageFile {
29
- name?: string;
30
- dependencies?: IDependenciesSection;
31
- devDependencies?: IDependenciesSection;
32
- peerDependencies?: IDependenciesSection;
33
- optionalDependencies?: IDependenciesSection;
34
- workspaces?: IWorkspacesSection;
35
- [key: string]: unknown;
36
- }
37
- /**
38
- * Section in package.json representing dependencies.
39
- */
40
- export type IDependenciesSection = Record<string, string>;
41
- /**
42
- * Package + version record, collected from the {"package": "^1.2.3"} sections.
43
- */
44
- export interface IPackageVersion {
45
- name: string;
46
- version: string;
47
- }
48
- /**
49
- * Describes how a package may be typed.
50
- */
51
- export interface IPackageTypingDescriptor {
52
- typingsName: string;
53
- codePackageName: string;
54
- typesPackageName: string;
55
- }
56
- /**
57
- * A type definition with the corresponding code package name.
58
- */
59
- export interface ISyncedTypeDefinition extends IPackageTypingDescriptor {
60
- codePackageName: string;
61
- }
62
- /**
63
- * Sync result.
64
- */
65
- export interface ISyncResult {
66
- /**
67
- * The files that were synced.
68
- */
69
- syncedFiles: Array<ISyncedFile>;
70
- }
71
- /**
72
- * A file that was synced.
73
- */
74
- export interface ISyncedFile {
75
- /**
76
- * The cwd-relative path to the synced file.
77
- */
78
- filePath: string;
79
- /**
80
- * The package file that was synced.
81
- */
82
- package: IPackageFile;
83
- /**
84
- * The new typings that were added.
85
- */
86
- newTypings: Array<ISyncedTypeDefinition>;
87
- }
88
- /**
89
- * Dependency sections.
90
- */
91
- export declare enum IDependencySection {
92
- dev = "dev",
93
- deps = "deps",
94
- optional = "optional",
95
- peer = "peer",
96
- }
97
- /**
98
- * CLI arguments.
99
- */
100
- export interface ICLIArguments {
101
- flags: Record<string, boolean | string | undefined>;
102
- args: Array<string>;
103
- }
package/dist/util.d.ts DELETED
@@ -1,53 +0,0 @@
1
- import type { IWorkspacesArray, IWorkspacesSection } from "./workspace-resolver.js";
2
- /**
3
- * Returns unique items.
4
- *
5
- * @param source The source to filter
6
- */
7
- export declare function uniq<T>(source: Array<T>): Array<T>;
8
- /**
9
- * Remove blank attributes in a object.
10
- *
11
- * @param source
12
- */
13
- export declare function shrinkObject<T extends object>(source: T): Partial<T>;
14
- /**
15
- * Merges a sequence of objects into a single object using `reduce`.
16
- *
17
- * @param source An array of objects to merge.
18
- */
19
- export declare function mergeObjects<T>(source: Array<T>): T;
20
- /**
21
- * Returns the assumed types package name.
22
- * @param name Package name
23
- */
24
- export declare function typed(name: string): string;
25
- /**
26
- * Returns the assumed code package name based on a types package name.
27
- * @param name
28
- */
29
- export declare function untyped(name: string): string;
30
- /**
31
- * Orders an object.
32
- * @param source
33
- */
34
- export declare function orderObject<
35
- T extends Record<string | number | symbol, U>,
36
- U
37
- >(source: T, comparer?: (a: string, b: string) => number): T;
38
- /**
39
- * Async memoize.
40
- *
41
- * @param fn
42
- */
43
- export declare function memoizeAsync<
44
- U extends Array<W>,
45
- V,
46
- W
47
- >(fn: (...args: U) => Promise<V>): (...args: U) => Promise<V>;
48
- /**
49
- * Ensures that we have a valid workspaces array.
50
- *
51
- * @param data
52
- */
53
- export declare function ensureWorkspacesArray(data?: IWorkspacesSection): IWorkspacesArray;
@@ -1,14 +0,0 @@
1
- /**
2
- * Version descriptor for versions returned in remote package info.
3
- */
4
- export interface IPackageVersionInfo {
5
- version: string;
6
- containsInternalTypings: boolean;
7
- }
8
- /**
9
- * Gets the closest matching package version info.
10
- *
11
- * @param availableVersions
12
- * @param version
13
- */
14
- export declare function getClosestMatchingVersion(availableVersions: Array<IPackageVersionInfo>, version: string): IPackageVersionInfo;
@@ -1,75 +0,0 @@
1
- import type * as fsUtils from "./fs-utils.js";
2
- import type { IGlobber } from "./globber.js";
3
- import type { IPackageFile } from "./types.js";
4
- /**
5
- * Service for fetching monorepo workspaces in a standardized format agnostic of the package manager used.
6
- * It is used to allow syncing all types in a workspace when run from the root of a monorepo.
7
- */
8
- export interface IWorkspaceResolverService {
9
- /**
10
- * Reads, parses, and normalizes a workspaces configuration from the following files, in this order:
11
- * - `package.json` `workspaces` field, as an array of globs.
12
- * - `package.json` `workspaces` field, as an object with a `packages` field, which is an array of globs.
13
- * - `pnpm-workspace.yaml` `packages` field, as an array of globs.
14
- *
15
- * Path is relative to the current working directory.
16
- * Note that this returns a list of directories, not paths to the manifests themselves.
17
- */
18
- getWorkspaces(this: void, packageJson: IPackageFile, root: string, globber: IGlobber, ignored: IWorkspacesArray): Promise<IWorkspacesArray>;
19
- }
20
- /**
21
- * @example
22
- * ```json
23
- * "workspaces": [
24
- * "packages/*",
25
- * ]
26
- * ```
27
- */
28
- export type IWorkspacesArray = Array<string>;
29
- /**
30
- * @example
31
- * ```yaml
32
- * packages:
33
- * - 'packages/*'
34
- * ```
35
- */
36
- export interface IWorkspacesObject {
37
- packages?: IWorkspacesArray;
38
- }
39
- /**
40
- * @see {@link IWorkspacesArray}
41
- */
42
- export type NpmWorkspacesConfig = IWorkspacesArray;
43
- /**
44
- * Yarn is a special snowflake.
45
- *
46
- * @example
47
- * ```json
48
- * "workspaces": {
49
- * "packages": [
50
- * "packages/*",
51
- * ],
52
- * "nohoist": []
53
- * }
54
- * ```
55
- */
56
- export type YarnWorkspacesConfig = IWorkspacesArray | (IWorkspacesObject & { nohoist?: Array<string> });
57
- /**
58
- * The contents of a `pnpm-workspace.yaml` file.
59
- *
60
- * @example
61
- * ```yaml
62
- * packages:
63
- * - 'packages/*'
64
- * ```
65
- */
66
- export type PnpmWorkspacesConfig = IWorkspacesObject;
67
- /**
68
- * @see {@link IWorkspacesArray}
69
- */
70
- export type BunWorkspacesConfig = IWorkspacesArray;
71
- /**
72
- * Section in `package.json` representing workspaces.
73
- */
74
- export type IWorkspacesSection = NpmWorkspacesConfig | YarnWorkspacesConfig | BunWorkspacesConfig;
75
- export declare function createWorkspaceResolverService({ readFileContents }: { readFileContents: typeof fsUtils.readFileContents }): IWorkspaceResolverService;