diff --git a/package-lock.json b/package-lock.json index b0bf32f7..5c7c25c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "chalk": "^2.4.2", "cheerio": "^1.0.0-rc.9", "commander": "^6.2.1", + "find-yarn-workspace-root": "^2.0.0", "glob": "^7.0.6", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", @@ -609,7 +610,6 @@ "version": "3.0.2", "resolved": "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz", "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc= sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -1053,7 +1053,6 @@ "version": "7.0.1", "resolved": "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA= sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1086,6 +1085,14 @@ "node": ">=8" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -1448,7 +1455,6 @@ "version": "7.0.0", "resolved": "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz", "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -1685,6 +1691,18 @@ "resolved": "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz", @@ -2044,7 +2062,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -2499,7 +2516,6 @@ "version": "5.0.1", "resolved": "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -3389,7 +3405,6 @@ "version": "3.0.2", "resolved": "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz", "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc= sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -3717,7 +3732,6 @@ "version": "7.0.1", "resolved": "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA= sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -3740,6 +3754,14 @@ } } }, + "find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "requires": { + "micromatch": "^4.0.2" + } + }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -4006,8 +4028,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-unicode-supported": { "version": "0.1.0", @@ -4196,6 +4217,15 @@ "resolved": "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz", @@ -4462,8 +4492,7 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "prebuild-install": { "version": "7.0.1", @@ -4787,7 +4816,6 @@ "version": "5.0.1", "resolved": "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } diff --git a/package.json b/package.json index b16cf251..7ae47728 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "chalk": "^2.4.2", "cheerio": "^1.0.0-rc.9", "commander": "^6.2.1", + "find-yarn-workspace-root": "^2.0.0", "glob": "^7.0.6", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", diff --git a/src/npm.ts b/src/npm.ts index c355cbef..8dafc357 100644 --- a/src/npm.ts +++ b/src/npm.ts @@ -1,8 +1,10 @@ import * as path from 'path'; import * as fs from 'fs'; import * as cp from 'child_process'; -import parseSemver from 'parse-semver'; -import { CancellationToken, log, nonnull } from './util'; +import findWorkspaceRoot from 'find-yarn-workspace-root'; +import { Manifest } from './manifest'; +import { readNodeManifest } from './package'; +import { CancellationToken, log } from './util'; const exists = (file: string) => fs.promises.stat(file).then( @@ -62,51 +64,67 @@ async function checkNPM(cancellationToken?: CancellationToken): Promise { } } -function getNpmDependencies(cwd: string): Promise { +function getNpmDependencies(cwd: string): Promise { return checkNPM() .then(() => exec('npm list --production --parseable --depth=99999 --loglevel=error', { cwd, maxBuffer: 5000 * 1024 }) ) - .then(({ stdout }) => stdout.split(/[\r\n]/).filter(dir => path.isAbsolute(dir))); -} - -interface YarnTreeNode { - name: string; - children: YarnTreeNode[]; + .then(({ stdout }) => stdout.split(/[\r\n]/).filter(dir => path.isAbsolute(dir)) + .map(dir => { + return { + src: dir, + dest: path.relative(cwd, dir) + } + })); } export interface YarnDependency { name: string; - path: string; + path: SourceAndDestination; children: YarnDependency[]; } -function asYarnDependency(prefix: string, tree: YarnTreeNode, prune: boolean): YarnDependency | null { - if (prune && /@[\^~]/.test(tree.name)) { - return null; - } - - let name: string; - - try { - const parseResult = parseSemver(tree.name); - name = parseResult.name; - } catch (err) { - name = tree.name.replace(/^([^@+])@.*$/, '$1'); - } - - const dependencyPath = path.join(prefix, name); - const children: YarnDependency[] = []; +export interface SourceAndDestination { + src: string; + dest: string; +} - for (const child of tree.children || []) { - const dep = asYarnDependency(path.join(prefix, name, 'node_modules'), child, prune); +async function asYarnDependencies(root: string, rootDependencies: string[]): Promise { + const resolve = async (prefix: string, dependencies: string[], collected: Map = new Map()): Promise => await Promise.all(dependencies + .map(async (name: string) => { + let newPrefix = prefix, depPath = null, depManifest = null; + while (!depManifest && root.length <= newPrefix.length) { + depPath = path.join(newPrefix, 'node_modules', name); + try { + depManifest = await readNodeManifest(depPath); + } catch (err) { + newPrefix = path.join(newPrefix, '..'); + if (newPrefix.length < root.length) { + throw err; + } + } + } - if (dep) { - children.push(dep); - } - } + if (!depPath || !depManifest) { + throw new Error(`Error finding dependencies`); + } - return { name, path: dependencyPath, children }; + const result: YarnDependency = { + name, + path: { + src: depPath, + dest: path.relative(root, depPath), + }, + children: [], + }; + const shouldResolveChildren = !collected.has(depPath); + collected.set(depPath, result); + if (shouldResolveChildren) { + result.children = await resolve(depPath, Object.keys(depManifest.dependencies || {}), collected); + } + return result; + })); + return resolve(root, rootDependencies); } function selectYarnDependencies(deps: YarnDependency[], packagedDependencies: string[]): YarnDependency[] { @@ -154,26 +172,10 @@ function selectYarnDependencies(deps: YarnDependency[], packagedDependencies: st return reached.values; } -async function getYarnProductionDependencies(cwd: string, packagedDependencies?: string[]): Promise { - const raw = await new Promise((c, e) => - cp.exec( - 'yarn list --prod --json', - { cwd, encoding: 'utf8', env: { ...process.env }, maxBuffer: 5000 * 1024 }, - (err, stdout) => (err ? e(err) : c(stdout)) - ) - ); - const match = /^{"type":"tree".*$/m.exec(raw); - - if (!match || match.length !== 1) { - throw new Error('Could not parse result of `yarn list --json`'); - } - +async function getYarnProductionDependencies(root: string, manifest: Manifest, packagedDependencies?: string[]): Promise { const usingPackagedDependencies = Array.isArray(packagedDependencies); - const trees = JSON.parse(match[0]).data.trees as YarnTreeNode[]; - let result = trees - .map(tree => asYarnDependency(path.join(cwd, 'node_modules'), tree, !usingPackagedDependencies)) - .filter(nonnull); + let result = await asYarnDependencies(root, Object.keys(manifest.dependencies || {})); if (usingPackagedDependencies) { result = selectYarnDependencies(result, packagedDependencies!); @@ -182,22 +184,35 @@ async function getYarnProductionDependencies(cwd: string, packagedDependencies?: return result; } -async function getYarnDependencies(cwd: string, packagedDependencies?: string[]): Promise { - const result = new Set([cwd]); +async function getYarnDependencies(cwd: string, root: string, manifest: Manifest, packagedDependencies?: string[]): Promise { + const result: SourceAndDestination[] = [{ + src: cwd, + dest: '' + }]; + + if (await exists(path.join(root, 'yarn.lock'))) { + const deps = await getYarnProductionDependencies(root, manifest, packagedDependencies); + const flatten = (dep: YarnDependency) => { + result.push(dep.path); + dep.children.forEach(flatten); + }; + deps.forEach(flatten); + } - const deps = await getYarnProductionDependencies(cwd, packagedDependencies); - const flatten = (dep: YarnDependency) => { - result.add(dep.path); - dep.children.forEach(flatten); - }; - deps.forEach(flatten); + const dedup = new Map(); - return [...result]; + for (const item of result) { + if (!dedup.has(item.src)) { + dedup.set(item.src, item); + } + } + + return [...dedup.values()]; } -export async function detectYarn(cwd: string): Promise { +export async function detectYarn(root: string) { for (const name of ['yarn.lock', '.yarnrc', '.yarnrc.yaml', '.pnp.cjs', '.yarn']) { - if (await exists(path.join(cwd, name))) { + if (await exists(path.join(root, name))) { if (!process.env['VSCE_TESTS']) { log.info( `Detected presence of ${name}. Using 'yarn' instead of 'npm' (to override this pass '--no-yarn' on the command line).` @@ -211,13 +226,16 @@ export async function detectYarn(cwd: string): Promise { export async function getDependencies( cwd: string, + manifest: Manifest, dependencies: 'npm' | 'yarn' | 'none' | undefined, packagedDependencies?: string[] -): Promise { +): Promise { + const root = findWorkspaceRoot(cwd) || cwd; + if (dependencies === 'none') { - return [cwd]; - } else if (dependencies === 'yarn' || (dependencies === undefined && (await detectYarn(cwd)))) { - return await getYarnDependencies(cwd, packagedDependencies); + return [{ src: root, dest: '' }]; + } else if (dependencies === 'yarn' || (dependencies === undefined && (await detectYarn(root)))) { + return await getYarnDependencies(cwd, root, manifest, packagedDependencies); } else { return await getNpmDependencies(cwd); } diff --git a/src/package.ts b/src/package.ts index ce628dab..93a893dd 100644 --- a/src/package.ts +++ b/src/package.ts @@ -20,7 +20,7 @@ import { validateEngineCompatibility, validateVSCodeTypesCompatibility, } from './validation'; -import { detectYarn, getDependencies } from './npm'; +import { detectYarn, getDependencies, SourceAndDestination } from './npm'; import * as GitHost from 'hosted-git-info'; import parseSemver from 'parse-semver'; import * as jsonc from 'jsonc-parser'; @@ -1315,10 +1315,8 @@ export function validateManifest(manifest: Manifest): Manifest { return manifest; } -export function readManifest(cwd = process.cwd(), nls = true): Promise { +export function readNodeManifest(cwd = process.cwd()): Promise { const manifestPath = path.join(cwd, 'package.json'); - const manifestNLSPath = path.join(cwd, 'package.nls.json'); - const manifest = fs.promises .readFile(manifestPath, 'utf8') .catch(() => Promise.reject(`Extension manifest not found: ${manifestPath}`)) @@ -1329,13 +1327,19 @@ export function readManifest(cwd = process.cwd(), nls = true): Promise console.error(`Error parsing 'package.json' manifest file: not a valid JSON file.`); throw e; } - }) + }); + return manifest; +} + +export function readManifest(cwd = process.cwd(), nls = true): Promise { + const manifest = readNodeManifest(cwd) .then(validateManifest); if (!nls) { return manifest; } + const manifestNLSPath = path.join(cwd, 'package.nls.json'); const manifestNLS = fs.promises .readFile(manifestNLSPath, 'utf8') .catch(err => (err.code !== 'ENOENT' ? Promise.reject(err) : Promise.resolve('{}'))) @@ -1526,13 +1530,17 @@ const notIgnored = ['!package.json', '!README.md']; async function collectAllFiles( cwd: string, + manifest: Manifest, dependencies: 'npm' | 'yarn' | 'none' | undefined, dependencyEntryPoints?: string[] -): Promise { - const deps = await getDependencies(cwd, dependencies, dependencyEntryPoints); +): Promise { + const deps = await getDependencies(cwd, manifest, dependencies, dependencyEntryPoints); const promises = deps.map(dep => - promisify(glob)('**', { cwd: dep, nodir: true, dot: true, ignore: 'node_modules/**' }).then(files => - files.map(f => path.relative(cwd, path.join(dep, f))).map(f => f.replace(/\\/g, '/')) + promisify(glob)('**', { cwd: dep.src, nodir: true, dot: true, ignore: 'node_modules/**' }).then(files => + files.map(f => ({ + src: path.relative(cwd, path.join(dep.src, f.replace(/\\/g, '/'))), + dest: path.join(dep.dest, f).replace(/\\/g, '/') + })) ) ); @@ -1541,12 +1549,13 @@ async function collectAllFiles( function collectFiles( cwd: string, + manifest: Manifest, dependencies: 'npm' | 'yarn' | 'none' | undefined, dependencyEntryPoints?: string[], ignoreFile?: string -): Promise { - return collectAllFiles(cwd, dependencies, dependencyEntryPoints).then(files => { - files = files.filter(f => !/\r$/m.test(f)); +): Promise { + return collectAllFiles(cwd, manifest, dependencies, dependencyEntryPoints).then(files => { + files = files.filter(f => !/\r$/m.test(f.src)); return ( fs.promises @@ -1586,8 +1595,8 @@ function collectFiles( .then(({ ignore, negate }) => files.filter( f => - !ignore.some(i => minimatch(f, i, MinimatchOptions)) || - negate.some(i => minimatch(f, i.substr(1), MinimatchOptions)) + !ignore.some(i => minimatch(f.src, i, MinimatchOptions)) || + negate.some(i => minimatch(f.src, i.substr(1), MinimatchOptions)) ) ) ); @@ -1658,8 +1667,8 @@ export function collect(manifest: Manifest, options: IPackageOptions = {}): Prom const ignoreFile = options.ignoreFile || undefined; const processors = createDefaultProcessors(manifest, options); - return collectFiles(cwd, getDependenciesOption(options), packagedDependencies, ignoreFile).then(fileNames => { - const files = fileNames.map(f => ({ path: `extension/${f}`, localPath: path.join(cwd, f) })); + return collectFiles(cwd, manifest, getDependenciesOption(options), packagedDependencies, ignoreFile).then(fileNames => { + const files = fileNames.map(f => ({ path: `extension/${f.dest}`, localPath: path.join(cwd, f.src) })); return processFiles(processors, files); }); @@ -1810,7 +1819,7 @@ export async function listFiles(options: IListFilesOptions = {}): Promise f.src); } /** @@ -1822,4 +1831,4 @@ export async function ls(options: IListFilesOptions = {}): Promise { for (const file of files) { console.log(`${file}`); } -} +} \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/.yarn-integrity b/src/test/fixtures/yarnWorkspaces/node_modules/.yarn-integrity new file mode 100644 index 00000000..ea5f503d --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/.yarn-integrity @@ -0,0 +1,28 @@ +{ + "systemParams": "darwin-x64-72", + "modulesFolders": [ + "node_modules", + "node_modules" + ], + "flags": [], + "linkedModules": [], + "topLevelPatterns": [ + "curry@1.2.0", + "filter-obj@2.0.1", + "in-array@0.1.2", + "is-number@7.0.0", + "map-obj@4.1.0", + "package-a@*", + "package-a@1.0.0", + "package-b@1.0.0" + ], + "lockfileEntries": { + "curry@1.2.0": "https://registry.yarnpkg.com/curry/-/curry-1.2.0.tgz#9e6dd289548dba7e653d5ae3fe903fe7dfb33af2", + "filter-obj@2.0.1": "https://registry.yarnpkg.com/filter-obj/-/filter-obj-2.0.1.tgz#34d9f0536786f072df7aeac3a8bda1c6e767aec6", + "in-array@0.1.2": "https://registry.yarnpkg.com/in-array/-/in-array-0.1.2.tgz#1a2683009177ab914ade0620a35c5039851f3715", + "is-number@7.0.0": "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b", + "map-obj@4.1.0": "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" + }, + "files": [], + "artifacts": {} +} \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/README.md b/src/test/fixtures/yarnWorkspaces/node_modules/curry/README.md new file mode 100644 index 00000000..8ae6ec36 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/README.md @@ -0,0 +1,130 @@ +CURRY +===== + +A curry function without anything **too clever** +_(... because hunger is the finest spice)_ + +[![browser support](https://ci.testling.com/hughfdjackson/curry.png)](https://ci.testling.com/hughfdjackson/curry) + + +# Why + +If you don't know currying, or aren't sold on it's awesomeness, perhaps [a friendly blog post](http://hughfdjackson.com/javascript/2013/07/06/why-curry-helps/) will help. + + +# API + +### curry + +```javascript +var curry = require('curry'); + +//-- creating a curried function is pretty +//-- straight forward: +var add = curry(function(a, b){ return a + b }); + +//-- it can be called like normal: +add(1, 2) //= 3 + +//-- or, if you miss off any arguments, +//-- a new funtion that expects all (or some) of +//-- the remaining arguments will be created: +var add1 = add(1); +add1(2) //= 3; + +//-- curry knows how many arguments a function should take +//-- by the number of parameters in the parameter list + +//-- in this case, a function and two arrays is expected +//-- (fn, a, b). zipWith will combine two arrays using a function: +var zipWith = curry(function(fn, a, b){ + return a.map(function(val, i){ return fn(val, b[i]) }); +}); + +//-- if there are still more arguments required, a curried function +//-- will always return a new curried function: +var zipAdd = zipWith(add); +var zipAddWith123 = zipAdd([1, 2, 3]); + +//-- both functions are usable as you'd expect at any time: +zipAdd([1, 2, 3], [1, 2, 3]); //= [2, 4, 6] +zipAddWith123([5, 6, 7]); //= [6, 8, 10] + +//-- the number of arguments a function is expected to provide +//-- can be discovered by the .length property +zipWith.length; //= 3 +zipAdd.length; //= 2 +zipAddWith123.length; //= 1 +``` + +### curry.to + +Sometimes it's necessary (especially when wrapping variadic functions) to explicitly provide an arity for your curried function: + +```javascript +var sum = function(){ + var nums = [].slice.call(arguments); + return nums.reduce(function(a, b){ return a + b }); +} + +var sum3 = curry.to(3, sum); +var sum4 = curry.to(4, sum); + +sum3(1, 2)(3) //= 6 +sum4(1)(2)(3, 4) //= 10 +``` + +### curry.adapt + +It's a (sad?) fact that JavaScript functions are often written to take the 'context' object as the first argument. + +With curried functions, of course, we want it to be the last object. `curry.adapt` shifts the context to the last argument, +to give us a hand with this: + +```javascript +var delve = require('delve'); +var delveC = curry.adapt(delve); + +var getDataFromResponse = delveC('response.body.data'); +getDataFromResponse({ response: { body: { data: { x: 2 }} } }); //= { x: 2 } +``` + +### curry.adaptTo + +Like `curry.adapt`, but the arity explicitly provided: + +```javascript +var _ = require('lodash'); +var map = curry.adaptTo(2, _.map); +var mapInc = map(function(a){ return a + 1 }) + +mapInc([1, 2, 3]) //= [2, 3, 4] +``` + +# installation + +### node/npm + +```bash +npm install curry +``` + +### amd + +```javascript +define(['libs/curry.min'], function(curry){ + //-- assuming libs/curry.min.js is the downloaded minified version from this repo, + //-- curry will be available here +}); +``` + +### browser + +If you're not using tools like [browserify](https://github.com/substack/node-browserify) or [require.js](http://requirejs.org), you can load curry globally: +```html + + +``` +∏∏ diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.js b/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.js new file mode 100644 index 00000000..9d8fe5ae --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.js @@ -0,0 +1,97 @@ +var slice = Array.prototype.slice; +var toArray = function(a){ return slice.call(a) } +var tail = function(a){ return slice.call(a, 1) } + +// fn, [value] -> fn +//-- create a curried function, incorporating any number of +//-- pre-existing arguments (e.g. if you're further currying a function). +var createFn = function(fn, args, totalArity){ + var remainingArity = totalArity - args.length; + + switch (remainingArity) { + case 0: return function(){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 1: return function(a){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 2: return function(a,b){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 3: return function(a,b,c){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 4: return function(a,b,c,d){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 5: return function(a,b,c,d,e){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 6: return function(a,b,c,d,e,f){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 7: return function(a,b,c,d,e,f,g){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 8: return function(a,b,c,d,e,f,g,h){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 9: return function(a,b,c,d,e,f,g,h,i){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + case 10: return function(a,b,c,d,e,f,g,h,i,j){ return processInvocation(fn, concatArgs(args, arguments), totalArity) }; + default: return createEvalFn(fn, args, remainingArity); + } +} + +// [value], arguments -> [value] +//-- concat new arguments onto old arguments array +var concatArgs = function(args1, args2){ + return args1.concat(toArray(args2)); +} + +// fn, [value], int -> fn +//-- create a function of the correct arity by the use of eval, +//-- so that curry can handle functions of any arity +var createEvalFn = function(fn, args, arity){ + var argList = makeArgList(arity); + + //-- hack for IE's faulty eval parsing -- http://stackoverflow.com/a/6807726 + var fnStr = 'false||' + + 'function(' + argList + '){ return processInvocation(fn, concatArgs(args, arguments)); }'; + return eval(fnStr); +} + +var makeArgList = function(len){ + var a = []; + for ( var i = 0; i < len; i += 1 ) a.push('a' + i.toString()); + return a.join(','); +} + +var trimArrLength = function(arr, length){ + if ( arr.length > length ) return arr.slice(0, length); + else return arr; +} + +// fn, [value] -> value +//-- handle a function being invoked. +//-- if the arg list is long enough, the function will be called +//-- otherwise, a new curried version is created. +var processInvocation = function(fn, argsArr, totalArity){ + argsArr = trimArrLength(argsArr, totalArity); + + if ( argsArr.length === totalArity ) return fn.apply(null, argsArr); + return createFn(fn, argsArr, totalArity); +} + +// fn -> fn +//-- curries a function! <3 +var curry = function(fn){ + return createFn(fn, [], fn.length); +} + +// num, fn -> fn +//-- curries a function to a certain arity! <33 +curry.to = curry(function(arity, fn){ + return createFn(fn, [], arity); +}); + +// num, fn -> fn +//-- adapts a function in the context-first style +//-- to a curried version. <3333 +curry.adaptTo = curry(function(num, fn){ + return curry.to(num, function(context){ + var args = tail(arguments).concat(context); + return fn.apply(this, args); + }); +}) + +// fn -> fn +//-- adapts a function in the context-first style to +//-- a curried version. <333 +curry.adapt = function(fn){ + return curry.adaptTo(fn.length, fn) +} + + +module.exports = curry; diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.min.js b/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.min.js new file mode 100644 index 00000000..7a93ac9d --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/curry.min.js @@ -0,0 +1 @@ +!function(e){if("function"==typeof bootstrap)bootstrap("curry",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeCurry=e}else"undefined"!=typeof window?window.curry=e():global.curry=e()}(function(){var define,ses,bootstrap,module,exports;return function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;slength)return arr.slice(0,length);else return arr};var processInvocation=function(fn,argsArr,totalArity){argsArr=trimArrLength(argsArr,totalArity);if(argsArr.length===totalArity)return fn.apply(null,argsArr);return createFn(fn,argsArr,totalArity)};var curry=function(fn){return createFn(fn,[],fn.length)};curry.to=curry(function(arity,fn){return createFn(fn,[],arity)});curry.adaptTo=curry(function(num,fn){return curry.to(num,function(context){var args=tail(arguments).concat(context);return fn.apply(this,args)})});curry.adapt=function(fn){return curry.adaptTo(fn.length,fn)};module.exports=curry},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/examples/usage.js b/src/test/fixtures/yarnWorkspaces/node_modules/curry/examples/usage.js new file mode 100644 index 00000000..5a190c7f --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/examples/usage.js @@ -0,0 +1,38 @@ +var curry = require('../'); + +//-- creating a curried function is pretty +//-- straight forward: +var add = curry(function(a, b){ return a + b }); + +//-- it can be called like normal: +add(1, 2) //= 3 + +//-- or, if you miss off any arguments, +//-- a new funtion that expects all (or some) of +//-- the remaining arguments will be created: +var add1 = add(1); +add1(2) //= 3; + +//-- curry knows how many arguments a function should take +//-- by the number of parameters in the parameter list + +//-- in this case, a function and two arrays is expected +//-- (fn, a, b). zipWith will combine two arrays using a function: +var zipWith = curry(function(fn, a, b){ + return a.map(function(val, i){ return fn(val, b[i]) }); +}); + +//-- if there are still more arguments required, a curried function +//-- will always return a new curried function: +var zipAdd = zipWith(add); +var zipAddWith123 = zipAdd([1, 2, 3]); + +//-- both functions are usable as you'd expect at any time: +zipAdd([1, 2, 3], [1, 2, 3]); //= [2, 4, 6] +zipAddWith123([5, 6, 7]); //= [6, 8, 10] + +//-- the number of arguments a function is expected to provide +//-- can be discovered by the .length property +zipWith.length; //= 3 +zipAdd.length; //= 2 +zipAddWith123.length; //= 1 diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/package.json b/src/test/fixtures/yarnWorkspaces/node_modules/curry/package.json new file mode 100644 index 00000000..a96c633a --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/package.json @@ -0,0 +1,43 @@ +{ + "name": "curry", + "description": "flexible but simple curry function", + "version": "1.2.0", + "homepage": "https://github.com/dominictarr/curry", + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/curry.git" + }, + "author": "Dominic Tarr ", + "contributors": [ + "Hugh FD Jackson " + ], + "main": "./curry", + "devDependencies": { + "mocha": "1.8.1", + "browserify": "2.17.2", + "uglify-js": "2.3.6", + "lodash": "2.1.0", + "delve": "0.3.2" + }, + "testling": { + "files": "test/*-test.js", + "browsers": [ + "iexplore/6.0", + "iexplore/7.0", + "iexplore/8.0", + "iexplore/9.0", + "iexplore/10.0", + "chrome/4.0", + "chrome/23.0", + "firefox/3.0", + "firefox/17.0", + "safari/5.0.5", + "safari/5.1" + ], + "harness": "mocha" + }, + "scripts": { + "test": "./node_modules/mocha/bin/mocha test", + "prepublish": "./node_modules/browserify/bin/cmd.js --standalone curry -e curry.js | ./node_modules/uglify-js/bin/uglifyjs > curry.min.js" + } +} diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/curry/test/curry-test.js b/src/test/fixtures/yarnWorkspaces/node_modules/curry/test/curry-test.js new file mode 100644 index 00000000..53e1911c --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/curry/test/curry-test.js @@ -0,0 +1,133 @@ +var curry = require('../'); +var a = require('assert'); + + +describe('curry', function(){ + + it('should curry in the haskell sense, taking the arity from the function', function(){ + var sum5 = function(a, b, c, d, e){ return a + b + c + d + e }; + var sum5C = curry(sum5); + + a.equal(sum5(1, 2, 3, 4, 5), sum5C(1)(2)(3)(4)(5)); + }); + + it('should be pure - each new argument should not affect the overall list', function(){ + var add = curry(function(a, b){ return a + b }); + var add1 = add(1); + var add2 = add(2); + a.equal(add1(1), 2); + a.equal(add1(2), 3); + a.equal(add1(3), 4); + a.equal(add1(4), 5); + + a.equal(add2(1), 3); + a.equal(add2(2), 4); + a.equal(add2(3), 5); + a.equal(add2(4), 6); + }); + + it('should drop "extra" arguments', function(){ + var reportArgs = curry(function(a, b){ return [].slice.call(arguments) }); + + a.deepEqual(reportArgs('a', 'b', 'c', 'd', 'e'), ['a', 'b']); + }); + + it('should allow multiple arguments to be passed at a time', function(){ + var sum3 = curry(function(a, b, c){ return a + b + c }); + + a.equal(sum3(1, 2, 3), sum3(1, 2)(3)); + a.equal(sum3(1, 2, 3), sum3(1)(2, 3)); + a.equal(sum3(1, 2, 3), sum3(1)(2)(3)); + }); + + it('should report the arity of returned functions correctly', function(){ + var sum3 = curry(function(a, b, c){ return a + b + c }); + + a.equal(sum3.length, 3); + a.equal(sum3(1).length, 2); + a.equal(sum3(1)(2).length, 1); + + a.equal(curry(function(){}).length, 0) + a.equal(curry(function(a){}).length, 1) + a.equal(curry(function(a, b){}).length, 2) + a.equal(curry(function(a, b, c){}).length, 3) + a.equal(curry(function(a, b, c, d){}).length, 4) + a.equal(curry(function(a, b, c, d, e){}).length, 5) + a.equal(curry(function(a, b, c, d, e, f){}).length, 6) + a.equal(curry(function(a, b, c, d, e, f, g){}).length, 7) + a.equal(curry(function(a, b, c, d, e, f, g, h){}).length, 8) + a.equal(curry(function(a, b, c, d, e, f, g, h, i){}).length, 9) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j){}).length, 10) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j, k){}).length, 11) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j, k, l){}).length, 12) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j, k, l, m){}).length, 13) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j, k, l, m, n){}).length, 14) + a.equal(curry(function(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o){}).length, 15) + }); + + it('should allow 0 arg curried fns', function(){ + var noop = curry(function(){}); + + a.equal(noop(), undefined); + }); +}); + +describe('curry.to', function(){ + + it('should curry to the specified arity', function(){ + var noop = function(){}; + + for ( var i = 0; i < 15; i += 1 ) + a.equal(curry.to(i, noop).length, i); + }); + + it('should be curried', function(){ + var sum = function(){ + var nums = [].slice.call(arguments); + var count = 0; + + for ( var i = 0; i < nums.length; i += 1 ) count += nums[i]; + return count; + }; + + var sum3 = curry.to(3)(sum); + a.equal(sum3(1)(2)(3), 6); + }); +}); + +describe('curry.adapt', function(){ + it('should shift the first argument the end', function(){ + var noop = curry.adapt(function(){}); + var cat1 = curry.adapt(function(a){ return a }); + var cat2 = curry.adapt(function(a, b){ return a + b }); + var cat3 = curry.adapt(function(a, b, c){ return a + b + c }); + var cat4 = curry.adapt(function(a, b, c, d){ return a + b + c + d }); + + a.equal(noop(), undefined); + a.equal(cat1('a'), 'a'); + a.equal(cat2('a')('b'), 'ba'); + a.equal(cat3('a', 'b')('c'), 'bca'); + a.equal(cat4('a', 'b')('c', 'd'), 'bcda'); + }); +}); + +describe('curry.adaptTo', function(){ + it('should shift the first argument the end, and curry by a specified amount', function(){ + var cat = function(){ + var args = [].slice.call(arguments); + return args.join(''); + } + + var noop = curry.adaptTo(0)(cat); + var cat1 = curry.adaptTo(1)(cat); + var cat2 = curry.adaptTo(2)(cat); + var cat3 = curry.adaptTo(3)(cat); + var cat4 = curry.adaptTo(4)(cat); + + a.equal(noop(), ''); + a.equal(cat1('a'), 'a'); + a.equal(cat2('a')('b'), 'ba'); + a.equal(cat3('a', 'b')('c'), 'bca'); + a.equal(cat4('a', 'b')('c', 'd'), 'bcda'); + }); +}); diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/index.js b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/index.js new file mode 100644 index 00000000..b05ed67c --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/index.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = (object, predicate) => { + const result = {}; + const isArray = Array.isArray(predicate); + + for (const [key, value] of Object.entries(object)) { + if (isArray ? predicate.includes(key) : predicate(key, value, object)) { + result[key] = value; + } + } + + return result; +}; diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/license b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/license new file mode 100644 index 00000000..e7af2f77 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/package.json b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/package.json new file mode 100644 index 00000000..3da71cc4 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/package.json @@ -0,0 +1,37 @@ +{ + "name": "filter-obj", + "version": "2.0.1", + "description": "Filter object keys and values into a new object", + "license": "MIT", + "repository": "sindresorhus/filter-obj", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "filter", + "object", + "key", + "keys", + "value", + "values", + "iterate", + "iterator" + ], + "devDependencies": { + "ava": "^2.4.0", + "tsd": "^0.9.0", + "xo": "^0.25.3" + } +} diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/readme.md b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/readme.md new file mode 100644 index 00000000..57c84ccd --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/filter-obj/readme.md @@ -0,0 +1,57 @@ +# filter-obj [![Build Status](https://travis-ci.org/sindresorhus/filter-obj.svg?branch=master)](https://travis-ci.org/sindresorhus/filter-obj) + +> Filter object keys and values into a new object + + +## Install + +``` +$ npm install filter-obj +``` + + +## Usage + +```js +const filterObject = require('filter-obj'); + +const object = { + foo: true, + bar: false +}; + +const newObject = filterObject(object, (key, value) => value === true); +//=> {foo: true} + +const newObject2 = filterObject(object, ['bar']); +//=> {bar: false} +``` + + +## API + +### filterObject(source, filter) +### filterObject(source, includeKeys) + +#### source + +Type: `object` + +Source object to filter properties from. + +#### filter + +Type: `Function` + +A predicate function that detemines whether a property should be assigned to the new object. The function has the signature `filterFunction(sourceKey, sourceValue, source)`. + +#### includeKeys + +Type: `string[]` + +Array of property names that should be assigned to the new object. + + +## Related + +- [map-obj](https://github.com/sindresorhus/map-obj) - Map object keys and values into a new object diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/in-array/LICENSE b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/LICENSE new file mode 100644 index 00000000..ce0a70f2 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/in-array/README.md b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/README.md new file mode 100644 index 00000000..1e0219f0 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/README.md @@ -0,0 +1,76 @@ +# in-array [![NPM version](https://img.shields.io/npm/v/in-array.svg?style=flat)](https://www.npmjs.com/package/in-array) [![NPM downloads](https://img.shields.io/npm/dm/in-array.svg?style=flat)](https://npmjs.org/package/in-array) [![Build Status](https://img.shields.io/travis/jonschlinkert/in-array.svg?style=flat)](https://travis-ci.org/jonschlinkert/in-array) + +> Return true if a value exists in an array. Faster than using indexOf and won't blow up on null values. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install in-array --save +``` + +## Usage + +```js +var inArray = require('in-array'); +console.log(inArray(['a', 'b', 'c'], 'a')); +//=> true + +console.log(inArray(null, 'a')); +//=> false + +console.log(inArray(null)); +//=> false +``` + +## Related projects + +You might also be interested in these projects: + +* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten) +* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://www.npmjs.com/package/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union) +* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object) +* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/in-array/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/in-array/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v, on March 27, 2016._ \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/in-array/index.js b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/index.js new file mode 100644 index 00000000..388c4faa --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/index.js @@ -0,0 +1,21 @@ +/*! + * in-array + * + * Copyright (c) 2014 Jon Schlinkert, contributors. + * Licensed under the MIT License + */ + +'use strict'; + +module.exports = function inArray (arr, val) { + arr = arr || []; + var len = arr.length; + var i; + + for (i = 0; i < len; i++) { + if (arr[i] === val) { + return true; + } + } + return false; +}; diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/in-array/package.json b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/package.json new file mode 100644 index 00000000..8c5da4eb --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/in-array/package.json @@ -0,0 +1,61 @@ +{ + "name": "in-array", + "description": "Return true if a value exists in an array. Faster than using indexOf and won't blow up on null values.", + "version": "0.1.2", + "homepage": "https://github.com/jonschlinkert/in-array", + "author": "Jon Schlinkert (https://github.com/jonschlinkert)", + "repository": "jonschlinkert/in-array", + "bugs": { + "url": "https://github.com/jonschlinkert/in-array/issues" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "main": "index.js", + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "lint": "jshint *.js test/*.js", + "test": "npm run lint && mocha" + }, + "devDependencies": { + "benchmark": "^2.1.0", + "gulp-format-md": "^0.1.7" + }, + "keywords": [ + "array", + "check", + "element", + "find", + "index", + "index-of", + "of" + ], + "verb": { + "run": true, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "isobject", + "is-plain-object", + "arr-flatten", + "arr-union" + ] + }, + "reflinks": [ + "verb" + ], + "lint": { + "reflinks": true + } + } +} diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/is-number/LICENSE b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/LICENSE new file mode 100644 index 00000000..9af4a67d --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/is-number/README.md b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/README.md new file mode 100644 index 00000000..eb8149e8 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/README.md @@ -0,0 +1,187 @@ +# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![NPM total downloads](https://img.shields.io/npm/dt/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-number) + +> Returns true if the value is a finite number. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save is-number +``` + +## Why is this needed? + +In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use `+`, `-`, or `Number()` to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results: + +```js +console.log(+[]); //=> 0 +console.log(+''); //=> 0 +console.log(+' '); //=> 0 +console.log(typeof NaN); //=> 'number' +``` + +This library offers a performant way to smooth out edge cases like these. + +## Usage + +```js +const isNumber = require('is-number'); +``` + +See the [tests](./test.js) for more examples. + +### true + +```js +isNumber(5e3); // true +isNumber(0xff); // true +isNumber(-1.1); // true +isNumber(0); // true +isNumber(1); // true +isNumber(1.1); // true +isNumber(10); // true +isNumber(10.10); // true +isNumber(100); // true +isNumber('-1.1'); // true +isNumber('0'); // true +isNumber('012'); // true +isNumber('0xff'); // true +isNumber('1'); // true +isNumber('1.1'); // true +isNumber('10'); // true +isNumber('10.10'); // true +isNumber('100'); // true +isNumber('5e3'); // true +isNumber(parseInt('012')); // true +isNumber(parseFloat('012')); // true +``` + +### False + +Everything else is false, as you would expect: + +```js +isNumber(Infinity); // false +isNumber(NaN); // false +isNumber(null); // false +isNumber(undefined); // false +isNumber(''); // false +isNumber(' '); // false +isNumber('foo'); // false +isNumber([1]); // false +isNumber([]); // false +isNumber(function () {}); // false +isNumber({}); // false +``` + +## Release history + +### 7.0.0 + +* Refactor. Now uses `.isFinite` if it exists. +* Performance is about the same as v6.0 when the value is a string or number. But it's now 3x-4x faster when the value is not a string or number. + +### 6.0.0 + +* Optimizations, thanks to @benaadams. + +### 5.0.0 + +**Breaking changes** + +* removed support for `instanceof Number` and `instanceof String` + +## Benchmarks + +As with all benchmarks, take these with a grain of salt. See the [benchmarks](./benchmark/index.js) for more detail. + +``` +# all +v7.0 x 413,222 ops/sec ±2.02% (86 runs sampled) +v6.0 x 111,061 ops/sec ±1.29% (85 runs sampled) +parseFloat x 317,596 ops/sec ±1.36% (86 runs sampled) +fastest is 'v7.0' + +# string +v7.0 x 3,054,496 ops/sec ±1.05% (89 runs sampled) +v6.0 x 2,957,781 ops/sec ±0.98% (88 runs sampled) +parseFloat x 3,071,060 ops/sec ±1.13% (88 runs sampled) +fastest is 'parseFloat,v7.0' + +# number +v7.0 x 3,146,895 ops/sec ±0.89% (89 runs sampled) +v6.0 x 3,214,038 ops/sec ±1.07% (89 runs sampled) +parseFloat x 3,077,588 ops/sec ±1.07% (87 runs sampled) +fastest is 'v6.0' +``` + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.") +* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive. | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ") +* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.") +* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 49 | [jonschlinkert](https://github.com/jonschlinkert) | +| 5 | [charlike-old](https://github.com/charlike-old) | +| 1 | [benaadams](https://github.com/benaadams) | +| 1 | [realityking](https://github.com/realityking) | + +### Author + +**Jon Schlinkert** + +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 15, 2018._ \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/is-number/index.js b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/index.js new file mode 100644 index 00000000..27f19b75 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/index.js @@ -0,0 +1,18 @@ +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +module.exports = function(num) { + if (typeof num === 'number') { + return num - num === 0; + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; +}; diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/is-number/package.json b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/package.json new file mode 100644 index 00000000..37150726 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/is-number/package.json @@ -0,0 +1,82 @@ +{ + "name": "is-number", + "description": "Returns true if a number or string value is a finite number. Useful for regex matches, parsing, user input, etc.", + "version": "7.0.0", + "homepage": "https://github.com/jonschlinkert/is-number", + "author": "Jon Schlinkert (https://github.com/jonschlinkert)", + "contributors": [ + "Jon Schlinkert (http://twitter.com/jonschlinkert)", + "Olsten Larck (https://i.am.charlike.online)", + "Rouven Weßling (www.rouvenwessling.de)" + ], + "repository": "jonschlinkert/is-number", + "bugs": { + "url": "https://github.com/jonschlinkert/is-number/issues" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "main": "index.js", + "engines": { + "node": ">=0.12.0" + }, + "scripts": { + "test": "mocha" + }, + "devDependencies": { + "ansi": "^0.3.1", + "benchmark": "^2.1.4", + "gulp-format-md": "^1.0.0", + "mocha": "^3.5.3" + }, + "keywords": [ + "cast", + "check", + "coerce", + "coercion", + "finite", + "integer", + "is", + "isnan", + "is-nan", + "is-num", + "is-number", + "isnumber", + "isfinite", + "istype", + "kind", + "math", + "nan", + "num", + "number", + "numeric", + "parseFloat", + "parseInt", + "test", + "type", + "typeof", + "value" + ], + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "related": { + "list": [ + "is-plain-object", + "is-primitive", + "isobject", + "kind-of" + ] + }, + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + } + } +} diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/index.js b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/index.js new file mode 100644 index 00000000..4f1e4be9 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/index.js @@ -0,0 +1,54 @@ +'use strict'; + +const isObject = value => typeof value === 'object' && value !== null; + +// Customized for this use-case +const isObjectCustom = value => + isObject(value) && + !(value instanceof RegExp) && + !(value instanceof Error) && + !(value instanceof Date); + +const mapObject = (object, mapper, options, isSeen = new WeakMap()) => { + options = { + deep: false, + target: {}, + ...options + }; + + if (isSeen.has(object)) { + return isSeen.get(object); + } + + isSeen.set(object, options.target); + + const {target} = options; + delete options.target; + + const mapArray = array => array.map(element => isObjectCustom(element) ? mapObject(element, mapper, options, isSeen) : element); + if (Array.isArray(object)) { + return mapArray(object); + } + + for (const [key, value] of Object.entries(object)) { + let [newKey, newValue] = mapper(key, value, object); + + if (options.deep && isObjectCustom(newValue)) { + newValue = Array.isArray(newValue) ? + mapArray(newValue) : + mapObject(newValue, mapper, options, isSeen); + } + + target[newKey] = newValue; + } + + return target; +}; + +module.exports = (object, mapper, options) => { + if (!isObject(object)) { + throw new TypeError(`Expected an object, got \`${object}\` (${typeof object})`); + } + + return mapObject(object, mapper, options); +}; diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/license b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/license new file mode 100644 index 00000000..e7af2f77 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/package.json b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/package.json new file mode 100644 index 00000000..18cf63c3 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/package.json @@ -0,0 +1,42 @@ +{ + "name": "map-obj", + "version": "4.1.0", + "description": "Map object keys and values into a new object", + "license": "MIT", + "repository": "sindresorhus/map-obj", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "map", + "object", + "key", + "keys", + "value", + "values", + "iterate", + "iterator", + "rename", + "modify", + "deep", + "recurse", + "recursive" + ], + "devDependencies": { + "ava": "^2.0.0", + "tsd": "^0.7.3", + "xo": "^0.24.0" + } +} diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/readme.md b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/readme.md new file mode 100644 index 00000000..cd405f56 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/map-obj/readme.md @@ -0,0 +1,76 @@ +# map-obj [![Build Status](https://travis-ci.org/sindresorhus/map-obj.svg?branch=master)](https://travis-ci.org/sindresorhus/map-obj) + +> Map object keys and values into a new object + + +## Install + +``` +$ npm install map-obj +``` + + +## Usage + +```js +const mapObject = require('map-obj'); + +const newObject = mapObject({foo: 'bar'}, (key, value) => [value, key]); +//=> {bar: 'foo'} +``` + + +## API + +### mapObject(source, mapper, options?) + +#### source + +Type: `object` + +Source object to copy properties from. + +#### mapper + +Type: `Function` + +Mapping function. + +- It has signature `mapper(sourceKey, sourceValue, source)`. +- It must return a two item array: `[targetKey, targetValue]`. + +#### options + +Type: `object` + +##### deep + +Type: `boolean`
+Default: `false` + +Recurse nested objects and objects in arrays. + +##### target + +Type: `object`
+Default: `{}` + +Target object to map properties on to. + + +## Related + +- [filter-obj](https://github.com/sindresorhus/filter-obj) - Filter object keys and values into a new object + + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/package-a b/src/test/fixtures/yarnWorkspaces/node_modules/package-a new file mode 120000 index 00000000..ea7528af --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/package-a @@ -0,0 +1 @@ +../packageA \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/node_modules/package-b b/src/test/fixtures/yarnWorkspaces/node_modules/package-b new file mode 120000 index 00000000..b9b0c8fc --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/node_modules/package-b @@ -0,0 +1 @@ +../packageB \ No newline at end of file diff --git a/src/test/fixtures/yarnWorkspaces/package.json b/src/test/fixtures/yarnWorkspaces/package.json new file mode 100644 index 00000000..899beedb --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/package.json @@ -0,0 +1,15 @@ +{ + "name": "yarn-workspaces-monorepo", + "publisher": "mocha", + "version": "1.0.0", + "private": true, + "engines": { "vscode": "*" }, + "workspaces": [ + "packageA", + "packageB" + ], + "dependencies": { + }, + "devDependencies": { + } +} diff --git a/src/test/fixtures/yarnWorkspaces/packageA/important/prod.log b/src/test/fixtures/yarnWorkspaces/packageA/important/prod.log new file mode 100644 index 00000000..6bfe6b19 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageA/important/prod.log @@ -0,0 +1 @@ +log diff --git a/src/test/fixtures/yarnWorkspaces/packageA/logger.log b/src/test/fixtures/yarnWorkspaces/packageA/logger.log new file mode 100644 index 00000000..6bfe6b19 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageA/logger.log @@ -0,0 +1 @@ +log diff --git a/src/test/fixtures/yarnWorkspaces/packageA/main.js b/src/test/fixtures/yarnWorkspaces/packageA/main.js new file mode 100644 index 00000000..90d2a58e --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageA/main.js @@ -0,0 +1 @@ +// Package A diff --git a/src/test/fixtures/yarnWorkspaces/packageA/package.json b/src/test/fixtures/yarnWorkspaces/packageA/package.json new file mode 100644 index 00000000..741a1e2f --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageA/package.json @@ -0,0 +1,15 @@ +{ + "name": "package-a", + "publisher": "mocha", + "version": "1.0.0", + "engines": { + "vscode": "*" + }, + "dependencies": { + "curry": "1.2.0", + "filter-obj": "2.0.1" + }, + "devDependencies": { + "is-number": "7.0.0" + } +} diff --git a/src/test/fixtures/yarnWorkspaces/packageB/.vscodeignore b/src/test/fixtures/yarnWorkspaces/packageB/.vscodeignore new file mode 100644 index 00000000..20e9ce5b --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageB/.vscodeignore @@ -0,0 +1,5 @@ +# pattern of file name +../node_modules/package-a/*.log + +# include files using negate +!../node_modules/package-a/important diff --git a/src/test/fixtures/yarnWorkspaces/packageB/main.js b/src/test/fixtures/yarnWorkspaces/packageB/main.js new file mode 100644 index 00000000..7fc1d307 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageB/main.js @@ -0,0 +1 @@ +// Package B diff --git a/src/test/fixtures/yarnWorkspaces/packageB/package.json b/src/test/fixtures/yarnWorkspaces/packageB/package.json new file mode 100644 index 00000000..4c5c6fa2 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/packageB/package.json @@ -0,0 +1,15 @@ +{ + "name": "package-b", + "publisher": "mocha", + "version": "1.0.0", + "engines": { + "vscode": "*" + }, + "dependencies": { + "map-obj": "4.1.0", + "package-a": "*" + }, + "devDependencies": { + "in-array": "0.1.2" + } +} diff --git a/src/test/fixtures/yarnWorkspaces/yarn.lock b/src/test/fixtures/yarnWorkspaces/yarn.lock new file mode 100644 index 00000000..8dcbbab5 --- /dev/null +++ b/src/test/fixtures/yarnWorkspaces/yarn.lock @@ -0,0 +1,28 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +curry@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/curry/-/curry-1.2.0.tgz#9e6dd289548dba7e653d5ae3fe903fe7dfb33af2" + integrity sha1-nm3SiVSNun5lPVrj/pA/59+zOvI= + +filter-obj@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-2.0.1.tgz#34d9f0536786f072df7aeac3a8bda1c6e767aec6" + integrity sha512-yDEp513p7+iLdFHWBVdZFnRiOYwg8ZqmpaAiZCMjzqsbo7tCS4Qm4ulXOht337NGzkukKa9u3W4wqQ9tQPm3Ug== + +in-array@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/in-array/-/in-array-0.1.2.tgz#1a2683009177ab914ade0620a35c5039851f3715" + integrity sha1-GiaDAJF3q5FK3gYgo1xQOYUfNxU= + +is-number@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +map-obj@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" + integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== diff --git a/src/test/package.test.ts b/src/test/package.test.ts index 87ecbcb6..c0f15329 100644 --- a/src/test/package.test.ts +++ b/src/test/package.test.ts @@ -11,6 +11,7 @@ import { validateManifest, IPackageOptions, ManifestProcessor, + ILocalFile, versionBump, VSIX, LicenseProcessor, @@ -243,6 +244,57 @@ describe('collect', function () { const manifest = await readManifest(cwd); await collect(manifest, { cwd }); }); + + it('should collect the right files when using yarn workspaces', async () => { + // PackageB will act as the extension here + const root = fixture('yarnWorkspaces'); + const cwd = path.join(root, 'packageB'); + const manifest = await readManifest(cwd); + + assert.strictEqual(manifest.name, 'package-b'); + + const files = await collect(manifest, { cwd }) as ILocalFile[]; + + [ + { + path: 'extension/main.js', + localPath: path.resolve(cwd, 'main.js') + }, + { + path: 'extension/package.json', + localPath: path.resolve(cwd, 'package.json') + }, + { + path: 'extension/node_modules/package-a/main.js', + localPath: path.resolve(root, 'node_modules/package-a/main.js') + }, + { + path: 'extension/node_modules/package-a/package.json', + localPath: path.resolve(root, 'node_modules/package-a/package.json') + }, + { + path: 'extension/node_modules/package-a/important/prod.log', + localPath: path.resolve(root, 'node_modules/package-a/important/prod.log') + }, + { + path: 'extension/node_modules/curry/curry.js', + localPath: path.resolve(root, 'node_modules/curry/curry.js') + }, + { + path: 'extension/node_modules/curry/package.json', + localPath: path.resolve(root, 'node_modules/curry/package.json') + } + ].forEach(expected => { + const found = files.find(f => f.path === expected.path || f.localPath === expected.localPath); + if (found) { + assert.strictEqual(found.path, expected.path, 'path'); + assert.strictEqual(found.localPath, expected.localPath, 'localPath'); + } + }) + const ignoreFilename = 'extension/node_modules/package-a/logger.log'; + const ignore = files.find(f => f.path === ignoreFilename); + assert.ok(!ignore, 'should ignore ' + ignoreFilename) + }); }); describe('readManifest', () => {