deslop-js 0.5.8 → 0.6.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
- MIT License
1
+ Modified MIT License
2
2
 
3
- Copyright (c) 2025 Million Software, Inc.
3
+ Copyright (c) 2026 Million Software, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -19,3 +19,16 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ Our only modification is that the following uses require prior written
24
+ permission from the copyright holder. To request permission, contact
25
+ founders@million.dev.
26
+
27
+ 1. Using the Software, its source code, or any derivative works thereof, in
28
+ whole or in part, as training, fine-tuning, or evaluation data, or as input
29
+ to any automated pipeline for training or improving any machine learning
30
+ model or AI system.
31
+
32
+ 2. Selling the Software, or offering it to third parties as a paid, hosted, or
33
+ managed product or service (including any commercial API or SaaS offering)
34
+ whose value derives entirely or substantially from the Software.
package/dist/index.cjs CHANGED
@@ -2085,6 +2085,13 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
2085
2085
  } else wholeObjectUses.push(objectName);
2086
2086
  }
2087
2087
  }
2088
+ if (node.type === "JSXMemberExpression") {
2089
+ const jsxMember = node;
2090
+ if (jsxMember.object.type === "JSXIdentifier" && jsxMember.object.name !== void 0 && namespaceLocalNames.has(jsxMember.object.name) && jsxMember.property.name !== void 0) memberAccesses.push({
2091
+ objectName: jsxMember.object.name,
2092
+ memberName: jsxMember.property.name
2093
+ });
2094
+ }
2088
2095
  if (node.type === "SpreadElement") {
2089
2096
  const spreadArgument = node.argument;
2090
2097
  if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
@@ -3227,8 +3234,11 @@ const resolveExpoPluginPath = (configDirectory, pluginPath) => {
3227
3234
  if (isFile(indexCandidatePath)) return indexCandidatePath;
3228
3235
  }
3229
3236
  };
3230
- const addExpoPluginEntry = (entries, rootDirectory, configDirectory, pluginPath) => {
3231
- if (!isLocalExpoPluginPath(pluginPath)) return;
3237
+ const addExpoPluginEntry = (entries, packageNamePlugins, rootDirectory, configDirectory, pluginPath) => {
3238
+ if (!isLocalExpoPluginPath(pluginPath)) {
3239
+ packageNamePlugins.add(pluginPath);
3240
+ return;
3241
+ }
3232
3242
  const resolvedPath = resolveExpoPluginPath(configDirectory, pluginPath);
3233
3243
  if (!resolvedPath) return;
3234
3244
  const relativePath = (0, node_path.relative)(rootDirectory, resolvedPath);
@@ -3243,42 +3253,47 @@ const unwrapExpression = (expression) => {
3243
3253
  while (typescript.default.isParenthesizedExpression(currentExpression)) currentExpression = currentExpression.expression;
3244
3254
  return currentExpression;
3245
3255
  };
3246
- const collectExpoPluginPathsFromArray = (array, entries, rootDirectory, configDirectory) => {
3256
+ const collectExpoPluginPathsFromArray = (array, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3247
3257
  for (const element of array.elements) {
3248
3258
  if (typescript.default.isStringLiteral(element) || typescript.default.isNoSubstitutionTemplateLiteral(element)) {
3249
- addExpoPluginEntry(entries, rootDirectory, configDirectory, element.text);
3259
+ addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, element.text);
3250
3260
  continue;
3251
3261
  }
3252
3262
  if (typescript.default.isArrayLiteralExpression(element)) {
3253
3263
  const [pluginName] = element.elements;
3254
- if (pluginName && (typescript.default.isStringLiteral(pluginName) || typescript.default.isNoSubstitutionTemplateLiteral(pluginName))) addExpoPluginEntry(entries, rootDirectory, configDirectory, pluginName.text);
3264
+ if (pluginName && (typescript.default.isStringLiteral(pluginName) || typescript.default.isNoSubstitutionTemplateLiteral(pluginName))) addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, pluginName.text);
3255
3265
  }
3256
3266
  }
3257
3267
  };
3258
- const collectExpoPluginPathsFromConfigObject = (objectLiteral, entries, rootDirectory, configDirectory) => {
3259
- for (const property of objectLiteral.properties) if (typescript.default.isPropertyAssignment(property) && getPropertyName(property.name) === "plugins" && typescript.default.isArrayLiteralExpression(property.initializer)) collectExpoPluginPathsFromArray(property.initializer, entries, rootDirectory, configDirectory);
3268
+ const collectExpoPluginPathsFromConfigObject = (objectLiteral, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3269
+ for (const property of objectLiteral.properties) {
3270
+ if (!typescript.default.isPropertyAssignment(property)) continue;
3271
+ const propertyName = getPropertyName(property.name);
3272
+ if (propertyName === "plugins" && typescript.default.isArrayLiteralExpression(property.initializer)) collectExpoPluginPathsFromArray(property.initializer, entries, packageNamePlugins, rootDirectory, configDirectory);
3273
+ if (propertyName === "expo" && typescript.default.isObjectLiteralExpression(property.initializer)) collectExpoPluginPathsFromConfigObject(property.initializer, entries, packageNamePlugins, rootDirectory, configDirectory);
3274
+ }
3260
3275
  };
3261
- const collectReturnedExpoConfigPluginPaths = (body, entries, rootDirectory, configDirectory) => {
3276
+ const collectReturnedExpoConfigPluginPaths = (body, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3262
3277
  if (!typescript.default.isBlock(body)) {
3263
3278
  const expression = unwrapExpression(body);
3264
- if (typescript.default.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, rootDirectory, configDirectory);
3279
+ if (typescript.default.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, packageNamePlugins, rootDirectory, configDirectory);
3265
3280
  return;
3266
3281
  }
3267
3282
  const visit = (node) => {
3268
3283
  if (typescript.default.isFunctionDeclaration(node) || typescript.default.isFunctionExpression(node) || typescript.default.isArrowFunction(node)) return;
3269
3284
  if (typescript.default.isReturnStatement(node) && node.expression) {
3270
3285
  const expression = unwrapExpression(node.expression);
3271
- if (typescript.default.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, rootDirectory, configDirectory);
3286
+ if (typescript.default.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, packageNamePlugins, rootDirectory, configDirectory);
3272
3287
  return;
3273
3288
  }
3274
3289
  typescript.default.forEachChild(node, visit);
3275
3290
  };
3276
3291
  visit(body);
3277
3292
  };
3278
- const collectExpoPluginPathsFromConfigExpression = (expression, entries, rootDirectory, configDirectory, bindings, seenIdentifiers = /* @__PURE__ */ new Set()) => {
3293
+ const collectExpoPluginPathsFromConfigExpression = (expression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings, seenIdentifiers = /* @__PURE__ */ new Set()) => {
3279
3294
  const configExpression = unwrapExpression(expression);
3280
3295
  if (typescript.default.isObjectLiteralExpression(configExpression)) {
3281
- collectExpoPluginPathsFromConfigObject(configExpression, entries, rootDirectory, configDirectory);
3296
+ collectExpoPluginPathsFromConfigObject(configExpression, entries, packageNamePlugins, rootDirectory, configDirectory);
3282
3297
  return;
3283
3298
  }
3284
3299
  if (typescript.default.isIdentifier(configExpression)) {
@@ -3286,18 +3301,18 @@ const collectExpoPluginPathsFromConfigExpression = (expression, entries, rootDir
3286
3301
  seenIdentifiers.add(configExpression.text);
3287
3302
  const boundExpression = bindings.expressions.get(configExpression.text);
3288
3303
  if (boundExpression) {
3289
- collectExpoPluginPathsFromConfigExpression(boundExpression, entries, rootDirectory, configDirectory, bindings, seenIdentifiers);
3304
+ collectExpoPluginPathsFromConfigExpression(boundExpression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings, seenIdentifiers);
3290
3305
  return;
3291
3306
  }
3292
3307
  const boundFunction = bindings.functions.get(configExpression.text);
3293
- if (boundFunction?.body) collectReturnedExpoConfigPluginPaths(boundFunction.body, entries, rootDirectory, configDirectory);
3308
+ if (boundFunction?.body) collectReturnedExpoConfigPluginPaths(boundFunction.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3294
3309
  return;
3295
3310
  }
3296
3311
  if (typescript.default.isArrowFunction(configExpression)) {
3297
- collectReturnedExpoConfigPluginPaths(configExpression.body, entries, rootDirectory, configDirectory);
3312
+ collectReturnedExpoConfigPluginPaths(configExpression.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3298
3313
  return;
3299
3314
  }
3300
- if (typescript.default.isFunctionExpression(configExpression) && configExpression.body) collectReturnedExpoConfigPluginPaths(configExpression.body, entries, rootDirectory, configDirectory);
3315
+ if (typescript.default.isFunctionExpression(configExpression) && configExpression.body) collectReturnedExpoConfigPluginPaths(configExpression.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3301
3316
  };
3302
3317
  const hasDefaultExportModifier = (node) => Boolean(typescript.default.canHaveModifiers(node) && typescript.default.getModifiers(node)?.some((modifier) => modifier.kind === typescript.default.SyntaxKind.DefaultKeyword));
3303
3318
  const isModuleExportsAssignmentTarget = (node) => typescript.default.isPropertyAccessExpression(node) && typescript.default.isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports";
@@ -3316,22 +3331,22 @@ const collectStaticConfigBindings = (sourceFile) => {
3316
3331
  functions
3317
3332
  };
3318
3333
  };
3319
- const collectExpoPluginPathsFromAppConfig = (configPath, entries, rootDirectory) => {
3334
+ const collectExpoPluginPathsFromAppConfig = (configPath, entries, packageNamePlugins, rootDirectory) => {
3320
3335
  const extension = (0, node_path.extname)(configPath);
3321
3336
  const sourceFile = typescript.default.createSourceFile(configPath, (0, node_fs.readFileSync)(configPath, "utf8"), typescript.default.ScriptTarget.Latest, true, extension === ".ts" || extension === ".mts" || extension === ".cts" ? typescript.default.ScriptKind.TS : typescript.default.ScriptKind.JS);
3322
3337
  const configDirectory = (0, node_path.dirname)(configPath);
3323
3338
  const bindings = collectStaticConfigBindings(sourceFile);
3324
3339
  const visit = (node) => {
3325
3340
  if (typescript.default.isExportAssignment(node)) {
3326
- collectExpoPluginPathsFromConfigExpression(node.expression, entries, rootDirectory, configDirectory, bindings);
3341
+ collectExpoPluginPathsFromConfigExpression(node.expression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings);
3327
3342
  return;
3328
3343
  }
3329
3344
  if (typescript.default.isFunctionDeclaration(node) && hasDefaultExportModifier(node) && node.body) {
3330
- collectReturnedExpoConfigPluginPaths(node.body, entries, rootDirectory, configDirectory);
3345
+ collectReturnedExpoConfigPluginPaths(node.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3331
3346
  return;
3332
3347
  }
3333
3348
  if (typescript.default.isBinaryExpression(node) && node.operatorToken.kind === typescript.default.SyntaxKind.EqualsToken && isModuleExportsAssignmentTarget(node.left)) {
3334
- collectExpoPluginPathsFromConfigExpression(node.right, entries, rootDirectory, configDirectory, bindings);
3349
+ collectExpoPluginPathsFromConfigExpression(node.right, entries, packageNamePlugins, rootDirectory, configDirectory, bindings);
3335
3350
  return;
3336
3351
  }
3337
3352
  typescript.default.forEachChild(node, visit);
@@ -3350,26 +3365,30 @@ const collectPluginPathsFromJsonValue = (value) => {
3350
3365
  }
3351
3366
  return pluginPaths;
3352
3367
  };
3353
- const collectExpoPluginPathsFromAppJson = (configPath, entries, rootDirectory) => {
3368
+ const collectExpoPluginPathsFromAppJson = (configPath, entries, packageNamePlugins, rootDirectory) => {
3354
3369
  const parsedJson = JSON.parse((0, node_fs.readFileSync)(configPath, "utf8"));
3355
3370
  const configDirectory = (0, node_path.dirname)(configPath);
3356
3371
  if (!isRecord(parsedJson)) return;
3357
3372
  const expoConfig = parsedJson.expo;
3358
3373
  const expoPluginPaths = isRecord(expoConfig) ? collectPluginPathsFromJsonValue(expoConfig.plugins) : [];
3359
- for (const pluginPath of [...expoPluginPaths, ...collectPluginPathsFromJsonValue(parsedJson.plugins)]) addExpoPluginEntry(entries, rootDirectory, configDirectory, pluginPath);
3374
+ for (const pluginPath of [...expoPluginPaths, ...collectPluginPathsFromJsonValue(parsedJson.plugins)]) addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, pluginPath);
3360
3375
  };
3361
- const collectExpoPluginPathsFromConfig = (configPath, entries, rootDirectory) => {
3376
+ const collectExpoPluginPathsFromConfig = (configPath, entries, packageNamePlugins, rootDirectory) => {
3362
3377
  try {
3363
3378
  if ((0, node_path.basename)(configPath) === "app.json") {
3364
- collectExpoPluginPathsFromAppJson(configPath, entries, rootDirectory);
3379
+ collectExpoPluginPathsFromAppJson(configPath, entries, packageNamePlugins, rootDirectory);
3365
3380
  return;
3366
3381
  }
3367
- collectExpoPluginPathsFromAppConfig(configPath, entries, rootDirectory);
3382
+ collectExpoPluginPathsFromAppConfig(configPath, entries, packageNamePlugins, rootDirectory);
3368
3383
  } catch {}
3369
3384
  };
3370
3385
  const extractExpoConfigPluginEntries = (directory, dependencies, rootDirectory = directory, includeNestedConfigs = true) => {
3371
- if (!isExpoOrReactNativeWorkspace(dependencies)) return [];
3386
+ if (!isExpoOrReactNativeWorkspace(dependencies)) return {
3387
+ filePaths: [],
3388
+ packageNames: []
3389
+ };
3372
3390
  const entries = /* @__PURE__ */ new Set();
3391
+ const packageNamePlugins = /* @__PURE__ */ new Set();
3373
3392
  const configPaths = fast_glob.default.sync(includeNestedConfigs ? NESTED_EXPO_CONFIG_FILE_GLOBS : EXPO_CONFIG_FILE_GLOBS, {
3374
3393
  cwd: directory,
3375
3394
  absolute: true,
@@ -3381,8 +3400,11 @@ const extractExpoConfigPluginEntries = (directory, dependencies, rootDirectory =
3381
3400
  ],
3382
3401
  deep: 6
3383
3402
  });
3384
- for (const configPath of configPaths) collectExpoPluginPathsFromConfig(configPath, entries, rootDirectory);
3385
- return [...entries];
3403
+ for (const configPath of configPaths) collectExpoPluginPathsFromConfig(configPath, entries, packageNamePlugins, rootDirectory);
3404
+ return {
3405
+ filePaths: [...entries],
3406
+ packageNames: [...packageNamePlugins]
3407
+ };
3386
3408
  };
3387
3409
 
3388
3410
  //#endregion
@@ -4883,10 +4905,11 @@ const resolveEntries = async (config) => {
4883
4905
  for (const workspacePackage of entryEligiblePackages) tsConfigIncludeEntries.push(...extractTsConfigIncludeFilesEntries(workspacePackage.directory));
4884
4906
  const configStringEntries = extractConfigStringReferencedEntries(absoluteRoot);
4885
4907
  for (const workspacePackage of entryEligiblePackages) configStringEntries.push(...extractConfigStringReferencedEntries(workspacePackage.directory));
4886
- const expoConfigPluginEntries = extractExpoConfigPluginEntries(absoluteRoot, readPackageJsonDependencies((0, node_path.join)(absoluteRoot, "package.json")), absoluteRoot, false);
4908
+ const expoConfigPluginEntries = [...extractExpoConfigPluginEntries(absoluteRoot, readPackageJsonDependencies((0, node_path.join)(absoluteRoot, "package.json")), absoluteRoot, false).filePaths];
4887
4909
  for (const workspacePackage of entryEligiblePackages) {
4888
4910
  const workspacePackageDependencies = readPackageJsonDependencies((0, node_path.join)(workspacePackage.directory, "package.json"));
4889
- expoConfigPluginEntries.push(...extractExpoConfigPluginEntries(workspacePackage.directory, workspacePackageDependencies, absoluteRoot));
4911
+ const workspaceExpoCollection = extractExpoConfigPluginEntries(workspacePackage.directory, workspacePackageDependencies, absoluteRoot);
4912
+ expoConfigPluginEntries.push(...workspaceExpoCollection.filePaths);
4890
4913
  }
4891
4914
  const sectionsModuleEntries = extractSectionsModuleEntries(absoluteRoot);
4892
4915
  const siblingWorkspaceImportEntries = extractSiblingWorkspaceImportEntries(absoluteRoot);
@@ -8098,7 +8121,8 @@ const detectStalePackages = (graph, config) => {
8098
8121
  const monorepoPackageJson = (0, node_path.join)(monorepoRoot, "package.json");
8099
8122
  if (!allPackageJsonPaths.includes(monorepoPackageJson) && (0, node_fs.existsSync)(monorepoPackageJson)) allPackageJsonPaths.push(monorepoPackageJson);
8100
8123
  }
8101
- const binToPackage = buildBinToPackageMap(nodeModulesSearchRoots, declaredNames);
8124
+ const { binToPackage, packagesProvidingBinary } = buildBinaryPackageIndex(nodeModulesSearchRoots, declaredNames);
8125
+ for (const packageName of packagesProvidingBinary) usedPackageNames.add(packageName);
8102
8126
  for (const workspacePackageJsonPath of allPackageJsonPaths) {
8103
8127
  const scriptReferenced = collectScriptReferencedPackages(workspacePackageJsonPath, declaredNames, binToPackage);
8104
8128
  for (const packageName of scriptReferenced) usedPackageNames.add(packageName);
@@ -8113,6 +8137,11 @@ const detectStalePackages = (graph, config) => {
8113
8137
  for (const packageName of configReferenced) usedPackageNames.add(packageName);
8114
8138
  const tsconfigReferenced = collectTsconfigReferencedPackages(configSearchRoot);
8115
8139
  for (const packageName of tsconfigReferenced) usedPackageNames.add(packageName);
8140
+ const { packageNames: expoPluginPackageNames } = extractExpoConfigPluginEntries(configSearchRoot, {
8141
+ ...dependencies,
8142
+ ...devDependencies
8143
+ });
8144
+ for (const packageName of expoPluginPackageNames) if (declaredNames.has(packageName)) usedPackageNames.add(packageName);
8116
8145
  }
8117
8146
  if (hasJsxFiles(graph)) {
8118
8147
  if (declaredNames.has("react")) usedPackageNames.add("react");
@@ -8146,10 +8175,6 @@ const detectStalePackages = (graph, config) => {
8146
8175
  }
8147
8176
  const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesSearchRoots, declaredNames, usedPackageNames);
8148
8177
  for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
8149
- const staticPeerSatisfied = collectStaticPeerSatisfiedPackages(declaredNames, usedPackageNames);
8150
- for (const packageName of staticPeerSatisfied) usedPackageNames.add(packageName);
8151
- const implicitCompanionPackages = collectImplicitCompanionPackages(declaredNames, usedPackageNames);
8152
- for (const packageName of implicitCompanionPackages) usedPackageNames.add(packageName);
8153
8178
  const overrideMappings = collectOverrideMappings(configSearchRoots, allPackageJsonPaths, monorepoRoot);
8154
8179
  for (const { fromPackage, toPackage } of overrideMappings) {
8155
8180
  if (declaredNames.has(toPackage)) usedPackageNames.add(toPackage);
@@ -8216,126 +8241,34 @@ const findInstalledPackageJsonPath = (packageName, nodeModulesSearchRoots) => {
8216
8241
  if ((0, node_fs.existsSync)(candidatePath)) return candidatePath;
8217
8242
  }
8218
8243
  };
8219
- const STATIC_PEER_DEPENDENCY_MAP = {
8220
- "@apollo/client": ["graphql"],
8221
- "@docusaurus/core": ["@mdx-js/react"],
8222
- "@fortawesome/react-fontawesome": ["@fortawesome/fontawesome-svg-core"],
8223
- "@gorhom/bottom-sheet": ["react-native-gesture-handler", "react-native-reanimated"],
8224
- "@hookform/resolvers": ["zod"],
8225
- "@mdx-js/loader": ["@mdx-js/react"],
8226
- "@mui/material": ["react-transition-group", "styled-components"],
8227
- "@stripe/react-stripe-js": ["@stripe/stripe-js"],
8228
- "@tiptap/core": ["@tiptap/pm"],
8229
- "@tiptap/react": ["@tiptap/pm"],
8230
- "@trpc/server": ["zod"],
8231
- "chart.js": [],
8232
- "fumadocs-core": ["@mdx-js/react"],
8233
- "fumadocs-mdx": ["@mdx-js/react"],
8234
- "fumadocs-ui": ["@mdx-js/react"],
8235
- "graphql-request": ["graphql"],
8236
- nextra: ["@mdx-js/react"],
8237
- "nextra-theme-blog": ["@mdx-js/react"],
8238
- "nextra-theme-docs": ["@mdx-js/react"],
8239
- "react-app-polyfill": ["core-js"],
8240
- "react-bootstrap": ["react-transition-group"],
8241
- "react-chartjs-2": ["chart.js"],
8242
- "react-redux": ["redux"],
8243
- "react-router-dom": ["react-router"],
8244
- "redux-thunk": ["redux"],
8245
- sanity: ["styled-components"],
8246
- sequelize: ["pg"],
8247
- "stylis-plugin-rtl": ["stylis"],
8248
- urql: ["graphql"],
8249
- "use-immer": ["immer"],
8250
- zustand: ["immer"]
8251
- };
8252
- const collectStaticPeerSatisfiedPackages = (declaredNames, confirmedUsedNames) => {
8253
- const peerSatisfied = /* @__PURE__ */ new Set();
8254
- for (const [packageName, peerNames] of Object.entries(STATIC_PEER_DEPENDENCY_MAP)) {
8255
- if (!confirmedUsedNames.has(packageName)) continue;
8256
- for (const peerName of peerNames) if (declaredNames.has(peerName)) peerSatisfied.add(peerName);
8257
- }
8258
- return peerSatisfied;
8259
- };
8260
- const IMPLICIT_COMPANION_DEPENDENCY_MAP = {
8261
- jest: ["jest-config"],
8262
- "jest-cli": ["jest-config"],
8263
- "vite-plus": ["@voidzero-dev/vite-plus-core"]
8264
- };
8265
- const collectImplicitCompanionPackages = (declaredNames, confirmedUsedNames) => {
8266
- const companions = /* @__PURE__ */ new Set();
8267
- for (const [packageName, companionNames] of Object.entries(IMPLICIT_COMPANION_DEPENDENCY_MAP)) {
8268
- if (!confirmedUsedNames.has(packageName)) continue;
8269
- for (const companionName of companionNames) if (declaredNames.has(companionName)) companions.add(companionName);
8270
- }
8271
- return companions;
8272
- };
8273
8244
  const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
8274
- const CLI_BINARY_TO_PACKAGE = {
8275
- "babel-node": "@babel/node",
8276
- "trigger.dev": "trigger.dev",
8277
- "@formatjs/cli": "@formatjs/cli",
8278
- "react-scripts": "react-scripts",
8279
- "webpack-cli": "webpack-cli",
8280
- "webpack-dev-server": "webpack-dev-server",
8281
- babel: "@babel/cli",
8282
- chokidar: "chokidar-cli",
8283
- "replace-in-file": "replace-in-file",
8284
- tauri: "@tauri-apps/cli",
8285
- tinacms: "@tinacms/cli",
8286
- "tsc-alias": "tsc-alias",
8287
- formatjs: "@formatjs/cli",
8288
- prompt: "prompt",
8289
- vitest: "vitest",
8290
- jest: "jest",
8291
- prisma: "prisma",
8292
- sequelize: "sequelize-cli",
8293
- rimraf: "rimraf",
8294
- concurrently: "concurrently",
8295
- parcel: "parcel",
8296
- rescript: "rescript",
8297
- webstudio: "webstudio",
8298
- cap: "@capacitor/cli",
8299
- "source-map-explorer": "source-map-explorer",
8300
- "ts-standard": "ts-standard",
8301
- "rndebugger-open": "react-native-debugger-open",
8302
- "simple-git-hooks": "simple-git-hooks",
8303
- "generate-arg-types": "@webstudio-is/generate-arg-types",
8304
- email: "@react-email/preview-server",
8305
- vp: "vite-plus",
8306
- turbo: "turbo",
8307
- changeset: "@changesets/cli",
8308
- tsx: "tsx"
8309
- };
8310
- const CLI_BINARY_FALLBACK_PACKAGES = {
8311
- babel: ["babel-cli"],
8312
- jest: ["jest-cli"],
8313
- remark: ["remark-cli"],
8314
- dumi: ["dumi"]
8315
- };
8316
- const ENV_WRAPPER_BINARY_SET = new Set([
8317
- "cross-env",
8318
- "dotenv",
8319
- "dotenv-flow",
8320
- "env-cmd"
8321
- ]);
8322
8245
  const INLINE_ENV_VAR_PATTERN = /^[A-Z_][A-Z0-9_]*=/;
8323
- const buildBinToPackageMap = (nodeModulesSearchRoots, declaredNames) => {
8246
+ const buildBinaryPackageIndex = (nodeModulesSearchRoots, declaredNames) => {
8324
8247
  const binToPackage = /* @__PURE__ */ new Map();
8325
- for (const [binary, packageName] of Object.entries(CLI_BINARY_TO_PACKAGE)) binToPackage.set(binary, packageName);
8248
+ const packagesProvidingBinary = /* @__PURE__ */ new Set();
8326
8249
  for (const packageName of declaredNames) {
8327
8250
  const packageBinJsonPath = findInstalledPackageJsonPath(packageName, nodeModulesSearchRoots);
8328
8251
  if (!packageBinJsonPath) continue;
8329
8252
  try {
8330
8253
  const binContent = (0, node_fs.readFileSync)(packageBinJsonPath, "utf-8");
8331
- const binPackageJson = JSON.parse(binContent);
8332
- if (typeof binPackageJson.bin === "string") binToPackage.set(packageName.split("/").pop(), packageName);
8333
- else if (typeof binPackageJson.bin === "object" && binPackageJson.bin !== null) for (const binaryName of Object.keys(binPackageJson.bin)) binToPackage.set(binaryName, packageName);
8254
+ const binField = JSON.parse(binContent).bin;
8255
+ if (typeof binField === "string" && binField.length > 0) {
8256
+ binToPackage.set(packageName.split("/").pop(), packageName);
8257
+ packagesProvidingBinary.add(packageName);
8258
+ } else if (typeof binField === "object" && binField !== null) {
8259
+ const binaryNames = Object.keys(binField);
8260
+ if (binaryNames.length === 0) continue;
8261
+ for (const binaryName of binaryNames) binToPackage.set(binaryName, packageName);
8262
+ packagesProvidingBinary.add(packageName);
8263
+ }
8334
8264
  } catch {
8335
8265
  continue;
8336
8266
  }
8337
8267
  }
8338
- return binToPackage;
8268
+ return {
8269
+ binToPackage,
8270
+ packagesProvidingBinary
8271
+ };
8339
8272
  };
8340
8273
  const collectScriptReferencedPackages = (packageJsonPath, declaredNames, binToPackage) => {
8341
8274
  const referenced = /* @__PURE__ */ new Set();
@@ -8364,14 +8297,6 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
8364
8297
  const tokens = segment.trim().split(/\s+/);
8365
8298
  if (tokens.length === 0) continue;
8366
8299
  let binaryIndex = 0;
8367
- const firstToken = tokens[0].replace(/^.*\//, "");
8368
- if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
8369
- const envPackage = binToPackage.get(firstToken);
8370
- if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
8371
- binaryIndex = 1;
8372
- while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
8373
- if (binaryIndex >= tokens.length) continue;
8374
- }
8375
8300
  while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
8376
8301
  if (binaryIndex >= tokens.length) continue;
8377
8302
  const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
@@ -8380,7 +8305,6 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
8380
8305
  if (!candidateBinary) continue;
8381
8306
  const mappedPackage = binToPackage.get(candidateBinary);
8382
8307
  if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
8383
- for (const fallbackPackage of CLI_BINARY_FALLBACK_PACKAGES[candidateBinary] ?? []) if (declaredNames.has(fallbackPackage)) referenced.add(fallbackPackage);
8384
8308
  if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
8385
8309
  }
8386
8310
  }
package/dist/index.mjs CHANGED
@@ -2053,6 +2053,13 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
2053
2053
  } else wholeObjectUses.push(objectName);
2054
2054
  }
2055
2055
  }
2056
+ if (node.type === "JSXMemberExpression") {
2057
+ const jsxMember = node;
2058
+ if (jsxMember.object.type === "JSXIdentifier" && jsxMember.object.name !== void 0 && namespaceLocalNames.has(jsxMember.object.name) && jsxMember.property.name !== void 0) memberAccesses.push({
2059
+ objectName: jsxMember.object.name,
2060
+ memberName: jsxMember.property.name
2061
+ });
2062
+ }
2056
2063
  if (node.type === "SpreadElement") {
2057
2064
  const spreadArgument = node.argument;
2058
2065
  if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
@@ -3195,8 +3202,11 @@ const resolveExpoPluginPath = (configDirectory, pluginPath) => {
3195
3202
  if (isFile(indexCandidatePath)) return indexCandidatePath;
3196
3203
  }
3197
3204
  };
3198
- const addExpoPluginEntry = (entries, rootDirectory, configDirectory, pluginPath) => {
3199
- if (!isLocalExpoPluginPath(pluginPath)) return;
3205
+ const addExpoPluginEntry = (entries, packageNamePlugins, rootDirectory, configDirectory, pluginPath) => {
3206
+ if (!isLocalExpoPluginPath(pluginPath)) {
3207
+ packageNamePlugins.add(pluginPath);
3208
+ return;
3209
+ }
3200
3210
  const resolvedPath = resolveExpoPluginPath(configDirectory, pluginPath);
3201
3211
  if (!resolvedPath) return;
3202
3212
  const relativePath = relative(rootDirectory, resolvedPath);
@@ -3211,42 +3221,47 @@ const unwrapExpression = (expression) => {
3211
3221
  while (ts.isParenthesizedExpression(currentExpression)) currentExpression = currentExpression.expression;
3212
3222
  return currentExpression;
3213
3223
  };
3214
- const collectExpoPluginPathsFromArray = (array, entries, rootDirectory, configDirectory) => {
3224
+ const collectExpoPluginPathsFromArray = (array, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3215
3225
  for (const element of array.elements) {
3216
3226
  if (ts.isStringLiteral(element) || ts.isNoSubstitutionTemplateLiteral(element)) {
3217
- addExpoPluginEntry(entries, rootDirectory, configDirectory, element.text);
3227
+ addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, element.text);
3218
3228
  continue;
3219
3229
  }
3220
3230
  if (ts.isArrayLiteralExpression(element)) {
3221
3231
  const [pluginName] = element.elements;
3222
- if (pluginName && (ts.isStringLiteral(pluginName) || ts.isNoSubstitutionTemplateLiteral(pluginName))) addExpoPluginEntry(entries, rootDirectory, configDirectory, pluginName.text);
3232
+ if (pluginName && (ts.isStringLiteral(pluginName) || ts.isNoSubstitutionTemplateLiteral(pluginName))) addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, pluginName.text);
3223
3233
  }
3224
3234
  }
3225
3235
  };
3226
- const collectExpoPluginPathsFromConfigObject = (objectLiteral, entries, rootDirectory, configDirectory) => {
3227
- for (const property of objectLiteral.properties) if (ts.isPropertyAssignment(property) && getPropertyName(property.name) === "plugins" && ts.isArrayLiteralExpression(property.initializer)) collectExpoPluginPathsFromArray(property.initializer, entries, rootDirectory, configDirectory);
3236
+ const collectExpoPluginPathsFromConfigObject = (objectLiteral, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3237
+ for (const property of objectLiteral.properties) {
3238
+ if (!ts.isPropertyAssignment(property)) continue;
3239
+ const propertyName = getPropertyName(property.name);
3240
+ if (propertyName === "plugins" && ts.isArrayLiteralExpression(property.initializer)) collectExpoPluginPathsFromArray(property.initializer, entries, packageNamePlugins, rootDirectory, configDirectory);
3241
+ if (propertyName === "expo" && ts.isObjectLiteralExpression(property.initializer)) collectExpoPluginPathsFromConfigObject(property.initializer, entries, packageNamePlugins, rootDirectory, configDirectory);
3242
+ }
3228
3243
  };
3229
- const collectReturnedExpoConfigPluginPaths = (body, entries, rootDirectory, configDirectory) => {
3244
+ const collectReturnedExpoConfigPluginPaths = (body, entries, packageNamePlugins, rootDirectory, configDirectory) => {
3230
3245
  if (!ts.isBlock(body)) {
3231
3246
  const expression = unwrapExpression(body);
3232
- if (ts.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, rootDirectory, configDirectory);
3247
+ if (ts.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, packageNamePlugins, rootDirectory, configDirectory);
3233
3248
  return;
3234
3249
  }
3235
3250
  const visit = (node) => {
3236
3251
  if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) return;
3237
3252
  if (ts.isReturnStatement(node) && node.expression) {
3238
3253
  const expression = unwrapExpression(node.expression);
3239
- if (ts.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, rootDirectory, configDirectory);
3254
+ if (ts.isObjectLiteralExpression(expression)) collectExpoPluginPathsFromConfigObject(expression, entries, packageNamePlugins, rootDirectory, configDirectory);
3240
3255
  return;
3241
3256
  }
3242
3257
  ts.forEachChild(node, visit);
3243
3258
  };
3244
3259
  visit(body);
3245
3260
  };
3246
- const collectExpoPluginPathsFromConfigExpression = (expression, entries, rootDirectory, configDirectory, bindings, seenIdentifiers = /* @__PURE__ */ new Set()) => {
3261
+ const collectExpoPluginPathsFromConfigExpression = (expression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings, seenIdentifiers = /* @__PURE__ */ new Set()) => {
3247
3262
  const configExpression = unwrapExpression(expression);
3248
3263
  if (ts.isObjectLiteralExpression(configExpression)) {
3249
- collectExpoPluginPathsFromConfigObject(configExpression, entries, rootDirectory, configDirectory);
3264
+ collectExpoPluginPathsFromConfigObject(configExpression, entries, packageNamePlugins, rootDirectory, configDirectory);
3250
3265
  return;
3251
3266
  }
3252
3267
  if (ts.isIdentifier(configExpression)) {
@@ -3254,18 +3269,18 @@ const collectExpoPluginPathsFromConfigExpression = (expression, entries, rootDir
3254
3269
  seenIdentifiers.add(configExpression.text);
3255
3270
  const boundExpression = bindings.expressions.get(configExpression.text);
3256
3271
  if (boundExpression) {
3257
- collectExpoPluginPathsFromConfigExpression(boundExpression, entries, rootDirectory, configDirectory, bindings, seenIdentifiers);
3272
+ collectExpoPluginPathsFromConfigExpression(boundExpression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings, seenIdentifiers);
3258
3273
  return;
3259
3274
  }
3260
3275
  const boundFunction = bindings.functions.get(configExpression.text);
3261
- if (boundFunction?.body) collectReturnedExpoConfigPluginPaths(boundFunction.body, entries, rootDirectory, configDirectory);
3276
+ if (boundFunction?.body) collectReturnedExpoConfigPluginPaths(boundFunction.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3262
3277
  return;
3263
3278
  }
3264
3279
  if (ts.isArrowFunction(configExpression)) {
3265
- collectReturnedExpoConfigPluginPaths(configExpression.body, entries, rootDirectory, configDirectory);
3280
+ collectReturnedExpoConfigPluginPaths(configExpression.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3266
3281
  return;
3267
3282
  }
3268
- if (ts.isFunctionExpression(configExpression) && configExpression.body) collectReturnedExpoConfigPluginPaths(configExpression.body, entries, rootDirectory, configDirectory);
3283
+ if (ts.isFunctionExpression(configExpression) && configExpression.body) collectReturnedExpoConfigPluginPaths(configExpression.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3269
3284
  };
3270
3285
  const hasDefaultExportModifier = (node) => Boolean(ts.canHaveModifiers(node) && ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword));
3271
3286
  const isModuleExportsAssignmentTarget = (node) => ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports";
@@ -3284,22 +3299,22 @@ const collectStaticConfigBindings = (sourceFile) => {
3284
3299
  functions
3285
3300
  };
3286
3301
  };
3287
- const collectExpoPluginPathsFromAppConfig = (configPath, entries, rootDirectory) => {
3302
+ const collectExpoPluginPathsFromAppConfig = (configPath, entries, packageNamePlugins, rootDirectory) => {
3288
3303
  const extension = extname(configPath);
3289
3304
  const sourceFile = ts.createSourceFile(configPath, readFileSync(configPath, "utf8"), ts.ScriptTarget.Latest, true, extension === ".ts" || extension === ".mts" || extension === ".cts" ? ts.ScriptKind.TS : ts.ScriptKind.JS);
3290
3305
  const configDirectory = dirname(configPath);
3291
3306
  const bindings = collectStaticConfigBindings(sourceFile);
3292
3307
  const visit = (node) => {
3293
3308
  if (ts.isExportAssignment(node)) {
3294
- collectExpoPluginPathsFromConfigExpression(node.expression, entries, rootDirectory, configDirectory, bindings);
3309
+ collectExpoPluginPathsFromConfigExpression(node.expression, entries, packageNamePlugins, rootDirectory, configDirectory, bindings);
3295
3310
  return;
3296
3311
  }
3297
3312
  if (ts.isFunctionDeclaration(node) && hasDefaultExportModifier(node) && node.body) {
3298
- collectReturnedExpoConfigPluginPaths(node.body, entries, rootDirectory, configDirectory);
3313
+ collectReturnedExpoConfigPluginPaths(node.body, entries, packageNamePlugins, rootDirectory, configDirectory);
3299
3314
  return;
3300
3315
  }
3301
3316
  if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExportsAssignmentTarget(node.left)) {
3302
- collectExpoPluginPathsFromConfigExpression(node.right, entries, rootDirectory, configDirectory, bindings);
3317
+ collectExpoPluginPathsFromConfigExpression(node.right, entries, packageNamePlugins, rootDirectory, configDirectory, bindings);
3303
3318
  return;
3304
3319
  }
3305
3320
  ts.forEachChild(node, visit);
@@ -3318,26 +3333,30 @@ const collectPluginPathsFromJsonValue = (value) => {
3318
3333
  }
3319
3334
  return pluginPaths;
3320
3335
  };
3321
- const collectExpoPluginPathsFromAppJson = (configPath, entries, rootDirectory) => {
3336
+ const collectExpoPluginPathsFromAppJson = (configPath, entries, packageNamePlugins, rootDirectory) => {
3322
3337
  const parsedJson = JSON.parse(readFileSync(configPath, "utf8"));
3323
3338
  const configDirectory = dirname(configPath);
3324
3339
  if (!isRecord(parsedJson)) return;
3325
3340
  const expoConfig = parsedJson.expo;
3326
3341
  const expoPluginPaths = isRecord(expoConfig) ? collectPluginPathsFromJsonValue(expoConfig.plugins) : [];
3327
- for (const pluginPath of [...expoPluginPaths, ...collectPluginPathsFromJsonValue(parsedJson.plugins)]) addExpoPluginEntry(entries, rootDirectory, configDirectory, pluginPath);
3342
+ for (const pluginPath of [...expoPluginPaths, ...collectPluginPathsFromJsonValue(parsedJson.plugins)]) addExpoPluginEntry(entries, packageNamePlugins, rootDirectory, configDirectory, pluginPath);
3328
3343
  };
3329
- const collectExpoPluginPathsFromConfig = (configPath, entries, rootDirectory) => {
3344
+ const collectExpoPluginPathsFromConfig = (configPath, entries, packageNamePlugins, rootDirectory) => {
3330
3345
  try {
3331
3346
  if (basename(configPath) === "app.json") {
3332
- collectExpoPluginPathsFromAppJson(configPath, entries, rootDirectory);
3347
+ collectExpoPluginPathsFromAppJson(configPath, entries, packageNamePlugins, rootDirectory);
3333
3348
  return;
3334
3349
  }
3335
- collectExpoPluginPathsFromAppConfig(configPath, entries, rootDirectory);
3350
+ collectExpoPluginPathsFromAppConfig(configPath, entries, packageNamePlugins, rootDirectory);
3336
3351
  } catch {}
3337
3352
  };
3338
3353
  const extractExpoConfigPluginEntries = (directory, dependencies, rootDirectory = directory, includeNestedConfigs = true) => {
3339
- if (!isExpoOrReactNativeWorkspace(dependencies)) return [];
3354
+ if (!isExpoOrReactNativeWorkspace(dependencies)) return {
3355
+ filePaths: [],
3356
+ packageNames: []
3357
+ };
3340
3358
  const entries = /* @__PURE__ */ new Set();
3359
+ const packageNamePlugins = /* @__PURE__ */ new Set();
3341
3360
  const configPaths = fg.sync(includeNestedConfigs ? NESTED_EXPO_CONFIG_FILE_GLOBS : EXPO_CONFIG_FILE_GLOBS, {
3342
3361
  cwd: directory,
3343
3362
  absolute: true,
@@ -3349,8 +3368,11 @@ const extractExpoConfigPluginEntries = (directory, dependencies, rootDirectory =
3349
3368
  ],
3350
3369
  deep: 6
3351
3370
  });
3352
- for (const configPath of configPaths) collectExpoPluginPathsFromConfig(configPath, entries, rootDirectory);
3353
- return [...entries];
3371
+ for (const configPath of configPaths) collectExpoPluginPathsFromConfig(configPath, entries, packageNamePlugins, rootDirectory);
3372
+ return {
3373
+ filePaths: [...entries],
3374
+ packageNames: [...packageNamePlugins]
3375
+ };
3354
3376
  };
3355
3377
 
3356
3378
  //#endregion
@@ -4851,10 +4873,11 @@ const resolveEntries = async (config) => {
4851
4873
  for (const workspacePackage of entryEligiblePackages) tsConfigIncludeEntries.push(...extractTsConfigIncludeFilesEntries(workspacePackage.directory));
4852
4874
  const configStringEntries = extractConfigStringReferencedEntries(absoluteRoot);
4853
4875
  for (const workspacePackage of entryEligiblePackages) configStringEntries.push(...extractConfigStringReferencedEntries(workspacePackage.directory));
4854
- const expoConfigPluginEntries = extractExpoConfigPluginEntries(absoluteRoot, readPackageJsonDependencies(join(absoluteRoot, "package.json")), absoluteRoot, false);
4876
+ const expoConfigPluginEntries = [...extractExpoConfigPluginEntries(absoluteRoot, readPackageJsonDependencies(join(absoluteRoot, "package.json")), absoluteRoot, false).filePaths];
4855
4877
  for (const workspacePackage of entryEligiblePackages) {
4856
4878
  const workspacePackageDependencies = readPackageJsonDependencies(join(workspacePackage.directory, "package.json"));
4857
- expoConfigPluginEntries.push(...extractExpoConfigPluginEntries(workspacePackage.directory, workspacePackageDependencies, absoluteRoot));
4879
+ const workspaceExpoCollection = extractExpoConfigPluginEntries(workspacePackage.directory, workspacePackageDependencies, absoluteRoot);
4880
+ expoConfigPluginEntries.push(...workspaceExpoCollection.filePaths);
4858
4881
  }
4859
4882
  const sectionsModuleEntries = extractSectionsModuleEntries(absoluteRoot);
4860
4883
  const siblingWorkspaceImportEntries = extractSiblingWorkspaceImportEntries(absoluteRoot);
@@ -8066,7 +8089,8 @@ const detectStalePackages = (graph, config) => {
8066
8089
  const monorepoPackageJson = join(monorepoRoot, "package.json");
8067
8090
  if (!allPackageJsonPaths.includes(monorepoPackageJson) && existsSync(monorepoPackageJson)) allPackageJsonPaths.push(monorepoPackageJson);
8068
8091
  }
8069
- const binToPackage = buildBinToPackageMap(nodeModulesSearchRoots, declaredNames);
8092
+ const { binToPackage, packagesProvidingBinary } = buildBinaryPackageIndex(nodeModulesSearchRoots, declaredNames);
8093
+ for (const packageName of packagesProvidingBinary) usedPackageNames.add(packageName);
8070
8094
  for (const workspacePackageJsonPath of allPackageJsonPaths) {
8071
8095
  const scriptReferenced = collectScriptReferencedPackages(workspacePackageJsonPath, declaredNames, binToPackage);
8072
8096
  for (const packageName of scriptReferenced) usedPackageNames.add(packageName);
@@ -8081,6 +8105,11 @@ const detectStalePackages = (graph, config) => {
8081
8105
  for (const packageName of configReferenced) usedPackageNames.add(packageName);
8082
8106
  const tsconfigReferenced = collectTsconfigReferencedPackages(configSearchRoot);
8083
8107
  for (const packageName of tsconfigReferenced) usedPackageNames.add(packageName);
8108
+ const { packageNames: expoPluginPackageNames } = extractExpoConfigPluginEntries(configSearchRoot, {
8109
+ ...dependencies,
8110
+ ...devDependencies
8111
+ });
8112
+ for (const packageName of expoPluginPackageNames) if (declaredNames.has(packageName)) usedPackageNames.add(packageName);
8084
8113
  }
8085
8114
  if (hasJsxFiles(graph)) {
8086
8115
  if (declaredNames.has("react")) usedPackageNames.add("react");
@@ -8114,10 +8143,6 @@ const detectStalePackages = (graph, config) => {
8114
8143
  }
8115
8144
  const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesSearchRoots, declaredNames, usedPackageNames);
8116
8145
  for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
8117
- const staticPeerSatisfied = collectStaticPeerSatisfiedPackages(declaredNames, usedPackageNames);
8118
- for (const packageName of staticPeerSatisfied) usedPackageNames.add(packageName);
8119
- const implicitCompanionPackages = collectImplicitCompanionPackages(declaredNames, usedPackageNames);
8120
- for (const packageName of implicitCompanionPackages) usedPackageNames.add(packageName);
8121
8146
  const overrideMappings = collectOverrideMappings(configSearchRoots, allPackageJsonPaths, monorepoRoot);
8122
8147
  for (const { fromPackage, toPackage } of overrideMappings) {
8123
8148
  if (declaredNames.has(toPackage)) usedPackageNames.add(toPackage);
@@ -8184,126 +8209,34 @@ const findInstalledPackageJsonPath = (packageName, nodeModulesSearchRoots) => {
8184
8209
  if (existsSync(candidatePath)) return candidatePath;
8185
8210
  }
8186
8211
  };
8187
- const STATIC_PEER_DEPENDENCY_MAP = {
8188
- "@apollo/client": ["graphql"],
8189
- "@docusaurus/core": ["@mdx-js/react"],
8190
- "@fortawesome/react-fontawesome": ["@fortawesome/fontawesome-svg-core"],
8191
- "@gorhom/bottom-sheet": ["react-native-gesture-handler", "react-native-reanimated"],
8192
- "@hookform/resolvers": ["zod"],
8193
- "@mdx-js/loader": ["@mdx-js/react"],
8194
- "@mui/material": ["react-transition-group", "styled-components"],
8195
- "@stripe/react-stripe-js": ["@stripe/stripe-js"],
8196
- "@tiptap/core": ["@tiptap/pm"],
8197
- "@tiptap/react": ["@tiptap/pm"],
8198
- "@trpc/server": ["zod"],
8199
- "chart.js": [],
8200
- "fumadocs-core": ["@mdx-js/react"],
8201
- "fumadocs-mdx": ["@mdx-js/react"],
8202
- "fumadocs-ui": ["@mdx-js/react"],
8203
- "graphql-request": ["graphql"],
8204
- nextra: ["@mdx-js/react"],
8205
- "nextra-theme-blog": ["@mdx-js/react"],
8206
- "nextra-theme-docs": ["@mdx-js/react"],
8207
- "react-app-polyfill": ["core-js"],
8208
- "react-bootstrap": ["react-transition-group"],
8209
- "react-chartjs-2": ["chart.js"],
8210
- "react-redux": ["redux"],
8211
- "react-router-dom": ["react-router"],
8212
- "redux-thunk": ["redux"],
8213
- sanity: ["styled-components"],
8214
- sequelize: ["pg"],
8215
- "stylis-plugin-rtl": ["stylis"],
8216
- urql: ["graphql"],
8217
- "use-immer": ["immer"],
8218
- zustand: ["immer"]
8219
- };
8220
- const collectStaticPeerSatisfiedPackages = (declaredNames, confirmedUsedNames) => {
8221
- const peerSatisfied = /* @__PURE__ */ new Set();
8222
- for (const [packageName, peerNames] of Object.entries(STATIC_PEER_DEPENDENCY_MAP)) {
8223
- if (!confirmedUsedNames.has(packageName)) continue;
8224
- for (const peerName of peerNames) if (declaredNames.has(peerName)) peerSatisfied.add(peerName);
8225
- }
8226
- return peerSatisfied;
8227
- };
8228
- const IMPLICIT_COMPANION_DEPENDENCY_MAP = {
8229
- jest: ["jest-config"],
8230
- "jest-cli": ["jest-config"],
8231
- "vite-plus": ["@voidzero-dev/vite-plus-core"]
8232
- };
8233
- const collectImplicitCompanionPackages = (declaredNames, confirmedUsedNames) => {
8234
- const companions = /* @__PURE__ */ new Set();
8235
- for (const [packageName, companionNames] of Object.entries(IMPLICIT_COMPANION_DEPENDENCY_MAP)) {
8236
- if (!confirmedUsedNames.has(packageName)) continue;
8237
- for (const companionName of companionNames) if (declaredNames.has(companionName)) companions.add(companionName);
8238
- }
8239
- return companions;
8240
- };
8241
8212
  const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
8242
- const CLI_BINARY_TO_PACKAGE = {
8243
- "babel-node": "@babel/node",
8244
- "trigger.dev": "trigger.dev",
8245
- "@formatjs/cli": "@formatjs/cli",
8246
- "react-scripts": "react-scripts",
8247
- "webpack-cli": "webpack-cli",
8248
- "webpack-dev-server": "webpack-dev-server",
8249
- babel: "@babel/cli",
8250
- chokidar: "chokidar-cli",
8251
- "replace-in-file": "replace-in-file",
8252
- tauri: "@tauri-apps/cli",
8253
- tinacms: "@tinacms/cli",
8254
- "tsc-alias": "tsc-alias",
8255
- formatjs: "@formatjs/cli",
8256
- prompt: "prompt",
8257
- vitest: "vitest",
8258
- jest: "jest",
8259
- prisma: "prisma",
8260
- sequelize: "sequelize-cli",
8261
- rimraf: "rimraf",
8262
- concurrently: "concurrently",
8263
- parcel: "parcel",
8264
- rescript: "rescript",
8265
- webstudio: "webstudio",
8266
- cap: "@capacitor/cli",
8267
- "source-map-explorer": "source-map-explorer",
8268
- "ts-standard": "ts-standard",
8269
- "rndebugger-open": "react-native-debugger-open",
8270
- "simple-git-hooks": "simple-git-hooks",
8271
- "generate-arg-types": "@webstudio-is/generate-arg-types",
8272
- email: "@react-email/preview-server",
8273
- vp: "vite-plus",
8274
- turbo: "turbo",
8275
- changeset: "@changesets/cli",
8276
- tsx: "tsx"
8277
- };
8278
- const CLI_BINARY_FALLBACK_PACKAGES = {
8279
- babel: ["babel-cli"],
8280
- jest: ["jest-cli"],
8281
- remark: ["remark-cli"],
8282
- dumi: ["dumi"]
8283
- };
8284
- const ENV_WRAPPER_BINARY_SET = new Set([
8285
- "cross-env",
8286
- "dotenv",
8287
- "dotenv-flow",
8288
- "env-cmd"
8289
- ]);
8290
8213
  const INLINE_ENV_VAR_PATTERN = /^[A-Z_][A-Z0-9_]*=/;
8291
- const buildBinToPackageMap = (nodeModulesSearchRoots, declaredNames) => {
8214
+ const buildBinaryPackageIndex = (nodeModulesSearchRoots, declaredNames) => {
8292
8215
  const binToPackage = /* @__PURE__ */ new Map();
8293
- for (const [binary, packageName] of Object.entries(CLI_BINARY_TO_PACKAGE)) binToPackage.set(binary, packageName);
8216
+ const packagesProvidingBinary = /* @__PURE__ */ new Set();
8294
8217
  for (const packageName of declaredNames) {
8295
8218
  const packageBinJsonPath = findInstalledPackageJsonPath(packageName, nodeModulesSearchRoots);
8296
8219
  if (!packageBinJsonPath) continue;
8297
8220
  try {
8298
8221
  const binContent = readFileSync(packageBinJsonPath, "utf-8");
8299
- const binPackageJson = JSON.parse(binContent);
8300
- if (typeof binPackageJson.bin === "string") binToPackage.set(packageName.split("/").pop(), packageName);
8301
- else if (typeof binPackageJson.bin === "object" && binPackageJson.bin !== null) for (const binaryName of Object.keys(binPackageJson.bin)) binToPackage.set(binaryName, packageName);
8222
+ const binField = JSON.parse(binContent).bin;
8223
+ if (typeof binField === "string" && binField.length > 0) {
8224
+ binToPackage.set(packageName.split("/").pop(), packageName);
8225
+ packagesProvidingBinary.add(packageName);
8226
+ } else if (typeof binField === "object" && binField !== null) {
8227
+ const binaryNames = Object.keys(binField);
8228
+ if (binaryNames.length === 0) continue;
8229
+ for (const binaryName of binaryNames) binToPackage.set(binaryName, packageName);
8230
+ packagesProvidingBinary.add(packageName);
8231
+ }
8302
8232
  } catch {
8303
8233
  continue;
8304
8234
  }
8305
8235
  }
8306
- return binToPackage;
8236
+ return {
8237
+ binToPackage,
8238
+ packagesProvidingBinary
8239
+ };
8307
8240
  };
8308
8241
  const collectScriptReferencedPackages = (packageJsonPath, declaredNames, binToPackage) => {
8309
8242
  const referenced = /* @__PURE__ */ new Set();
@@ -8332,14 +8265,6 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
8332
8265
  const tokens = segment.trim().split(/\s+/);
8333
8266
  if (tokens.length === 0) continue;
8334
8267
  let binaryIndex = 0;
8335
- const firstToken = tokens[0].replace(/^.*\//, "");
8336
- if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
8337
- const envPackage = binToPackage.get(firstToken);
8338
- if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
8339
- binaryIndex = 1;
8340
- while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
8341
- if (binaryIndex >= tokens.length) continue;
8342
- }
8343
8268
  while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
8344
8269
  if (binaryIndex >= tokens.length) continue;
8345
8270
  const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
@@ -8348,7 +8273,6 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
8348
8273
  if (!candidateBinary) continue;
8349
8274
  const mappedPackage = binToPackage.get(candidateBinary);
8350
8275
  if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
8351
- for (const fallbackPackage of CLI_BINARY_FALLBACK_PACKAGES[candidateBinary] ?? []) if (declaredNames.has(fallbackPackage)) referenced.add(fallbackPackage);
8352
8276
  if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
8353
8277
  }
8354
8278
  }
@@ -1737,6 +1737,13 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
1737
1737
  } else wholeObjectUses.push(objectName);
1738
1738
  }
1739
1739
  }
1740
+ if (node.type === "JSXMemberExpression") {
1741
+ const jsxMember = node;
1742
+ if (jsxMember.object.type === "JSXIdentifier" && jsxMember.object.name !== void 0 && namespaceLocalNames.has(jsxMember.object.name) && jsxMember.property.name !== void 0) memberAccesses.push({
1743
+ objectName: jsxMember.object.name,
1744
+ memberName: jsxMember.property.name
1745
+ });
1746
+ }
1740
1747
  if (node.type === "SpreadElement") {
1741
1748
  const spreadArgument = node.argument;
1742
1749
  if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "deslop-js",
3
- "version": "0.5.8",
4
- "description": "Deslop JavaScript code",
3
+ "version": "0.6.1",
4
+ "description": "Remove AI slop from JavaScript code.",
5
5
  "keywords": [
6
6
  "dead-code",
7
7
  "dependencies",
@@ -16,7 +16,7 @@
16
16
  "bugs": {
17
17
  "url": "https://github.com/millionco/react-doctor/issues"
18
18
  },
19
- "license": "MIT",
19
+ "license": "SEE LICENSE IN LICENSE",
20
20
  "author": {
21
21
  "name": "Aiden Bai",
22
22
  "email": "aiden@million.dev"
@@ -58,7 +58,7 @@
58
58
  "minimatch": "^10.2.5",
59
59
  "oxc-parser": "^0.132.0",
60
60
  "oxc-resolver": "^11.19.1",
61
- "typescript": "^6.0.3"
61
+ "typescript": ">=5.0.4 <6"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/minimatch": "^5.1.2",