diff --git a/doc/adr/0011-native-npm-lock-regeneration.md b/doc/adr/0011-native-npm-lock-regeneration.md new file mode 100644 index 00000000000..18b2f8cb7e5 --- /dev/null +++ b/doc/adr/0011-native-npm-lock-regeneration.md @@ -0,0 +1,135 @@ +# 11. Native npm lock file regeneration + +Date: 2026-07-29 + +## Status + +Proposed + +Applies the approach of [9. Native Python lock file regeneration](0009-native-python-lock-regeneration.md) +to the Node ecosystem, npm first. + +## Context + +When a dependency recipe edits a `package.json`, the sibling lock file must be updated to +match. Regeneration previously ran the package manager (`npm install --package-lock-only +--ignore-scripts --legacy-peer-deps`) in a temp directory. At fleet scale this fails for +environmental reasons unrelated to the edit — the package manager missing from the +worker, registry credentials not reaching the sandbox — and the run finishes with the +manifest changed and the lock stale, surfacing only truncated subprocess stderr +(customer-requests#2893). + +Node is materially easier to regenerate natively than Python was: + +- **One registry request per moving package.** The full packument carries each version's + dependencies, `engines`, `license`, `funding`, `bin` and the `dist.integrity` hash the + lock needs — npm itself resolves with `fullMetadata: true`. Python's three-tier + metadata ladder has no analogue here, and no tarball is ever downloaded. +- **No backtracking.** npm permits coexisting versions, so resolution is a greedy tree + walk; the only search-like behavior is placement (below). +- **The lock records the requested state.** The root `""` entry mirrors the manifest's + dependency blocks, so the edit set falls out of a diff with no external oracle. + +And harder in one way: `package-lock.json` records a **physical `node_modules` tree**. +Whether a package lands hoisted at `node_modules/x` or nested under a dependent is a +placement decision (arborist's `placeDep`), and `dev`/`optional`/`devOptional`/`peer` +flags are whole-graph reachability colors. + +npm's emission is fully deterministic and reimplementable: the lock is +`json-stringify-nice(data, swKeyOrder, indent) + '\n'` with `\n` mapped to the source +file's EOL — every object's keys sorted scalars-before-objects, `swKeyOrder` first, then +`localeCompare('en')`. + +## Decision + +Replace the npm shell-out with a **native Java engine** behind the existing +`LockFileRegeneration` seam, preserving ADR 0009's contract: minimal update, untouched +entries byte-for-byte, fail loud with a structured failure rather than guess, and no +dual mechanism (the npm shell-out is deleted; the other package managers keep theirs +until they go native). + +The engine (`internal/npmlock/NpmLockEngine`) handles the provable subset: + +- a **version move** whose closure stays satisfied by the existing tree, checked in both + directions: the new version's requirements resolve satisfied from its location + (nested copies shadowing, `overrides` substituted), and every dependent that resolved + the old copy still accepts the new version; +- **removals**, with an orphan sweep and flag recoloring via arborist's own + `calc-dep-flags` fixed-point algorithm — applied only where the edit changed an + entry's color, so pre-existing drift is never rewritten as a side effect; +- **top-level additions** that fit without displacing anything; +- **range edits** the current pin already satisfies (zero network); +- version selection matching npm-pick-manifest: the `latest` dist-tag wins when it + satisfies the range, else the highest satisfying version. + +Everything else fails loud with `RESOLUTION_REQUIRED` or `UNSUPPORTED_ENTRY_TYPE`: +cascading placement, peer conflicts, workspace and `link:` locks, git/file/alias/tarball +specs, bundled dependencies, lockfileVersion < 3, and **override edits that move a +pin** — the recorded `override` fixture shows npm re-places overridden copies (nesting +them under dependents), which is placement, not substitution. A lock that fails the +parse→emit round-trip (hand-edited, or written by npm < 9) is refused rather than +normalized wholesale. + +Supporting layers, mirroring ADR 0009's stack: + +- `internal/semver`: node-semver versions and ranges ported from npm/node-semver and + driven by its own fixture corpus. +- `internal/registry`: packument client on the run's `HttpSender`; `.npmrc` resolution + (scoped registries, the npm-registry-fetch auth-key walk, `${VAR}` expansion failing + only when used); host overrides via `JavaScriptExecutionContextView` + (the `MavenExecutionContextView` pattern). +- `internal/npmlock/NpmLockWriter`: the `json-stringify-nice` emission ported exactly, + including an `Intl`-collator-equivalent key comparator pinned by Node-generated + vectors. Round-trip byte identity over every npm-written fixture is the founding + invariant. + +Failures carry a `Reason`/package/registry/detail structure surfaced three ways: the +existing manifest warning, a warning **on the unchanged lock file itself**, and a +`NodeLockRegenerationFailures` data table for fleet-scale aggregation. On any failure +the manifest edit still applies and the old lock is untouched, deferring to CI's +`npm ci` — the defer-to-CI composition from ADR 0010. + +Two deliberate divergences from a local npm run, both environment-decoupling: +npm-pick-manifest deprioritizes versions whose `engines` exclude the *locally running* +node — the engine ignores engines during selection so results don't depend on the +worker's node version; and lockfileVersion 1/2 locks fail loud rather than being +rewritten wholesale to v3 as a modern npm would. + +### Testing + +Scenario fixtures recorded from real npm 11.17.0 (`src/test/resources/npmlock/`, +regenerable via `record.sh`): before/after manifests, before/after locks, and the full +packuments for every moving package, captured together. Offline tests replay them +through a routed `HttpSender` and assert the engine's output **byte-identical to what +npm produced for the same edit**, plus that nothing escaped to the network. node-semver +conformance runs its transposed fixture corpus; the writer's collation is pinned by +Node-sorted vectors; recipe-level tests run the full scan/edit/regenerate/overlay flow +pure-JVM. + +## Consequences + +- npm lock regeneration works wherever the JVM runs: no node, no npm, no PATH or + credential coupling. Registry access uses the run's `HttpSender` with + host-configurable credentials, the same operational posture as rewrite-maven. +- Coverage is the provable subset; the residual (cascades, placement, workspaces, + Yarn/pnpm/bun) still shells out or defers to CI, now with structured, aggregatable + failure data that will size the next phase (ADR 0010's sizing-before-building + sequence). +- Yarn Berry can never be fully native: its lock `checksum` hashes the zip archive Yarn + re-packs from the tarball, not the registry artifact. Any Berry strategy is a separate + decision. +- We own a semver port, a registry client, and an emitter that track npm. The tracked + surfaces are small and slow-moving, and the fixture corpus pins them per npm version — + the same maintenance posture as rewrite-python's engines. + +## Addendum: behavior changes surfaced in review + +- The deleted shell-out ran npm with `--legacy-peer-deps`, tolerating peer conflicts + (lagging third-party libraries during major framework bumps). The native engine + enforces peers strictly and defers those edits to CI — a coverage regression the + failures table will quantify. +- npm's environment-variable configuration (`npm_config_registry`, `NPM_CONFIG_*`, + `npm_config_//host/:_authToken`) is not consulted: registry discovery reads only the + captured `.npmrc` files (with `${VAR}` expansion) and + `JavaScriptExecutionContextView`. Hosts injecting registries via environment + variables must configure the view instead. diff --git a/rewrite-javascript/build.gradle.kts b/rewrite-javascript/build.gradle.kts index 44679f5fa09..7a21414c647 100644 --- a/rewrite-javascript/build.gradle.kts +++ b/rewrite-javascript/build.gradle.kts @@ -331,6 +331,9 @@ val generateTestClasspath by tasks.registering { extensions.configure { header = file("${rootProject.projectDir}/gradle/msalLicenseHeader.txt") exclude("**/rewrite-javascript-version.txt") + // Recorded npm registry/lock fixtures and conformance corpora must stay byte-exact. + exclude("**/npmlock/**") + exclude("**/npm-semver/**") // includePatterns.addAll( // listOf("**/*.ts") // ) diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/AddDependency.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/AddDependency.java index 306e431b0f1..bf9591c1f34 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/AddDependency.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/AddDependency.java @@ -22,6 +22,7 @@ import org.openrewrite.javascript.internal.LockFileRegeneration; import org.openrewrite.javascript.internal.PackageJsonHelper; import org.openrewrite.javascript.marker.NodeResolutionResult; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import org.openrewrite.javascript.marker.NodeResolutionResult.Dependency; import org.openrewrite.json.tree.Json; import org.openrewrite.marker.Markup; @@ -37,6 +38,8 @@ @Value public class AddDependency extends ScanningRecipe { + transient NodeLockRegenerationFailures lockRegenerationFailures = new NodeLockRegenerationFailures(this); + @Option(displayName = "Package name", description = "The name of the npm package to add (e.g., `lodash`, `@types/node`).", example = "lodash") @@ -59,8 +62,9 @@ public class AddDependency extends ScanningRecipe { @Override public String getInstanceNameSuffix() { return String.format("`%s`", packageName); } @Override public String getDescription() { - return "Add an npm dependency to `package.json` and regenerate the lock file by running the " + - "package manager. If the dependency already exists in any scope, the recipe is a no-op. " + + return "Add an npm dependency to `package.json` and regenerate the lock file (natively for npm, " + + "by running the package manager otherwise). " + + "If the dependency already exists in any scope, the recipe is a no-op. " + "Not safe to use as a precondition: invokes the package manager and publishes per-project " + "state shared with other dependency recipes."; } @@ -78,6 +82,7 @@ static class ProjectState { @Nullable Map configFiles; @Nullable SourceFile modifiedPackageJson; LockFileRegeneration.@Nullable Result regenResult; + boolean failureRecorded; } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @@ -96,7 +101,9 @@ public TreeVisitor getScanner(Accumulator acc) { if (sf instanceof Json.Document || sf instanceof Yaml.Documents || sf instanceof PlainText) { Path packagePath = PackageJsonHelper.correspondingPackageJsonPath(p); ProjectState ps = acc.projects.computeIfAbsent(packagePath, k -> new ProjectState()); - ps.capturedLockContent = sf.printAll(); + if (ps.capturedLockContent == null) { + ps.capturedLockContent = sf.printAll(); + } acc.lockToPackage.put(p, packagePath); } return tree; @@ -139,7 +146,7 @@ public TreeVisitor getVisitor(Accumulator acc) { ProjectState ps = acc.projects.get(p); if (ps != null && ps.capturedPackageJson != null) { if (matchesAdd(sf)) { - ensureComputed(ps, sf); + ensureComputed(ps, sf, ctx); } if (ps.modifiedPackageJson != null) { SourceFile out = ps.modifiedPackageJson; @@ -160,7 +167,7 @@ public TreeVisitor getVisitor(Accumulator acc) { SourceFile pkg = PackageJsonHelper.getLiveTree(ctx, packagePath); if (pkg == null) pkg = lockPs.capturedPackageJson; if (pkg != null && matchesAdd(pkg)) { - ensureComputed(lockPs, pkg); + ensureComputed(lockPs, pkg, ctx); if (lockPs.modifiedPackageJson != null) { PackageJsonHelper.putLiveTree(ctx, packagePath, lockPs.modifiedPackageJson); } @@ -169,16 +176,24 @@ public TreeVisitor getVisitor(Accumulator acc) { if (lockPs.regenResult != null && lockPs.regenResult.isSuccess()) { return PackageJsonHelper.reparseLock(sf, lockPs.regenResult.getLockFileContent()); } + if (lockPs.regenResult != null && !lockPs.regenResult.isSuccess() && !lockPs.failureRecorded) { + lockPs.failureRecorded = true; + LockFileRegeneration.insertFailureRow(ctx, lockRegenerationFailures, p, lockPs.regenResult, + packageName); + return Markup.warn(sf, new RuntimeException( + "lock regeneration failed: " + lockPs.regenResult.getErrorMessage())); + } return tree; } - private void ensureComputed(ProjectState ps, SourceFile pkg) { + private void ensureComputed(ProjectState ps, SourceFile pkg, ExecutionContext ctx) { if (ps.modifiedPackageJson != null) return; PackageJsonHelper.EditAndRegenerateResult r = PackageJsonHelper.editAndRegenerate( pkg, doc -> PackageJsonHelper.addDependency(doc, packageName, version, targetScope()), ps.capturedLockContent, - ps.configFiles); + ps.configFiles, + ctx); if (r.isChanged()) { ps.modifiedPackageJson = r.getModifiedPackageJson(); ps.regenResult = r.getRegenResult(); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/ChangeDependency.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/ChangeDependency.java index 83e09e74ded..42a50df38f4 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/ChangeDependency.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/ChangeDependency.java @@ -22,6 +22,7 @@ import org.openrewrite.javascript.internal.LockFileRegeneration; import org.openrewrite.javascript.internal.PackageJsonHelper; import org.openrewrite.javascript.marker.NodeResolutionResult; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import org.openrewrite.javascript.marker.NodeResolutionResult.Dependency; import org.openrewrite.json.tree.Json; import org.openrewrite.marker.Markup; @@ -37,6 +38,8 @@ @Value public class ChangeDependency extends ScanningRecipe { + transient NodeLockRegenerationFailures lockRegenerationFailures = new NodeLockRegenerationFailures(this); + @Option(displayName = "Old package name", description = "The current name of the npm package to rename.", example = "lodash") @@ -67,7 +70,8 @@ public class ChangeDependency extends ScanningRecipe configFiles; @Nullable SourceFile modifiedPackageJson; LockFileRegeneration.@Nullable Result regenResult; + boolean failureRecorded; } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @@ -101,7 +106,9 @@ public TreeVisitor getScanner(Accumulator acc) { if (sf instanceof Json.Document || sf instanceof Yaml.Documents || sf instanceof PlainText) { Path packagePath = PackageJsonHelper.correspondingPackageJsonPath(p); ProjectState ps = acc.projects.computeIfAbsent(packagePath, k -> new ProjectState()); - ps.capturedLockContent = sf.printAll(); + if (ps.capturedLockContent == null) { + ps.capturedLockContent = sf.printAll(); + } acc.lockToPackage.put(p, packagePath); } return tree; @@ -158,7 +165,7 @@ public TreeVisitor getVisitor(Accumulator acc) { ProjectState ps = acc.projects.get(p); if (ps != null && ps.capturedPackageJson != null) { if (matchesChange(sf)) { - ensureComputed(ps, sf); + ensureComputed(ps, sf, ctx); } if (ps.modifiedPackageJson != null) { SourceFile out = ps.modifiedPackageJson; @@ -179,7 +186,7 @@ public TreeVisitor getVisitor(Accumulator acc) { SourceFile pkg = PackageJsonHelper.getLiveTree(ctx, packagePath); if (pkg == null) pkg = lockPs.capturedPackageJson; if (pkg != null && matchesChange(pkg)) { - ensureComputed(lockPs, pkg); + ensureComputed(lockPs, pkg, ctx); if (lockPs.modifiedPackageJson != null) { PackageJsonHelper.putLiveTree(ctx, packagePath, lockPs.modifiedPackageJson); } @@ -188,16 +195,24 @@ public TreeVisitor getVisitor(Accumulator acc) { if (lockPs.regenResult != null && lockPs.regenResult.isSuccess()) { return PackageJsonHelper.reparseLock(sf, lockPs.regenResult.getLockFileContent()); } + if (lockPs.regenResult != null && !lockPs.regenResult.isSuccess() && !lockPs.failureRecorded) { + lockPs.failureRecorded = true; + LockFileRegeneration.insertFailureRow(ctx, lockRegenerationFailures, p, lockPs.regenResult, + oldPackageName); + return Markup.warn(sf, new RuntimeException( + "lock regeneration failed: " + lockPs.regenResult.getErrorMessage())); + } return tree; } - private void ensureComputed(ProjectState ps, SourceFile pkg) { + private void ensureComputed(ProjectState ps, SourceFile pkg, ExecutionContext ctx) { if (ps.modifiedPackageJson != null) return; PackageJsonHelper.EditAndRegenerateResult r = PackageJsonHelper.editAndRegenerate( pkg, doc -> PackageJsonHelper.changeDependency(doc, oldPackageName, newPackageName, newVersion, scope), ps.capturedLockContent, - ps.configFiles); + ps.configFiles, + ctx); if (r.isChanged()) { ps.modifiedPackageJson = r.getModifiedPackageJson(); ps.regenResult = r.getRegenResult(); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptExecutionContextView.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptExecutionContextView.java new file mode 100644 index 00000000000..77ac401be92 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptExecutionContextView.java @@ -0,0 +1,88 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript; + +import org.openrewrite.DelegatingExecutionContext; +import org.openrewrite.ExecutionContext; +import org.jspecify.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +import static java.util.Collections.emptyList; + +/** + * JavaScript-ecosystem configuration carried on the {@link ExecutionContext}, + * following the {@code MavenExecutionContextView} pattern. Hosts embedding + * OpenRewrite use this to point npm dependency recipes at private registries + * and to supply credentials, instead of relying on {@code .npmrc} files + * captured from the repository. + */ +public class JavaScriptExecutionContextView extends DelegatingExecutionContext { + private static final String NPM_DEFAULT_REGISTRY = "org.openrewrite.javascript.npmDefaultRegistry"; + private static final String NPM_SCOPED_REGISTRIES = "org.openrewrite.javascript.npmScopedRegistries"; + private static final String NPM_REGISTRY_CREDENTIALS = "org.openrewrite.javascript.npmRegistryCredentials"; + + public JavaScriptExecutionContextView(ExecutionContext delegate) { + super(delegate); + } + + public static JavaScriptExecutionContextView view(ExecutionContext ctx) { + if (ctx instanceof JavaScriptExecutionContextView) { + return (JavaScriptExecutionContextView) ctx; + } + return new JavaScriptExecutionContextView(ctx); + } + + /** + * Override the default npm registry for all packages, taking precedence over any + * {@code registry=} entry in the project's {@code .npmrc}. + */ + public JavaScriptExecutionContextView setNpmDefaultRegistry(@Nullable String registryUrl) { + putMessage(NPM_DEFAULT_REGISTRY, registryUrl); + return this; + } + + public @Nullable String getNpmDefaultRegistry() { + return getMessage(NPM_DEFAULT_REGISTRY); + } + + /** + * Override registries per scope (e.g. {@code "@myorg" -> "https://npm.example.com/"}), + * taking precedence over {@code @scope:registry=} entries in the project's {@code .npmrc}. + */ + public JavaScriptExecutionContextView setNpmScopedRegistries(@Nullable Map scopeToRegistryUrl) { + putMessage(NPM_SCOPED_REGISTRIES, scopeToRegistryUrl); + return this; + } + + public @Nullable Map getNpmScopedRegistries() { + return getMessage(NPM_SCOPED_REGISTRIES); + } + + /** + * Credentials merged into discovered registries by hostname, taking precedence + * over credentials found in {@code .npmrc} files. + */ + public JavaScriptExecutionContextView setRegistryCredentials(List credentials) { + putMessage(NPM_REGISTRY_CREDENTIALS, credentials); + return this; + } + + public List getRegistryCredentials() { + return getMessage(NPM_REGISTRY_CREDENTIALS, emptyList()); + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/NpmRegistryCredentials.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/NpmRegistryCredentials.java new file mode 100644 index 00000000000..b2d868b589c --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/NpmRegistryCredentials.java @@ -0,0 +1,41 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript; + +import lombok.Value; +import org.jspecify.annotations.Nullable; + +/** + * Credentials for an npm registry host, supplied by the host application via + * {@link JavaScriptExecutionContextView#setRegistryCredentials}. Matched to + * registries by hostname, the same pattern as Maven's settings credentials. + * Either a bearer {@code token} or a {@code username}/{@code password} pair. + */ +@Value +public class NpmRegistryCredentials { + String host; + @Nullable String token; + @Nullable String username; + @Nullable String password; + + public static NpmRegistryCredentials token(String host, String token) { + return new NpmRegistryCredentials(host, token, null, null); + } + + public static NpmRegistryCredentials usernamePassword(String host, String username, String password) { + return new NpmRegistryCredentials(host, null, username, password); + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/RemoveDependency.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/RemoveDependency.java index ead7cac084c..54cec57ef1c 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/RemoveDependency.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/RemoveDependency.java @@ -22,6 +22,7 @@ import org.openrewrite.javascript.internal.LockFileRegeneration; import org.openrewrite.javascript.internal.PackageJsonHelper; import org.openrewrite.javascript.marker.NodeResolutionResult; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import org.openrewrite.javascript.marker.NodeResolutionResult.Dependency; import org.openrewrite.json.tree.Json; import org.openrewrite.marker.Markup; @@ -40,6 +41,8 @@ @Value public class RemoveDependency extends ScanningRecipe { + transient NodeLockRegenerationFailures lockRegenerationFailures = new NodeLockRegenerationFailures(this); + @Option(displayName = "Package name", description = "The name of the npm package to remove (e.g., `lodash`, `@types/node`).", example = "lodash") @@ -73,6 +76,7 @@ static class ProjectState { @Nullable SourceFile modifiedPackageJson; @Nullable Set scopesContainingPackage; LockFileRegeneration.@Nullable Result regenResult; + boolean failureRecorded; } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @@ -91,7 +95,9 @@ public TreeVisitor getScanner(Accumulator acc) { if (sf instanceof Json.Document || sf instanceof Yaml.Documents || sf instanceof PlainText) { Path packagePath = PackageJsonHelper.correspondingPackageJsonPath(p); ProjectState ps = acc.projects.computeIfAbsent(packagePath, k -> new ProjectState()); - ps.capturedLockContent = sf.printAll(); + if (ps.capturedLockContent == null) { + ps.capturedLockContent = sf.printAll(); + } acc.lockToPackage.put(p, packagePath); } return tree; @@ -137,7 +143,7 @@ public TreeVisitor getVisitor(Accumulator acc) { ProjectState ps = acc.projects.get(p); if (ps != null && ps.capturedPackageJson != null) { if ((ps.scopesContainingPackage = findContainingScopes(sf)) != null) { - ensureComputed(ps, sf); + ensureComputed(ps, sf, ctx); } if (ps.modifiedPackageJson != null) { SourceFile out = ps.modifiedPackageJson; @@ -158,7 +164,7 @@ public TreeVisitor getVisitor(Accumulator acc) { SourceFile pkg = PackageJsonHelper.getLiveTree(ctx, packagePath); if (pkg == null) pkg = lockPs.capturedPackageJson; if (pkg != null && (lockPs.scopesContainingPackage = findContainingScopes(pkg)) != null) { - ensureComputed(lockPs, pkg); + ensureComputed(lockPs, pkg, ctx); if (lockPs.modifiedPackageJson != null) { PackageJsonHelper.putLiveTree(ctx, packagePath, lockPs.modifiedPackageJson); } @@ -167,10 +173,17 @@ public TreeVisitor getVisitor(Accumulator acc) { if (lockPs.regenResult != null && lockPs.regenResult.isSuccess()) { return PackageJsonHelper.reparseLock(sf, lockPs.regenResult.getLockFileContent()); } + if (lockPs.regenResult != null && !lockPs.regenResult.isSuccess() && !lockPs.failureRecorded) { + lockPs.failureRecorded = true; + LockFileRegeneration.insertFailureRow(ctx, lockRegenerationFailures, p, lockPs.regenResult, + packageName); + return Markup.warn(sf, new RuntimeException( + "lock regeneration failed: " + lockPs.regenResult.getErrorMessage())); + } return tree; } - private void ensureComputed(ProjectState ps, SourceFile pkg) { + private void ensureComputed(ProjectState ps, SourceFile pkg, ExecutionContext ctx) { if (ps.modifiedPackageJson != null) return; if (ps.scopesContainingPackage == null) return; Set scopes = ps.scopesContainingPackage; @@ -178,7 +191,8 @@ private void ensureComputed(ProjectState ps, SourceFile pkg) { pkg, doc -> PackageJsonHelper.removeDependency(doc, packageName, scopes), ps.capturedLockContent, - ps.configFiles); + ps.configFiles, + ctx); if (r.isChanged()) { ps.modifiedPackageJson = r.getModifiedPackageJson(); ps.regenResult = r.getRegenResult(); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeDependencyVersion.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeDependencyVersion.java index 281e672e9d0..14d86752dc2 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeDependencyVersion.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeDependencyVersion.java @@ -24,6 +24,7 @@ import org.openrewrite.javascript.internal.PackageJsonHelper; import org.openrewrite.javascript.marker.NodeResolutionResult; import org.openrewrite.javascript.marker.NodeResolutionResult.Dependency; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import org.openrewrite.json.tree.Json; import org.openrewrite.marker.Markup; import org.openrewrite.text.PlainText; @@ -38,6 +39,8 @@ @Value public class UpgradeDependencyVersion extends ScanningRecipe { + transient NodeLockRegenerationFailures lockRegenerationFailures = new NodeLockRegenerationFailures(this); + @Option(displayName = "Package name", description = "Exact package name to match. Mutually exclusive with `packagePattern`; " + "at least one is required.", @@ -61,7 +64,8 @@ public class UpgradeDependencyVersion extends ScanningRecipe matchedDeps; @Nullable SourceFile modifiedPackageJson; LockFileRegeneration.@Nullable Result regenResult; + boolean failureRecorded; } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @@ -108,7 +113,9 @@ public TreeVisitor getScanner(Accumulator acc) { if (sf instanceof Json.Document || sf instanceof Yaml.Documents || sf instanceof PlainText) { Path packagePath = PackageJsonHelper.correspondingPackageJsonPath(p); ProjectState ps = acc.projects.computeIfAbsent(packagePath, k -> new ProjectState()); - ps.capturedLockContent = sf.printAll(); + if (ps.capturedLockContent == null) { + ps.capturedLockContent = sf.printAll(); + } acc.lockToPackage.put(p, packagePath); } return tree; @@ -186,7 +193,7 @@ public TreeVisitor getVisitor(Accumulator acc) { if (liveTree != null) { effectiveSf = liveTree; } - ensureComputed(ps, effectiveSf); + ensureComputed(ps, effectiveSf, ctx); } if (ps.modifiedPackageJson != null) { SourceFile out = ps.modifiedPackageJson; @@ -211,7 +218,7 @@ public TreeVisitor getVisitor(Accumulator acc) { lockPs.matchedDeps = findMatches(pkg); } if (pkg != null && lockPs.matchedDeps != null && !lockPs.matchedDeps.isEmpty()) { - ensureComputed(lockPs, pkg); + ensureComputed(lockPs, pkg, ctx); if (lockPs.modifiedPackageJson != null) { PackageJsonHelper.putLiveTree(ctx, packagePath, lockPs.modifiedPackageJson); } @@ -220,10 +227,17 @@ public TreeVisitor getVisitor(Accumulator acc) { if (lockPs.regenResult != null && lockPs.regenResult.isSuccess()) { return PackageJsonHelper.reparseLock(sf, lockPs.regenResult.getLockFileContent()); } + if (lockPs.regenResult != null && !lockPs.regenResult.isSuccess() && !lockPs.failureRecorded) { + lockPs.failureRecorded = true; + LockFileRegeneration.insertFailureRow(ctx, lockRegenerationFailures, p, lockPs.regenResult, + packageName != null ? packageName : packagePattern); + return Markup.warn(sf, new RuntimeException( + "lock regeneration failed: " + lockPs.regenResult.getErrorMessage())); + } return tree; } - private void ensureComputed(ProjectState ps, SourceFile pkg) { + private void ensureComputed(ProjectState ps, SourceFile pkg, ExecutionContext ctx) { if (ps.modifiedPackageJson != null) return; if (ps.matchedDeps == null || ps.matchedDeps.isEmpty()) return; List matches = ps.matchedDeps; @@ -231,7 +245,8 @@ private void ensureComputed(ProjectState ps, SourceFile pkg) { pkg, doc -> PackageJsonHelper.upgradeVersion(doc, matches, newVersion), ps.capturedLockContent, - ps.configFiles); + ps.configFiles, + ctx); if (r.isChanged()) { ps.modifiedPackageJson = r.getModifiedPackageJson(); ps.regenResult = r.getRegenResult(); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeTransitiveDependencyVersion.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeTransitiveDependencyVersion.java index 6eeb8bb9f18..113f484f548 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeTransitiveDependencyVersion.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/UpgradeTransitiveDependencyVersion.java @@ -24,6 +24,7 @@ import org.openrewrite.javascript.internal.PackageJsonHelper; import org.openrewrite.javascript.internal.PackageJsonOverrides; import org.openrewrite.javascript.marker.NodeResolutionResult; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import org.openrewrite.json.tree.Json; import org.openrewrite.marker.Markup; import org.openrewrite.text.PlainText; @@ -38,6 +39,8 @@ @Value public class UpgradeTransitiveDependencyVersion extends ScanningRecipe { + transient NodeLockRegenerationFailures lockRegenerationFailures = new NodeLockRegenerationFailures(this); + @Option(displayName = "Package name", description = "The name of the transitive npm dependency to upgrade.", example = "lodash") @@ -78,6 +81,7 @@ static class ProjectState { @Nullable Map configFiles; @Nullable SourceFile modifiedPackageJson; LockFileRegeneration.@Nullable Result regenResult; + boolean failureRecorded; } @Override public Accumulator getInitialValue(ExecutionContext ctx) { return new Accumulator(); } @@ -96,7 +100,9 @@ public TreeVisitor getScanner(Accumulator acc) { if (sf instanceof Json.Document || sf instanceof Yaml.Documents || sf instanceof PlainText) { Path packagePath = PackageJsonHelper.correspondingPackageJsonPath(p); ProjectState ps = acc.projects.computeIfAbsent(packagePath, k -> new ProjectState()); - ps.capturedLockContent = sf.printAll(); + if (ps.capturedLockContent == null) { + ps.capturedLockContent = sf.printAll(); + } acc.lockToPackage.put(p, packagePath); } return tree; @@ -130,7 +136,7 @@ public TreeVisitor getVisitor(Accumulator acc) { ProjectState ps = acc.projects.get(p); if (ps != null && ps.capturedPackageJson != null) { if (canApply(sf)) { - ensureComputed(ps, sf); + ensureComputed(ps, sf, ctx); } if (ps.modifiedPackageJson != null) { SourceFile out = ps.modifiedPackageJson; @@ -151,7 +157,7 @@ public TreeVisitor getVisitor(Accumulator acc) { SourceFile pkg = PackageJsonHelper.getLiveTree(ctx, packagePath); if (pkg == null) pkg = lockPs.capturedPackageJson; if (pkg != null && canApply(pkg)) { - ensureComputed(lockPs, pkg); + ensureComputed(lockPs, pkg, ctx); if (lockPs.modifiedPackageJson != null) { PackageJsonHelper.putLiveTree(ctx, packagePath, lockPs.modifiedPackageJson); } @@ -160,10 +166,17 @@ public TreeVisitor getVisitor(Accumulator acc) { if (lockPs.regenResult != null && lockPs.regenResult.isSuccess()) { return PackageJsonHelper.reparseLock(sf, lockPs.regenResult.getLockFileContent()); } + if (lockPs.regenResult != null && !lockPs.regenResult.isSuccess() && !lockPs.failureRecorded) { + lockPs.failureRecorded = true; + LockFileRegeneration.insertFailureRow(ctx, lockRegenerationFailures, p, lockPs.regenResult, + packageName); + return Markup.warn(sf, new RuntimeException( + "lock regeneration failed: " + lockPs.regenResult.getErrorMessage())); + } return tree; } - private void ensureComputed(ProjectState ps, SourceFile pkg) { + private void ensureComputed(ProjectState ps, SourceFile pkg, ExecutionContext ctx) { if (ps.modifiedPackageJson != null) return; NodeResolutionResult marker = pkg.getMarkers().findFirst(NodeResolutionResult.class).orElse(null); if (marker == null || marker.getPackageManager() == null) return; @@ -176,7 +189,8 @@ private void ensureComputed(ProjectState ps, SourceFile pkg) { pkg, doc -> PackageJsonHelper.upgradeTransitive(doc, pm, packageName, newVersion, parsedPath), ps.capturedLockContent, - ps.configFiles); + ps.configFiles, + ctx); if (r.isChanged()) { ps.modifiedPackageJson = r.getModifiedPackageJson(); ps.regenResult = r.getRegenResult(); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/LockFileRegeneration.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/LockFileRegeneration.java index f8d2134c552..0d3f749a2e4 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/LockFileRegeneration.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/LockFileRegeneration.java @@ -17,7 +17,10 @@ import lombok.Value; import org.jspecify.annotations.Nullable; +import org.openrewrite.ExecutionContext; +import org.openrewrite.javascript.internal.npmlock.NpmLockEngine; import org.openrewrite.javascript.marker.NodeResolutionResult.PackageManager; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -29,34 +32,36 @@ import java.util.stream.Stream; /** - * Regenerate a JavaScript project's lock file by running the package manager - * in a temp directory seeded with the package.json and (optionally) the existing - * lock file plus config files such as {@code .npmrc}. + * Regenerate a JavaScript project's lock file after a {@code package.json} edit. * - *

Pre-configured instances are provided for each - * {@link PackageManager}; {@link #forPackageManager(PackageManager)} dispatches - * to the right one. The install args are preserved verbatim from the TypeScript - * implementation in {@code rewrite-javascript/rewrite/src/javascript/package-manager.ts}. + *

For npm ({@code package-lock.json}) regeneration is native: a Java engine + * consults the project's registry over HTTP and surgically updates the lock, + * with no package manager execution — see {@link NpmLockEngine}. For the other + * package managers regeneration still runs the package manager in a temp + * directory seeded with the {@code package.json}, the existing lock file, and + * config files such as {@code .npmrc}. + * + *

Failures are structured ({@link Failure}) so recipes can aggregate them in + * the {@link NodeLockRegenerationFailures} data table; on any failure the old + * lock is left untouched. */ -public final class LockFileRegeneration { +public abstract class LockFileRegeneration { - public static final LockFileRegeneration NPM = new LockFileRegeneration( - PackageManagerExecutor.NPM, "package-lock.json", - new String[]{"install", "--package-lock-only", "--ignore-scripts", "--legacy-peer-deps"}); + public static final LockFileRegeneration NPM = new NativeNpm(); - public static final LockFileRegeneration YARN_CLASSIC = new LockFileRegeneration( + public static final LockFileRegeneration YARN_CLASSIC = new ShellOut( PackageManagerExecutor.YARN, "yarn.lock", new String[]{"install", "--ignore-scripts"}); - public static final LockFileRegeneration YARN_BERRY = new LockFileRegeneration( + public static final LockFileRegeneration YARN_BERRY = new ShellOut( PackageManagerExecutor.YARN, "yarn.lock", new String[]{"install", "--mode", "skip-build"}); - public static final LockFileRegeneration PNPM = new LockFileRegeneration( + public static final LockFileRegeneration PNPM = new ShellOut( PackageManagerExecutor.PNPM, "pnpm-lock.yaml", new String[]{"install", "--lockfile-only", "--ignore-scripts", "--no-strict-peer-dependencies"}); - public static final LockFileRegeneration BUN = new LockFileRegeneration( + public static final LockFileRegeneration BUN = new ShellOut( PackageManagerExecutor.BUN, "bun.lock", new String[]{"install", "--ignore-scripts"}); @@ -74,124 +79,213 @@ public final class LockFileRegeneration { } } + public enum Reason { + REGISTRY_UNREACHABLE, + REGISTRY_CONFIG, + AUTH_FAILED, + PACKAGE_NOT_FOUND, + VERSION_NOT_FOUND, + INTEGRITY_UNAVAILABLE, + RESOLUTION_REQUIRED, + UNSUPPORTED_ENTRY_TYPE, + UNSUPPORTED_LOCK_VERSION, + MALFORMED_MANIFEST, + MALFORMED_LOCK, + PACKAGE_MANAGER_UNAVAILABLE, + PACKAGE_MANAGER_FAILED + } + + @Value + public static class Failure { + Reason reason; + @Nullable String packageName; + @Nullable String registryUrl; + String detail; + } + @Value public static class Result { boolean success; @Nullable String lockFileContent; - @Nullable String errorMessage; + @Nullable Failure failure; public static Result success(String lockFileContent) { return new Result(true, lockFileContent, null); } - public static Result failure(String errorMessage) { - return new Result(false, null, errorMessage); + public static Result failure(Failure failure) { + return new Result(false, null, failure); } - } - private final PackageManagerExecutor executor; - private final String lockFile; - private final String[] installArgs; + public static Result failure(Reason reason, String detail) { + return failure(new Failure(reason, null, null, detail)); + } - private LockFileRegeneration(PackageManagerExecutor executor, String lockFile, String[] installArgs) { - this.executor = executor; - this.lockFile = lockFile; - this.installArgs = installArgs; + public @Nullable String getErrorMessage() { + return failure == null ? null : failure.getReason() + ": " + failure.getDetail(); + } } - public String getLockFile() { - return lockFile; + /** + * Record a failed regeneration in the data table, once per project. The + * fallback package name attributes rows whose failure carries no package of + * its own (shell-out failures, unreachable registries) to the package the + * recipe targeted. + */ + public static void insertFailureRow(ExecutionContext ctx, NodeLockRegenerationFailures table, + Path lockPath, Result result, @Nullable String fallbackPackageName) { + Failure failure = result.getFailure(); + if (failure == null) { + failure = new Failure(Reason.PACKAGE_MANAGER_FAILED, null, null, ""); + } + table.insertRow(ctx, new NodeLockRegenerationFailures.Row( + lockPath.toString(), + failure.getPackageName() != null ? failure.getPackageName() : fallbackPackageName, + failure.getReason().toString(), + failure.getDetail())); } - public Result regenerate(String packageJsonContent) { - return regenerate(packageJsonContent, null, null); - } + public abstract String getLockFile(); - public Result regenerate(String packageJsonContent, @Nullable String existingLockContent) { - return regenerate(packageJsonContent, existingLockContent, null); + /** + * Regenerate the lock file for an edited {@code package.json}. + * + * @param packageJsonContent the manifest after the recipe's edit + * @param originalPackageJsonContent the manifest before the edit, when available; + * used to detect which {@code overrides} the + * recipe changed (dependency edits are diffed + * against the lock itself, which records them) + * @param existingLockContent the current lock file content + * @param configFiles extra config, typically {@code {".npmrc": "..."}} + */ + public abstract Result regenerate(String packageJsonContent, + @Nullable String originalPackageJsonContent, + @Nullable String existingLockContent, + @Nullable Map configFiles, + ExecutionContext ctx); + + private static class NativeNpm extends LockFileRegeneration { + @Override + public String getLockFile() { + return "package-lock.json"; + } + + @Override + public Result regenerate(String packageJsonContent, + @Nullable String originalPackageJsonContent, + @Nullable String existingLockContent, + @Nullable Map configFiles, + ExecutionContext ctx) { + if (existingLockContent == null) { + return Result.failure(Reason.RESOLUTION_REQUIRED, + "Creating a lock file from scratch requires full resolution; only existing " + + "package-lock.json files are regenerated natively"); + } + String npmrc = configFiles == null ? null : configFiles.get(".npmrc"); + return NpmLockEngine.regenerate(packageJsonContent, originalPackageJsonContent, + existingLockContent, npmrc, ctx); + } } /** - * Regenerate the lock file. Optional inputs: - *

    - *
  • {@code existingLockContent} — when present, seeded into the temp dir so - * the package manager performs a minimal update rather than a full - * re-resolve.
  • - *
  • {@code configFiles} — extra files to seed into the temp dir - * (typically {@code {".npmrc": "..."}}).
  • - *
+ * The pre-native mechanism, retained for the package managers without a native + * engine yet. The install args are preserved verbatim from the TypeScript + * implementation in {@code rewrite-javascript/rewrite/src/javascript/package-manager.ts}. */ - public Result regenerate(String packageJsonContent, - @Nullable String existingLockContent, - @Nullable Map configFiles) { - String executablePath = executor.find(); - if (executablePath == null) { - return Result.failure(executor.getName() + " is not installed or not on PATH"); - } + private static class ShellOut extends LockFileRegeneration { + private final PackageManagerExecutor executor; + private final String lockFile; + private final String[] installArgs; - Path tempDir = null; - try { - tempDir = Files.createTempDirectory("openrewrite-pm-lock-"); + private ShellOut(PackageManagerExecutor executor, String lockFile, String[] installArgs) { + this.executor = executor; + this.lockFile = lockFile; + this.installArgs = installArgs; + } - Files.write(tempDir.resolve("package.json"), - packageJsonContent.getBytes(StandardCharsets.UTF_8)); + @Override + public String getLockFile() { + return lockFile; + } - if (existingLockContent != null) { - Files.write(tempDir.resolve(lockFile), - existingLockContent.getBytes(StandardCharsets.UTF_8)); + @Override + public Result regenerate(String packageJsonContent, + @Nullable String originalPackageJsonContent, + @Nullable String existingLockContent, + @Nullable Map configFiles, + ExecutionContext ctx) { + String executablePath = executor.find(); + if (executablePath == null) { + return Result.failure(Reason.PACKAGE_MANAGER_UNAVAILABLE, + executor.getName() + " is not installed or not on PATH"); } - if (configFiles != null) { - for (Map.Entry entry : configFiles.entrySet()) { - Files.write(tempDir.resolve(entry.getKey()), - entry.getValue().getBytes(StandardCharsets.UTF_8)); + + Path tempDir = null; + try { + tempDir = Files.createTempDirectory("openrewrite-pm-lock-"); + + Files.write(tempDir.resolve("package.json"), + packageJsonContent.getBytes(StandardCharsets.UTF_8)); + + if (existingLockContent != null) { + Files.write(tempDir.resolve(lockFile), + existingLockContent.getBytes(StandardCharsets.UTF_8)); + } + if (configFiles != null) { + for (Map.Entry entry : configFiles.entrySet()) { + Files.write(tempDir.resolve(entry.getKey()), + entry.getValue().getBytes(StandardCharsets.UTF_8)); + } } - } - PackageManagerExecutor.RunResult runResult = executor.run(tempDir, executablePath, - Collections.emptyMap(), installArgs); - if (!runResult.isSuccess()) { - String stderr = runResult.getStderr(); - if (stderr != null && stderr.length() > 2000) { - stderr = stderr.substring(0, 2000) + "..."; + PackageManagerExecutor.RunResult runResult = executor.run(tempDir, executablePath, + Collections.emptyMap(), installArgs); + if (!runResult.isSuccess()) { + String stderr = runResult.getStderr(); + if (stderr != null && stderr.length() > 2000) { + stderr = stderr.substring(0, 2000) + "..."; + } + return Result.failure(Reason.PACKAGE_MANAGER_FAILED, executor.getName() + + " install failed (exit " + runResult.getExitCode() + "): " + stderr); } - return Result.failure(executor.getName() + " install failed (exit " - + runResult.getExitCode() + "): " + stderr); - } - Path lockPath = tempDir.resolve(lockFile); - if (!Files.exists(lockPath)) { - return Result.failure(executor.getName() + " install did not produce a " - + lockFile + " file"); - } - return Result.success(new String(Files.readAllBytes(lockPath), StandardCharsets.UTF_8)); - - } catch (IOException e) { - return Result.failure("IO error during " + executor.getName() + " install: " + e.getMessage()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return Result.failure(executor.getName() + " install was interrupted"); - } finally { - if (tempDir != null) { - cleanupDirectory(tempDir); + Path lockPath = tempDir.resolve(lockFile); + if (!Files.exists(lockPath)) { + return Result.failure(Reason.PACKAGE_MANAGER_FAILED, + executor.getName() + " install did not produce a " + lockFile + " file"); + } + return Result.success(new String(Files.readAllBytes(lockPath), StandardCharsets.UTF_8)); + + } catch (IOException e) { + return Result.failure(Reason.PACKAGE_MANAGER_FAILED, + "IO error during " + executor.getName() + " install: " + e.getMessage()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return Result.failure(Reason.PACKAGE_MANAGER_FAILED, + executor.getName() + " install was interrupted"); + } finally { + if (tempDir != null) { + cleanupDirectory(tempDir); + } } } - } - private static void cleanupDirectory(Path dir) { - if (!Files.exists(dir)) { - return; - } - try (Stream walk = Files.walk(dir)) { - walk.sorted(Comparator.reverseOrder()) - .forEach(path -> { - try { - Files.delete(path); - } catch (IOException e) { - // Ignore - } - }); - } catch (IOException e) { - // Ignore + private static void cleanupDirectory(Path dir) { + if (!Files.exists(dir)) { + return; + } + try (Stream walk = Files.walk(dir)) { + walk.sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + // best-effort temp-dir cleanup + } + }); + } catch (IOException e) { + // best-effort temp-dir cleanup + } } } } diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/PackageJsonHelper.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/PackageJsonHelper.java index 9d8e1cd21af..2f9db2ff6b4 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/PackageJsonHelper.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/PackageJsonHelper.java @@ -745,7 +745,8 @@ public static EditAndRegenerateResult editAndRegenerate( SourceFile packageJson, java.util.function.Function editFn, @Nullable String capturedLockContent, - @Nullable Map configFiles) { + @Nullable Map configFiles, + ExecutionContext ctx) { if (!(packageJson instanceof Json.Document)) { return EditAndRegenerateResult.unchanged(); } @@ -756,7 +757,7 @@ public static EditAndRegenerateResult editAndRegenerate( } SourceFile refreshed = refreshMarker(after); LockFileRegeneration.Result regen = capturedLockContent == null ? null - : regenerateLockContent(refreshed, capturedLockContent, configFiles); + : regenerateLockContent(refreshed, before.printAll(), capturedLockContent, configFiles, ctx); SourceFile finalSource = refreshed; if (regen != null && regen.isSuccess()) { NodeResolutionResult marker = refreshed.getMarkers() @@ -776,8 +777,10 @@ public static EditAndRegenerateResult editAndRegenerate( public static LockFileRegeneration.@Nullable Result regenerateLockContent( SourceFile packageJson, + @Nullable String originalPackageJsonContent, @Nullable String capturedLockContent, - @Nullable Map configFiles) { + @Nullable Map configFiles, + ExecutionContext ctx) { NodeResolutionResult marker = packageJson.getMarkers() .findFirst(NodeResolutionResult.class).orElse(null); if (marker == null || marker.getPackageManager() == null) { @@ -787,6 +790,7 @@ public static EditAndRegenerateResult editAndRegenerate( if (regen == null) { return null; } - return regen.regenerate(packageJson.printAll(), capturedLockContent, configFiles); + return regen.regenerate(packageJson.printAll(), originalPackageJsonContent, + capturedLockContent, configFiles, ctx); } } diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/EngineFailure.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/EngineFailure.java new file mode 100644 index 00000000000..8cdeaccca57 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/EngineFailure.java @@ -0,0 +1,35 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import lombok.Getter; +import org.jspecify.annotations.Nullable; +import org.openrewrite.javascript.internal.LockFileRegeneration.Failure; +import org.openrewrite.javascript.internal.LockFileRegeneration.Reason; + +/** + * Carries a structured {@link Failure} out of the engine's deep call stack; the + * engine entry point converts it to a failed {@code Result}, never a thrown error. + */ +@Getter +class EngineFailure extends RuntimeException { + private final Failure failure; + + EngineFailure(Reason reason, @Nullable String packageName, String detail) { + super(reason + ": " + detail); + this.failure = new Failure(reason, packageName, null, detail); + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngine.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngine.java new file mode 100644 index 00000000000..8b9e9685b14 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngine.java @@ -0,0 +1,676 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.jspecify.annotations.Nullable; +import org.openrewrite.ExecutionContext; +import org.openrewrite.HttpSenderExecutionContextView; +import org.openrewrite.ipc.http.HttpSender; +import org.openrewrite.javascript.internal.LockFileRegeneration.Failure; +import org.openrewrite.javascript.internal.LockFileRegeneration.Reason; +import org.openrewrite.javascript.internal.LockFileRegeneration.Result; +import org.openrewrite.javascript.internal.registry.NpmRegistryClient; +import org.openrewrite.javascript.internal.registry.NpmRegistryConfig; +import org.openrewrite.javascript.internal.registry.NpmRegistryException; +import org.openrewrite.javascript.internal.registry.Packument; +import org.openrewrite.javascript.internal.semver.NpmRange; +import org.openrewrite.javascript.internal.npmlock.NpmLockTree.Edge; +import org.openrewrite.javascript.internal.npmlock.NpmLockTree.Flags; + +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Native {@code package-lock.json} regeneration: applies a recipe's manifest edit to + * the lock without executing npm, consulting the project's registry only for the + * packages the edit actually moves. + * + *

The lock's root {@code ""} entry mirrors the manifest npm last resolved, so + * diffing the edited manifest against it yields the edit set for free. The engine + * handles the provable subset — a version move whose closure stays satisfied by the + * existing tree, removals with an orphan sweep, top-level additions that fit without + * placement conflicts, range edits the current pin already satisfies, and flat + * {@code overrides} retargeting a single copy — and fails loudly with a structured + * {@link Failure} on everything else (cascading placement, peer conflicts, workspace + * locks, non-registry specs, lockfileVersion < 3). On failure the old lock is left + * byte-untouched and the stale pin is caught by {@code npm ci} in CI. + * + *

Dependency flags ({@code dev}/{@code optional}/{@code devOptional}/{@code peer}) + * are recomputed with arborist's own fixed-point algorithm, and applied only where + * the edit changed an entry's color — pre-existing drift elsewhere in the file is + * preserved byte-for-byte, never "fixed" as a side effect. + */ +public final class NpmLockEngine { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private static final String[] DEP_SCOPES = { + "dependencies", "devDependencies", "optionalDependencies", "peerDependencies"}; + + private NpmLockEngine() { + } + + public static Result regenerate(String packageJsonContent, + @Nullable String originalPackageJsonContent, + String lockContent, + @Nullable String npmrcContent, + ExecutionContext ctx) { + try { + return new Run(packageJsonContent, originalPackageJsonContent, lockContent, npmrcContent, ctx).run(); + } catch (EngineFailure e) { + return Result.failure(e.getFailure()); + } catch (NpmRegistryException e) { + return Result.failure(new Failure(mapRegistryReason(e.getReason()), null, e.getRegistryUrl(), e.getMessage())); + } + } + + private static Reason mapRegistryReason(NpmRegistryException.Reason reason) { + switch (reason) { + case AUTH_FAILED: + return Reason.AUTH_FAILED; + case NOT_FOUND: + return Reason.PACKAGE_NOT_FOUND; + case CONFIG: + return Reason.REGISTRY_CONFIG; + default: + return Reason.REGISTRY_UNREACHABLE; + } + } + + private static class Run { + private final ObjectNode manifest; + private final @Nullable ObjectNode originalManifest; + private final String lockContent; + private final String indent; + private final String eol; + private final ObjectNode lock; + private final ObjectNode packages; + private final NpmLockTree tree; + private final NpmRegistryClient registry; + private final Map overrides; + private final Set rebuiltPaths = new LinkedHashSet<>(); + + Run(String packageJsonContent, @Nullable String originalPackageJsonContent, + String lockContent, @Nullable String npmrcContent, ExecutionContext ctx) { + this.manifest = parseObject(packageJsonContent, Reason.MALFORMED_MANIFEST, "package.json"); + this.originalManifest = originalPackageJsonContent == null ? null + : parseObject(originalPackageJsonContent, Reason.MALFORMED_MANIFEST, "original package.json"); + this.lockContent = lockContent; + this.indent = NpmLockWriter.detectIndent(lockContent); + this.eol = NpmLockWriter.detectEol(lockContent); + this.lock = parseObject(lockContent, Reason.MALFORMED_LOCK, "package-lock.json"); + JsonNode packagesNode = lock.get("packages"); + if (!(packagesNode instanceof ObjectNode)) { + throw new EngineFailure(Reason.MALFORMED_LOCK, null, "lock file is missing the `packages` map"); + } + this.packages = (ObjectNode) packagesNode; + this.tree = new NpmLockTree(packages); + HttpSender http = HttpSenderExecutionContextView.view(ctx).getHttpSender(); + this.registry = new NpmRegistryClient(http, + new NpmRegistryConfig(NpmRegistryConfig.parseNpmrc(npmrcContent), ctx)); + this.overrides = parseOverrides(); + } + + private static ObjectNode parseObject(String content, Reason reason, String what) { + try { + JsonNode node = MAPPER.readTree(content); + if (node instanceof ObjectNode) { + return (ObjectNode) node; + } + throw new EngineFailure(reason, null, what + " is not a JSON object"); + } catch (EngineFailure e) { + throw e; + } catch (Exception e) { + throw new EngineFailure(reason, null, "malformed " + what + ": " + e.getMessage()); + } + } + + Result run() { + guardSupported(); + + Map oldFlags = tree.calcDepFlags(); + Set editedNames = editedNames(); + applyOverrideEdits(); + + for (String name : editedNames) { + applyDependencyEdit(name); + } + syncRootEntry(editedNames); + syncTopLevel(); + + Map newFlags = tree.calcDepFlags(); + sweepOrphans(oldFlags, newFlags); + reconcileFlags(oldFlags, newFlags); + + String out = NpmLockWriter.write(lock, indent, eol); + return Result.success(out); + } + + private void guardSupported() { + int lockfileVersion = lock.path("lockfileVersion").asInt(-1); + if (lockfileVersion != 3) { + throw new EngineFailure(Reason.UNSUPPORTED_LOCK_VERSION, null, + "lockfileVersion " + (lockfileVersion < 0 ? "(absent)" : lockfileVersion) + + " is not supported natively; only v3 (npm 9+) locks are. A CI `npm install` " + + "will upgrade the lock format"); + } + if (manifest.has("workspaces") || root().has("workspaces")) { + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, null, + "workspace projects resolve across multiple manifests"); + } + for (String path : tree.paths()) { + ObjectNode entry = tree.entry(path); + if (entry != null && entry.path("link").asBoolean(false)) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, NpmLockTree.nameOf(path), + "symlinked (`link: true`) entries require filesystem resolution"); + } + } + String roundTrip = NpmLockWriter.write(lock, indent, eol); + if (!roundTrip.equals(lockContent)) { + throw new EngineFailure(Reason.MALFORMED_LOCK, null, + "lock file is not in canonical npm form (hand-edited or written by an older npm?); " + + "refusing to rewrite it wholesale"); + } + } + + private ObjectNode root() { + ObjectNode root = tree.entry(""); + if (root == null) { + throw new EngineFailure(Reason.MALFORMED_LOCK, null, "lock file has no root \"\" entry"); + } + return root; + } + + /** + * Names whose manifest declaration disagrees with the lock's recorded root + * entry. The lock root is the baseline (not the pre-edit manifest) because + * regeneration always starts from the lock captured at scan time: a prior + * recipe's edit in the same run must be reconciled too, or it would be lost + * when this recipe's output replaces the lock. + */ + private Set editedNames() { + ObjectNode baseline = root(); + Set names = new LinkedHashSet<>(); + for (String scope : DEP_SCOPES) { + JsonNode before = baseline.path(scope); + JsonNode after = manifest.path(scope); + Set scopeNames = new LinkedHashSet<>(); + before.fieldNames().forEachRemaining(scopeNames::add); + after.fieldNames().forEachRemaining(scopeNames::add); + for (String n : scopeNames) { + if (!Objects.equals(before.path(n).asText(null), after.path(n).asText(null))) { + names.add(n); + } + } + } + return names; + } + + private Map parseOverrides() { + Map parsed = new LinkedHashMap<>(); + JsonNode overridesNode = manifest.path("overrides"); + if (overridesNode.isMissingNode()) { + return parsed; + } + if (!overridesNode.isObject()) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, null, "non-object `overrides`"); + } + overridesNode.fields().forEachRemaining(e -> { + String key = e.getKey(); + JsonNode value = e.getValue(); + if (!value.isTextual() || key.contains("@") && key.lastIndexOf('@') > 0 || value.asText().startsWith("$")) { + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, key, + "only flat `\"package\": \"range\"` overrides are supported natively"); + } + NpmRange range = NpmRange.parse(value.asText()); + if (range == null) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, key, + "override target `" + value.asText() + "` is not a semver range"); + } + parsed.put(key, range); + }); + return parsed; + } + + /** + * An override whose value changed since the pre-edit manifest (the + * {@code UpgradeTransitiveDependencyVersion} path) is a no-op when every copy + * of the package already satisfies it. When it would actually move a pin, npm + * re-places the overridden copies (nesting them under their dependents, as the + * recorded {@code override} fixture shows) — a placement decision this engine + * refuses to guess. + */ + private void applyOverrideEdits() { + JsonNode before = originalManifest == null ? MAPPER.createObjectNode() + : originalManifest.path("overrides"); + for (Map.Entry override : overrides.entrySet()) { + String name = override.getKey(); + if (Objects.equals(before.path(name).asText(null), + manifest.path("overrides").path(name).asText(null))) { + continue; + } + for (String path : tree.paths()) { + if (!name.equals(NpmLockTree.nameOf(path))) { + continue; + } + ObjectNode entry = tree.entry(path); + String pinned = entry == null ? null : entry.path("version").asText(null); + if (pinned == null || !override.getValue().satisfies(pinned)) { + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, name, + "override `" + name + "` -> `" + override.getValue() + + "` moves " + name + "@" + pinned + " at " + path + + "; npm re-places overridden copies, which requires full resolution"); + } + } + } + } + + private void applyDependencyEdit(String name) { + String newRange = declaredRange(manifest, name); + if (newRange == null) { + return; // removal: the root-entry sync and orphan sweep complete it + } + NpmRange range = NpmRange.parse(effectiveRange(name, newRange)); + if (range == null) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, name, + "`" + newRange + "` is not a registry semver range; git, file, alias and " + + "tarball dependencies are not resolved natively"); + } + String location = tree.resolve("", name); + if (location == null) { + addEntry(name, range); + return; + } + ObjectNode entry = tree.entry(location); + if (entry == null) { + throw new EngineFailure(Reason.MALFORMED_LOCK, name, "unresolvable entry at " + location); + } + if (entry.has("name") && !name.equals(entry.path("name").asText())) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, name, + "aliased package at " + location); + } + String pinned = entry.path("version").asText(null); + if (pinned != null && range.satisfies(pinned)) { + return; // npm keeps a still-valid pin; only the recorded ranges change + } + moveEntry(location, name, range); + } + + /** Scope priority mirrors arborist's edge precedence: dev > optional > prod > peer. */ + private static final String[] DECLARATION_PRIORITY = { + "devDependencies", "optionalDependencies", "dependencies", "peerDependencies"}; + + private @Nullable String declaredRange(ObjectNode source, String name) { + for (String scope : DECLARATION_PRIORITY) { + JsonNode range = source.path(scope).get(name); + if (range != null) { + return range.asText(); + } + } + return null; + } + + private String effectiveRange(String name, String declared) { + NpmRange override = overrides.get(name); + return override != null ? override.toString() : declared; + } + + /** Re-resolve the entry at {@code location} to the best version for {@code range}. */ + private void moveEntry(String location, String name, NpmRange range) { + guardNoBundledChildren(location, name); + ObjectNode current = tree.entry(location); + String chosen = placeEntry(location, name, range, + current == null ? null : current.path("version").asText(null)); + if (chosen != null) { + verifyDependents(location, name, chosen); + } + } + + /** Add {@code name} as a new top-level entry, npm's maximally-hoisted placement. */ + private void addEntry(String name, NpmRange range) { + placeEntry("node_modules/" + name, name, range, null); + } + + private @Nullable String placeEntry(String location, String name, NpmRange range, + @Nullable String currentVersion) { + Packument packument = registry.packument(name); + String chosen = NpmRange.pickVersion(packument.versions().keySet(), packument.latestTag(), range); + if (chosen == null) { + throw new EngineFailure(Reason.VERSION_NOT_FOUND, name, + "no published version of " + name + " satisfies `" + range + "`"); + } + if (chosen.equals(currentVersion)) { + return null; + } + ObjectNode versionManifest = packument.version(chosen); + if (versionManifest == null) { + throw new EngineFailure(Reason.VERSION_NOT_FOUND, name, name + "@" + chosen + " has no manifest"); + } + packages.set(location, buildEntry(name, versionManifest)); + rebuiltPaths.add(location); + verifyClosure(location, name, chosen); + return chosen; + } + + private void guardNoBundledChildren(String location, String name) { + String prefix = location + "/node_modules/"; + for (String path : tree.paths()) { + if (path.startsWith(prefix)) { + ObjectNode child = tree.entry(path); + if (child != null && child.path("inBundle").asBoolean(false)) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, name, + name + " ships bundled dependencies, whose content is only " + + "knowable from the tarball"); + } + } + } + } + + /** + * The Tier-0 proof: every requirement of the moved/added entry must already be + * satisfied by the tree visible from its location. Anything else would require + * placing new packages or moving pins npm chose — full resolution territory. + */ + private void verifyClosure(String location, String name, String version) { + for (Edge edge : tree.edges(location)) { + NpmRange edgeRange = NpmRange.parse(effectiveRange(edge.name, edge.range)); + if (edgeRange == null) { + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, name, + name + "@" + version + " depends on " + edge.name + "@`" + edge.range + + "`, which is not a registry semver range"); + } + String target = tree.resolve(location, edge.name); + if (target == null) { + if (edge.optional) { + continue; + } + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, name, + name + "@" + version + " requires " + edge.name + "@`" + edge.range + + "`, which is not in the tree; installing it needs full resolution"); + } + ObjectNode targetEntry = tree.entry(target); + String targetVersion = targetEntry == null ? null : targetEntry.path("version").asText(null); + if (targetEntry != null && targetEntry.has("name")) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, name, + edge.name + " resolves to an aliased package at " + target); + } + if (targetVersion == null || !edgeRange.satisfies(targetVersion)) { + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, name, + name + "@" + version + " requires " + edge.name + "@`" + edge.range + + "` but the tree pins " + edge.name + "@" + targetVersion + + (edge.peer ? " (peer dependency conflict)" : "; the cascade needs full resolution")); + } + } + } + + /** + * The reverse proof: every entry that resolves this location for its own + * requirement must still accept the new version. Where it would not, npm nests + * a fresh copy for that dependent — a placement decision we refuse to guess. + */ + private void verifyDependents(String location, String name, String version) { + for (String path : tree.paths()) { + if (path.equals(location)) { + continue; + } + for (Edge edge : tree.edges(path)) { + if (!edge.name.equals(name) || !location.equals(tree.resolve(path, edge.name))) { + continue; + } + NpmRange edgeRange = NpmRange.parse(effectiveRange(edge.name, edge.range)); + if (edgeRange == null || !edgeRange.satisfies(version)) { + if (path.isEmpty()) { + continue; // the root's own edge is the edit being applied + } + throw new EngineFailure(Reason.RESOLUTION_REQUIRED, name, + NpmLockTree.nameOf(path) + " requires " + name + "@`" + edge.range + + "`, which " + name + "@" + version + " no longer satisfies; " + + "npm would nest a second copy"); + } + } + } + } + + /** + * The manifest fields npm copies into a lock entry ({@code pkgMetaKeys} in + * arborist's shrinkwrap.js), with its quirks: falsy values and empty objects + * are skipped, and a license object collapses to its {@code type}. + */ + private static final String[] PKG_META_KEYS = { + "version", "dependencies", "peerDependencies", "peerDependenciesMeta", + "optionalDependencies", "bundleDependencies", "acceptDependencies", + "funding", "engines", "os", "cpu", "libc", "license", "bin", "deprecated", "workspaces"}; + + private ObjectNode buildEntry(String name, ObjectNode versionManifest) { + if (truthy(versionManifest.get("bundleDependencies")) || truthy(versionManifest.get("bundledDependencies"))) { + throw new EngineFailure(Reason.UNSUPPORTED_ENTRY_TYPE, name, + name + " bundles dependencies inside its tarball"); + } + ObjectNode entry = MAPPER.createObjectNode(); + for (String key : PKG_META_KEYS) { + JsonNode value = versionManifest.get(key); + if (value == null || !truthy(value) || (value.isObject() && value.isEmpty())) { + continue; + } + if ("license".equals(key) && value.isObject() && value.hasNonNull("type")) { + entry.set("license", value.get("type")); + } else if ("funding".equals(key) && value.isTextual()) { + entry.putObject("funding").put("url", value.textValue()); + } else if ("bin".equals(key)) { + ObjectNode bin = normalizeBin(value, versionManifest.path("name").asText(name)); + if (bin != null) { + entry.set("bin", bin); + } + } else { + entry.set(key, value.deepCopy()); + } + } + JsonNode scripts = versionManifest.path("scripts"); + if (versionManifest.path("hasInstallScript").asBoolean(false) || + scripts.has("install") || scripts.has("preinstall") || scripts.has("postinstall")) { + entry.put("hasInstallScript", true); + } + JsonNode dist = versionManifest.path("dist"); + String tarball = dist.path("tarball").asText(null); + if (tarball == null) { + throw new EngineFailure(Reason.INTEGRITY_UNAVAILABLE, name, + "registry supplies no tarball URL for " + name); + } + entry.put("resolved", tarball); + String integrity = dist.path("integrity").asText(null); + if (integrity == null) { + String shasum = dist.path("shasum").asText(null); + if (shasum == null || !shasum.matches("(?:[0-9a-fA-F]{2})+")) { + throw new EngineFailure(Reason.INTEGRITY_UNAVAILABLE, name, + "registry supplies neither integrity nor a well-formed shasum for " + name); + } + integrity = "sha1-" + Base64.getEncoder().encodeToString(hexToBytes(shasum)); + } + entry.put("integrity", integrity); + return entry; + } + + /** + * npm-normalize-package-bin: a string bin keys on the package name, an array + * keys each path on its basename, keys collapse to their basename (dropping + * any scope), and targets are resolved as rooted paths (stripping {@code ./} + * and {@code ../} escapes). No surviving entries means no {@code bin} field. + */ + private static @Nullable ObjectNode normalizeBin(JsonNode value, String packageName) { + ObjectNode raw = MAPPER.createObjectNode(); + if (value.isTextual()) { + raw.set(packageName, value); + } else if (value.isArray()) { + for (JsonNode element : value) { + if (element.isTextual()) { + raw.set(basename(element.textValue().replace('\\', '/')), element); + } + } + } else if (value.isObject()) { + raw = (ObjectNode) value; + } else { + return null; + } + ObjectNode clean = MAPPER.createObjectNode(); + raw.fields().forEachRemaining(e -> { + if (!e.getValue().isTextual()) { + return; + } + String base = resolveRooted(basename(e.getKey().replaceAll("[\\\\:]", "/"))); + String target = resolveRooted(e.getValue().textValue().replace('\\', '/')); + if (!base.isEmpty() && !target.isEmpty()) { + clean.put(base, target); + } + }); + return clean.isEmpty() ? null : clean; + } + + private static String basename(String path) { + return path.substring(path.lastIndexOf('/') + 1); + } + + /** {@code path.join('/', p).slice(1)}: resolve {@code .}/{@code ..} against a root, then drop it. */ + private static String resolveRooted(String path) { + java.util.Deque stack = new java.util.ArrayDeque<>(); + for (String segment : path.split("/")) { + if (segment.isEmpty() || ".".equals(segment)) { + continue; + } + if ("..".equals(segment)) { + stack.pollLast(); + } else { + stack.addLast(segment); + } + } + return String.join("/", stack); + } + + private static boolean truthy(@Nullable JsonNode node) { + if (node == null || node.isNull() || node.isMissingNode()) { + return false; + } + if (node.isBoolean()) { + return node.booleanValue(); + } + if (node.isTextual()) { + return !node.textValue().isEmpty(); + } + if (node.isNumber()) { + return node.doubleValue() != 0; + } + return true; + } + + private static byte[] hexToBytes(String hex) { + byte[] out = new byte[hex.length() / 2]; + for (int i = 0; i < out.length; i++) { + out[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16); + } + return out; + } + + /** + * Mirror the manifest's declaration of each edited name into the root entry's + * dependency blocks. Only edited names are touched: unrelated drift between the + * manifest and the recorded root entry is preserved as-is. + */ + private void syncRootEntry(Set editedNames) { + ObjectNode root = root(); + for (String scope : DEP_SCOPES) { + for (String name : editedNames) { + JsonNode declared = manifest.path(scope).get(name); + JsonNode block = root.get(scope); + if (declared != null) { + ObjectNode target = block instanceof ObjectNode ? (ObjectNode) block + : root.putObject(scope); + target.set(name, declared.deepCopy()); + } else if (block instanceof ObjectNode) { + ((ObjectNode) block).remove(name); + if (block.isEmpty()) { + root.remove(scope); + } + } + } + } + } + + private void syncTopLevel() { + JsonNode name = manifest.get("name"); + if (name != null && name.isTextual()) { + lock.set("name", name.deepCopy()); + root().set("name", name.deepCopy()); + } + JsonNode version = manifest.get("version"); + if (version != null && version.isTextual()) { + lock.set("version", version.deepCopy()); + root().set("version", version.deepCopy()); + } + } + + /** + * Remove entries the edit orphaned. Entries that were already unreachable + * before the edit are left in place — that drift predates the recipe. + */ + private void sweepOrphans(Map oldFlags, Map newFlags) { + for (String path : tree.paths()) { + if (!path.isEmpty() && oldFlags.containsKey(path) && !newFlags.containsKey(path)) { + packages.remove(path); + } + } + } + + /** + * Apply recomputed dep flags only where the edit changed an entry's color. When + * a color change lands on an entry whose recorded flags already disagreed with + * the recomputed before-state, our model of the tree cannot be trusted for it. + */ + private void reconcileFlags(Map oldFlags, Map newFlags) { + for (String path : tree.paths()) { + if (path.isEmpty()) { + continue; + } + ObjectNode entry = tree.entry(path); + Flags after = newFlags.get(path); + if (entry == null || after == null) { + continue; + } + Flags before = oldFlags.get(path); + if (before == null || rebuiltPaths.contains(path)) { + NpmLockTree.applyFlags(entry, after); + } else if (!sameColor(before, after)) { + if (!NpmLockTree.sameFlags(entry, before)) { + throw new EngineFailure(Reason.MALFORMED_LOCK, NpmLockTree.nameOf(path), + "recorded dev/optional flags of " + path + " disagree with the " + + "recorded dependency graph"); + } + NpmLockTree.applyFlags(entry, after); + } + } + } + + private static boolean sameColor(Flags a, Flags b) { + return a.dev == b.dev && a.optional == b.optional && + a.devOptional == b.devOptional && a.peer == b.peer; + } + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockTree.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockTree.java new file mode 100644 index 00000000000..e8b939fc4ee --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockTree.java @@ -0,0 +1,238 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.jspecify.annotations.Nullable; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Graph operations over a {@code package-lock.json} v3 {@code packages} map. The map + * records a physical {@code node_modules} tree; an entry's dependency on {@code name} + * resolves to the nearest {@code node_modules/name} walking up from the entry's own + * location — nested copies shadow top-level ones. + */ +final class NpmLockTree { + + /** An outgoing requirement edge: {@code from}'s manifest asks for {@code name@range}. */ + static final class Edge { + final String name; + final String range; + final boolean dev; + final boolean optional; + final boolean peer; + + Edge(String name, String range, boolean dev, boolean optional, boolean peer) { + this.name = name; + this.range = range; + this.dev = dev; + this.optional = optional; + this.peer = peer; + } + } + + /** Mutable dep flags per entry, mirroring arborist's node flags. */ + static final class Flags { + boolean dev = true; + boolean optional = true; + boolean devOptional = true; + boolean peer = true; + } + + private final ObjectNode packages; + + NpmLockTree(ObjectNode packages) { + this.packages = packages; + } + + @Nullable ObjectNode entry(String pathKey) { + JsonNode node = packages.get(pathKey); + return node instanceof ObjectNode ? (ObjectNode) node : null; + } + + List paths() { + List out = new ArrayList<>(); + packages.fieldNames().forEachRemaining(out::add); + return out; + } + + /** The nearest visible location providing {@code name} from {@code fromPath}, or null. */ + @Nullable String resolve(String fromPath, String name) { + String scope = fromPath; + while (true) { + String candidate = scope.isEmpty() ? "node_modules/" + name : scope + "/node_modules/" + name; + if (packages.has(candidate)) { + return candidate; + } + if (scope.isEmpty()) { + return null; + } + int idx = scope.lastIndexOf("/node_modules/"); + scope = idx < 0 ? "" : scope.substring(0, idx); + } + } + + /** + * Outgoing edges of the entry at {@code pathKey}, in arborist's load order — + * peer first, then prod, optional, and (root only) dev, with a later scope + * replacing an earlier same-name edge, so the effective precedence is + * dev > optional > prod > peer. A root declaring the same package in both + * {@code peerDependencies} and {@code devDependencies} gets a dev edge, which + * is why npm records such entries as {@code "dev": true}. + */ + List edges(String pathKey) { + ObjectNode entry = entry(pathKey); + if (entry == null) { + return new ArrayList<>(); + } + Map byName = new LinkedHashMap<>(); + JsonNode peerMeta = entry.get("peerDependenciesMeta"); + forEachDep(entry, "peerDependencies", (name, range) -> { + boolean peerOptional = peerMeta != null && + peerMeta.path(name).path("optional").asBoolean(false); + byName.put(name, new Edge(name, range, false, peerOptional, true)); + }); + forEachDep(entry, "dependencies", (name, range) -> + byName.put(name, new Edge(name, range, false, false, false))); + forEachDep(entry, "optionalDependencies", (name, range) -> + byName.put(name, new Edge(name, range, false, true, false))); + if (pathKey.isEmpty()) { + forEachDep(entry, "devDependencies", (name, range) -> + byName.put(name, new Edge(name, range, true, false, false))); + } + return new ArrayList<>(byName.values()); + } + + private static void forEachDep(ObjectNode entry, String field, + java.util.function.BiConsumer consumer) { + JsonNode deps = entry.get(field); + if (deps != null && deps.isObject()) { + deps.fields().forEachRemaining(e -> consumer.accept(e.getKey(), e.getValue().asText(""))); + } + } + + /** + * arborist's {@code calc-dep-flags}: all flags start true (root all-false) and are + * unset walking edges to a fixed point; whatever survives is provable ("still + * flagged optional" means "only reachable via optional edges"). Returns flags for + * every reachable entry; unreachable entries are absent, which makes this double + * as the orphan sweep. + */ + Map calcDepFlags() { + Map flags = new HashMap<>(); + Flags rootFlags = new Flags(); + rootFlags.dev = rootFlags.optional = rootFlags.devOptional = rootFlags.peer = false; + flags.put("", rootFlags); + + Deque queue = new ArrayDeque<>(); + queue.push(""); + Set seen = new HashSet<>(); + while (!queue.isEmpty()) { + String path = queue.pop(); + seen.add(path); + Flags from = flags.get(path); + for (Edge edge : edges(path)) { + String toPath = resolve(path, edge.name); + if (toPath == null) { + continue; + } + Flags to = flags.computeIfAbsent(toPath, k -> new Flags()); + boolean changed = !seen.contains(toPath); + if (to.dev && !from.dev && !edge.dev) { + to.dev = false; + changed = true; + } + if (to.optional && !from.optional && !edge.optional) { + to.optional = false; + changed = true; + } + if (to.devOptional && !from.devOptional && !from.dev && !from.optional && + !edge.dev && !edge.optional) { + to.devOptional = false; + changed = true; + } + if (to.peer && !from.peer && !edge.peer) { + to.peer = false; + changed = true; + } + if (changed) { + queue.push(toPath); + } + } + } + for (Map.Entry e : flags.entrySet()) { + Flags f = e.getValue(); + if (f.devOptional && (f.dev || f.optional)) { + f.devOptional = false; + } + } + return flags; + } + + /** + * Apply computed flags to an entry's {@code dev}/{@code optional}/{@code peer}/ + * {@code devOptional} fields exactly as {@code Shrinkwrap.metaFromNode} writes them. + */ + static void applyFlags(ObjectNode entry, Flags flags) { + entry.remove("dev"); + entry.remove("optional"); + entry.remove("devOptional"); + entry.remove("peer"); + if (flags.peer) { + entry.put("peer", true); + } + if (flags.dev) { + entry.put("dev", true); + } + if (flags.optional) { + entry.put("optional", true); + } + if (flags.devOptional && !flags.dev && !flags.optional) { + entry.put("devOptional", true); + } + } + + static boolean sameFlags(ObjectNode entry, Flags flags) { + return flagMatches(entry, "dev", flags.dev) && + flagMatches(entry, "optional", flags.optional) && + flagMatches(entry, "peer", flags.peer) && + flagMatches(entry, "devOptional", flags.devOptional && !flags.dev && !flags.optional); + } + + private static boolean flagMatches(ObjectNode entry, String field, boolean expected) { + return entry.path(field).asBoolean(false) == expected; + } + + /** The package name of a lock path key: whatever follows the last {@code node_modules/}. */ + static @Nullable String nameOf(String pathKey) { + int marker = pathKey.lastIndexOf("node_modules/"); + if (marker < 0) { + return null; + } + String tail = pathKey.substring(marker + "node_modules/".length()); + return tail.isEmpty() ? null : tail; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriter.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriter.java new file mode 100644 index 00000000000..870b4713f4a --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriter.java @@ -0,0 +1,261 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Emits {@code package-lock.json} byte-identically to npm. npm writes the lock via + * {@code json-stringify-nice(data, swKeyOrder, indent) + '\n'} with {@code \n} + * replaced by the original file's line ending — a deterministic full-document + * re-serialization that sorts every object's keys: non-object values before object + * values, the {@code swKeyOrder} priority list first, then {@code localeCompare('en')}. + *

+ * The en-collation comparator is reproduced as a two-pass comparison (per-character + * primary weights with case folded, then lowercase-before-uppercase), verified against + * {@code Intl.Collator}-sorted vectors in {@code src/test/resources/npmlock/}. + */ +public final class NpmLockWriter { + + private static final Map SW_KEY_ORDER = new java.util.HashMap<>(); + + static { + String[] keys = {"name", "version", "lockfileVersion", "resolved", "integrity", + "requires", "packages", "dependencies"}; + for (int i = 0; i < keys.length; i++) { + SW_KEY_ORDER.put(keys[i], i); + } + } + + /** + * Primary collation weights: characters in ascending {@code localeCompare('en')} + * order with upper/lowercase folded together. Generated with Node's Intl collator. + */ + private static final String PRIMARY_ORDER = " _-,;:!?.'\"()[]{}@*/\\&#%`^+<=>|~$0123456789abcdefghijklmnopqrstuvwxyz"; + private static final int[] PRIMARY_WEIGHT = new int[128]; + + static { + java.util.Arrays.fill(PRIMARY_WEIGHT, -1); + for (int i = 0; i < PRIMARY_ORDER.length(); i++) { + char c = PRIMARY_ORDER.charAt(i); + PRIMARY_WEIGHT[c] = i; + if (c >= 'a' && c <= 'z') { + PRIMARY_WEIGHT[Character.toUpperCase(c)] = i; + } + } + } + + private NpmLockWriter() { + } + + public static String write(JsonNode root, String indent, String eol) { + StringBuilder sb = new StringBuilder(); + writeValue(root, sb, indent, ""); + sb.append('\n'); + String out = sb.toString(); + return "\n".equals(eol) ? out : out.replace("\n", eol); + } + + private static void writeValue(JsonNode node, StringBuilder sb, String indent, String gap) { + if (node.isObject()) { + writeObject(node, sb, indent, gap); + } else if (node.isArray()) { + writeArray(node, sb, indent, gap); + } else if (node.isTextual()) { + writeString(node.textValue(), sb); + } else if (node.isNull()) { + sb.append("null"); + } else if (node.isBoolean()) { + sb.append(node.booleanValue()); + } else if (node.isIntegralNumber()) { + sb.append(node.bigIntegerValue()); + } else { + sb.append(node.decimalValue().stripTrailingZeros().toPlainString()); + } + } + + private static void writeObject(JsonNode node, StringBuilder sb, String indent, String gap) { + if (node.isEmpty()) { + sb.append("{}"); + return; + } + List> entries = new ArrayList<>(); + node.fields().forEachRemaining(entries::add); + entries.sort((a, b) -> { + boolean aObj = isObj(a.getValue()); + boolean bObj = isObj(b.getValue()); + if (aObj != bObj) { + return aObj ? 1 : -1; + } + return compareKeys(a.getKey(), b.getKey()); + }); + String childGap = gap + indent; + sb.append("{\n"); + for (int i = 0; i < entries.size(); i++) { + sb.append(childGap); + writeString(entries.get(i).getKey(), sb); + sb.append(": "); + writeValue(entries.get(i).getValue(), sb, indent, childGap); + if (i < entries.size() - 1) { + sb.append(','); + } + sb.append('\n'); + } + sb.append(gap).append('}'); + } + + private static void writeArray(JsonNode node, StringBuilder sb, String indent, String gap) { + if (node.isEmpty()) { + sb.append("[]"); + return; + } + String childGap = gap + indent; + sb.append("[\n"); + for (int i = 0; i < node.size(); i++) { + sb.append(childGap); + writeValue(node.get(i), sb, indent, childGap); + if (i < node.size() - 1) { + sb.append(','); + } + sb.append('\n'); + } + sb.append(gap).append(']'); + } + + private static boolean isObj(JsonNode node) { + return node.isObject(); + } + + static int compareKeys(String a, String b) { + Integer prefA = SW_KEY_ORDER.get(a); + Integer prefB = SW_KEY_ORDER.get(b); + if (prefA != null || prefB != null) { + if (prefA == null) { + return 1; + } + if (prefB == null) { + return -1; + } + return prefA.compareTo(prefB); + } + return localeCompareEn(a, b); + } + + /** + * {@code String.prototype.localeCompare(other, 'en')}: primary weights across the + * whole string first (shorter prefix wins), then case as a tiebreak per position + * (lowercase before uppercase). + */ + static int localeCompareEn(String a, String b) { + int len = Math.min(a.length(), b.length()); + for (int i = 0; i < len; i++) { + int wa = primaryWeight(a.charAt(i)); + int wb = primaryWeight(b.charAt(i)); + if (wa != wb) { + return Integer.compare(wa, wb); + } + } + if (a.length() != b.length()) { + return Integer.compare(a.length(), b.length()); + } + for (int i = 0; i < len; i++) { + char ca = a.charAt(i); + char cb = b.charAt(i); + if (ca != cb) { + boolean upperA = ca >= 'A' && ca <= 'Z'; + boolean upperB = cb >= 'A' && cb <= 'Z'; + if (upperA != upperB) { + return upperA ? 1 : -1; + } + return Character.compare(ca, cb); + } + } + return 0; + } + + private static int primaryWeight(char c) { + if (c < 128 && PRIMARY_WEIGHT[c] >= 0) { + return PRIMARY_WEIGHT[c]; + } + return 1000 + c; + } + + /** JSON.stringify string escaping: short escapes, {@code \\u00xx} control chars, UTF-8 passthrough. */ + private static void writeString(String s, StringBuilder sb) { + sb.append('"'); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\b': + sb.append("\\b"); + break; + case '\t': + sb.append("\\t"); + break; + case '\n': + sb.append("\\n"); + break; + case '\f': + sb.append("\\f"); + break; + case '\r': + sb.append("\\r"); + break; + default: + boolean loneHigh = Character.isHighSurrogate(c) && + (i + 1 >= s.length() || !Character.isLowSurrogate(s.charAt(i + 1))); + boolean loneLow = Character.isLowSurrogate(c) && + (i == 0 || !Character.isHighSurrogate(s.charAt(i - 1))); + if (c < 0x20 || loneHigh || loneLow) { + sb.append(String.format("\\u%04x", (int) c)); + } else { + sb.append(c); + } + } + } + sb.append('"'); + } + + /** Indent unit of the original file (whitespace run opening the second line), npm's default is two spaces. */ + static String detectIndent(String content) { + int nl = content.indexOf('\n'); + if (nl >= 0) { + int i = nl + 1; + int start = i; + while (i < content.length() && (content.charAt(i) == ' ' || content.charAt(i) == '\t')) { + i++; + } + if (i > start && i < content.length()) { + return content.substring(start, i); + } + } + return " "; + } + + static String detectEol(String content) { + return content.contains("\r\n") ? "\r\n" : "\n"; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryClient.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryClient.java new file mode 100644 index 00000000000..a388d33d551 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryClient.java @@ -0,0 +1,97 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.registry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.openrewrite.ipc.http.HttpSender; +import org.openrewrite.javascript.internal.registry.NpmRegistryException.Reason; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Fetches full packuments over the run's {@link HttpSender}. Full (not abbreviated) + * metadata is required because npm itself resolves with {@code fullMetadata: true} — + * lock entries carry {@code license}, {@code funding} and {@code bin}, which the + * abbreviated document omits. Responses are cached per client instance; the engine + * only fetches metadata for packages an edit actually moves. + */ +public class NpmRegistryClient { + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private final HttpSender httpSender; + private final NpmRegistryConfig config; + private final Map cache = new ConcurrentHashMap<>(); + + public NpmRegistryClient(HttpSender httpSender, NpmRegistryConfig config) { + this.httpSender = httpSender; + this.config = config; + } + + public Packument packument(String packageName) { + String registry = config.registryFor(packageName); + String url = registry + encodeName(packageName); + return cache.computeIfAbsent(url, u -> fetch(registry, u, packageName)); + } + + private Packument fetch(String registry, String url, String packageName) { + HttpSender.Request request; + try { + HttpSender.Request.Builder builder = httpSender.get(url) + .withHeader("Accept", "application/json"); + String authorization = config.authorizationFor(registry); + if (authorization != null) { + builder = builder.withHeader("Authorization", authorization); + } + request = builder.build(); + } catch (NpmRegistryException e) { + throw e; + } catch (Exception e) { + throw new NpmRegistryException(Reason.CONFIG, registry, "Invalid registry URL: " + url, e); + } + try (HttpSender.Response response = httpSender.send(request)) { + int code = response.getCode(); + if (code == 401 || code == 403) { + throw new NpmRegistryException(Reason.AUTH_FAILED, registry, "HTTP " + code + " from " + url); + } + if (code == 404) { + throw new NpmRegistryException(Reason.NOT_FOUND, registry, + "Package " + packageName + " not found at " + registry); + } + if (!response.isSuccessful()) { + throw new NpmRegistryException(Reason.UNREACHABLE, registry, "HTTP " + code + " from " + url); + } + JsonNode body = MAPPER.readTree(response.getBodyAsBytes()); + if (!(body instanceof ObjectNode)) { + throw new NpmRegistryException(Reason.UNREACHABLE, registry, + "Unexpected packument payload from " + url); + } + return new Packument((ObjectNode) body); + } catch (NpmRegistryException e) { + throw e; + } catch (Exception e) { + throw new NpmRegistryException(Reason.UNREACHABLE, registry, + "Failed to fetch " + packageName + " from " + registry + ": " + e, e); + } + } + + static String encodeName(String packageName) { + // Scoped names URL-encode the separating slash, matching npm-package-arg. + return packageName.startsWith("@") ? packageName.replace("/", "%2f") : packageName; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfig.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfig.java new file mode 100644 index 00000000000..8e80779da4e --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfig.java @@ -0,0 +1,219 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.registry; + +import org.jspecify.annotations.Nullable; +import org.openrewrite.ExecutionContext; +import org.openrewrite.javascript.JavaScriptExecutionContextView; +import org.openrewrite.javascript.NpmRegistryCredentials; +import org.openrewrite.javascript.internal.registry.NpmRegistryException.Reason; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Registry and credential resolution for npm packages, mirroring npm's own rules: + * {@code @scope:registry=} then {@code registry=} then the npmjs default, with + * auth keys matched to a registry by the npm-registry-fetch walk over + * {@code //host/path:_authToken}-style keys. {@code ${VAR}} placeholders expand + * from the environment; a registry whose URL still contains an unresolved + * placeholder fails loudly only when actually used. + *

+ * Host-supplied configuration on {@link JavaScriptExecutionContextView} takes + * precedence over {@code .npmrc} properties, which arrive already merged in + * scope priority (global < user < project). + */ +public class NpmRegistryConfig { + + public static final String DEFAULT_REGISTRY = "https://registry.npmjs.org/"; + + private static final Pattern ENV_VAR = Pattern.compile("\\$\\{([^}]+)}"); + + private final Map npmrc; + private final @Nullable String viewDefaultRegistry; + private final Map viewScopedRegistries; + private final java.util.List viewCredentials; + private final Function env; + + public NpmRegistryConfig(Map npmrcProperties, ExecutionContext ctx) { + this(npmrcProperties, ctx, System::getenv); + } + + NpmRegistryConfig(Map npmrcProperties, ExecutionContext ctx, + Function env) { + this.npmrc = npmrcProperties; + this.env = env; + JavaScriptExecutionContextView view = JavaScriptExecutionContextView.view(ctx); + this.viewDefaultRegistry = view.getNpmDefaultRegistry(); + this.viewScopedRegistries = view.getNpmScopedRegistries() == null + ? new LinkedHashMap<>() : view.getNpmScopedRegistries(); + this.viewCredentials = view.getRegistryCredentials(); + } + + /** Parse merged {@code .npmrc} content (ini-style {@code key=value} lines). */ + public static Map parseNpmrc(@Nullable String content) { + Map props = new LinkedHashMap<>(); + if (content == null) { + return props; + } + for (String line : content.split("\r?\n")) { + String trimmed = line.trim(); + if (trimmed.isEmpty() || trimmed.startsWith("#") || trimmed.startsWith(";")) { + continue; + } + int eq = trimmed.indexOf('='); + if (eq < 1) { + continue; + } + String key = trimmed.substring(0, eq).trim(); + String value = trimmed.substring(eq + 1).trim(); + if (value.length() >= 2 && + (value.startsWith("\"") && value.endsWith("\"") || + value.startsWith("'") && value.endsWith("'"))) { + value = value.substring(1, value.length() - 1); + } + props.put(key, value); + } + return props; + } + + /** The registry URL (trailing slash guaranteed) serving the given package name. */ + public String registryFor(String packageName) { + String scope = packageName.startsWith("@") && packageName.indexOf('/') > 0 + ? packageName.substring(0, packageName.indexOf('/')) + : null; + String url = null; + if (scope != null) { + url = viewScopedRegistries.get(scope); + if (url == null) { + url = expanded(scope + ":registry"); + } + } + if (url == null) { + url = viewDefaultRegistry; + } + if (url == null) { + url = expanded("registry"); + } + if (url == null) { + url = DEFAULT_REGISTRY; + } + return url.endsWith("/") ? url : url + "/"; + } + + /** + * The {@code Authorization} header value for the given registry URL, or + * {@code null} for anonymous access. Host-supplied credentials win; otherwise + * npm's auth-key walk over the registry's host and path. + */ + public @Nullable String authorizationFor(String registryUrl) { + URI uri = URI.create(registryUrl); + String host = uri.getHost(); + if (host != null) { + for (NpmRegistryCredentials cred : viewCredentials) { + if (host.equalsIgnoreCase(cred.getHost())) { + if (cred.getToken() != null) { + return "Bearer " + cred.getToken(); + } + if (cred.getUsername() != null && cred.getPassword() != null) { + return basic(cred.getUsername(), cred.getPassword()); + } + } + } + } + + String path = uri.getPath() == null ? "/" : uri.getPath(); + String regKey = "//" + (host == null ? "" : hostWithPort(uri)) + path; + while (regKey.length() > 2) { + String auth = authAt(regKey); + if (auth != null) { + return auth; + } + if (regKey.endsWith("/")) { + regKey = regKey.substring(0, regKey.length() - 1); + } else { + int lastSlash = regKey.lastIndexOf('/'); + regKey = regKey.substring(0, Math.max(2, lastSlash + 1)); + if ("//".equals(regKey)) { + break; + } + } + } + + // Legacy top-level _authToken/_auth apply to whichever registry is in use. + String token = expanded("_authToken"); + if (token != null) { + return "Bearer " + token; + } + String auth = expanded("_auth"); + if (auth != null) { + return "Basic " + auth; + } + return null; + } + + private static String hostWithPort(URI uri) { + return uri.getPort() > 0 ? uri.getHost() + ":" + uri.getPort() : uri.getHost(); + } + + private @Nullable String authAt(String regKey) { + String token = expanded(regKey + ":_authToken"); + if (token != null) { + return "Bearer " + token; + } + String auth = expanded(regKey + ":_auth"); + if (auth != null) { + return "Basic " + auth; + } + String username = expanded(regKey + ":username"); + String password = expanded(regKey + ":_password"); + if (username != null && password != null) { + String decoded = new String(Base64.getDecoder().decode(password), StandardCharsets.UTF_8); + return basic(username, decoded); + } + return null; + } + + private static String basic(String username, String password) { + return "Basic " + Base64.getEncoder().encodeToString( + (username + ":" + password).getBytes(StandardCharsets.UTF_8)); + } + + private @Nullable String expanded(String key) { + String value = npmrc.get(key); + if (value == null) { + return null; + } + Matcher m = ENV_VAR.matcher(value); + StringBuffer sb = new StringBuffer(); + while (m.find()) { + String replacement = env.apply(m.group(1)); + if (replacement == null) { + throw new NpmRegistryException(Reason.CONFIG, null, + ".npmrc value for " + key + " references unset environment variable ${" + m.group(1) + "}"); + } + m.appendReplacement(sb, Matcher.quoteReplacement(replacement)); + } + m.appendTail(sb); + return sb.toString(); + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryException.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryException.java new file mode 100644 index 00000000000..487d7cef1db --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/NpmRegistryException.java @@ -0,0 +1,49 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.registry; + +import lombok.Getter; +import org.jspecify.annotations.Nullable; + +/** + * A structured failure talking to an npm registry, mapping onto the lock + * regeneration failure reasons rather than surfacing as raw IO errors. + */ +@Getter +public class NpmRegistryException extends RuntimeException { + + public enum Reason { + AUTH_FAILED, + NOT_FOUND, + UNREACHABLE, + CONFIG + } + + private final Reason reason; + private final @Nullable String registryUrl; + + public NpmRegistryException(Reason reason, @Nullable String registryUrl, String message) { + super(message); + this.reason = reason; + this.registryUrl = registryUrl; + } + + public NpmRegistryException(Reason reason, @Nullable String registryUrl, String message, Throwable cause) { + super(message, cause); + this.reason = reason; + this.registryUrl = registryUrl; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/Packument.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/Packument.java new file mode 100644 index 00000000000..ce7e6efb033 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/registry/Packument.java @@ -0,0 +1,67 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.registry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.jspecify.annotations.Nullable; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A full registry packument ({@code GET registry/name}). Version manifests are kept + * as raw {@link ObjectNode}s: lock entries copy manifest fields verbatim, so any + * remodeling would risk losing the exact shapes npm preserves (funding arrays, + * string-or-object bin, etc.). + */ +public final class Packument { + private final ObjectNode root; + + Packument(ObjectNode root) { + this.root = root; + } + + public @Nullable String latestTag() { + JsonNode distTags = root.get("dist-tags"); + if (distTags != null && distTags.hasNonNull("latest")) { + return distTags.get("latest").asText(); + } + return null; + } + + public Map versions() { + Map out = new LinkedHashMap<>(); + JsonNode versions = root.get("versions"); + if (versions != null && versions.isObject()) { + versions.fields().forEachRemaining(e -> { + if (e.getValue() instanceof ObjectNode) { + out.put(e.getKey(), (ObjectNode) e.getValue()); + } + }); + } + return out; + } + + public @Nullable ObjectNode version(String version) { + JsonNode versions = root.get("versions"); + if (versions == null || !versions.isObject()) { + return null; + } + JsonNode v = versions.get(version); + return v instanceof ObjectNode ? (ObjectNode) v : null; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmComparator.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmComparator.java new file mode 100644 index 00000000000..21a9d567543 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmComparator.java @@ -0,0 +1,87 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.semver; + +import org.jspecify.annotations.Nullable; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A single desugared comparator ({@code >=1.2.3}, {@code <2.0.0-0}, ...) as produced by + * {@link NpmRange}'s pipeline. {@link #ANY} is the empty comparator matching everything. + */ +final class NpmComparator { + + static final NpmComparator ANY = new NpmComparator("", null); + + private static final Pattern COMPARATOR = Pattern.compile("^((?:<|>)?=?)\\s*(.*)$"); + + private final String operator; + private final @Nullable NpmVersion version; + + private NpmComparator(String operator, @Nullable NpmVersion version) { + this.operator = operator; + this.version = version; + } + + static @Nullable NpmComparator parse(String comp) { + Matcher m = COMPARATOR.matcher(comp.trim()); + if (!m.matches()) { + return null; + } + String op = m.group(1); + String rest = m.group(2); + if (rest.isEmpty()) { + return op.isEmpty() ? ANY : null; + } + NpmVersion v = NpmVersion.parse(rest); + if (v == null) { + return null; + } + return new NpmComparator("=".equals(op) ? "" : op, v); + } + + @Nullable NpmVersion getVersion() { + return version; + } + + boolean test(NpmVersion candidate) { + if (version == null) { + return true; + } + int cmp = candidate.compareTo(version); + switch (operator) { + case "": + return cmp == 0; + case ">": + return cmp > 0; + case ">=": + return cmp >= 0; + case "<": + return cmp < 0; + case "<=": + return cmp <= 0; + default: + return false; + } + } + + @Override + public String toString() { + return version == null ? "" : operator + version; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmRange.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmRange.java new file mode 100644 index 00000000000..67a6ccd0c68 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmRange.java @@ -0,0 +1,367 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.semver; + +import org.jspecify.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A node-semver range: {@code ||}-separated comparator sets with {@code ^}, {@code ~}, + * x-ranges, hyphen ranges, and the prerelease-exclusion rule. The desugaring pipeline + * (hyphen → trims → caret → tilde → x-range → star → GTE0) is ported line-for-line from + * npm/node-semver {@code classes/range.js} in strict (non-loose) mode, and validated + * against node-semver's range-include/range-exclude fixture corpus. + *

+ * Deliberately not built on {@link org.openrewrite.semver.Semver}: that package is a + * recipe-facing version selector (four-part Maven-style versions, metadata patterns, no + * {@code ||} unions or compound comparator sets, no prerelease-exclusion rule), while + * lock regeneration needs bit-exact node-semver {@code satisfies} semantics. + */ +public final class NpmRange { + + private static final int PARSE_CACHE_LIMIT = 1000; + private static final Map> PARSE_CACHE = new ConcurrentHashMap<>(); + + private static final String XRANGE_ID = "[0-9]+|x|X|\\*"; + private static final String XRANGE_PLAIN = "[v=\\s]*(" + XRANGE_ID + ")" + + "(?:\\.(" + XRANGE_ID + ")" + + "(?:\\.(" + XRANGE_ID + ")" + + "(?:" + NpmVersion.PRERELEASE + ")?" + + NpmVersion.BUILD + "?" + + ")?)?"; + private static final String GTLT = "((?:<|>)?=?)"; + + private static final Pattern HYPHEN_RANGE = Pattern.compile( + "^\\s*(" + XRANGE_PLAIN + ")\\s+-\\s+(" + XRANGE_PLAIN + ")\\s*$"); + private static final Pattern COMPARATOR_TRIM = Pattern.compile( + "(\\s*)" + GTLT + "\\s*(" + XRANGE_PLAIN + ")"); + private static final Pattern TILDE_TRIM = Pattern.compile("(\\s*)~>?\\s+"); + private static final Pattern CARET_TRIM = Pattern.compile("(\\s*)\\^\\s+"); + private static final Pattern TILDE = Pattern.compile("^(?:~>?)" + XRANGE_PLAIN + "$"); + private static final Pattern CARET = Pattern.compile("^(?:\\^)" + XRANGE_PLAIN + "$"); + private static final Pattern XRANGE = Pattern.compile("^" + GTLT + "\\s*" + XRANGE_PLAIN + "$"); + private static final Pattern STAR = Pattern.compile("(<|>)?=?\\s*\\*"); + private static final Pattern GTE0 = Pattern.compile("^\\s*>=\\s*0\\.0\\.0\\s*$"); + private static final Pattern BUILD_STRIP = Pattern.compile(NpmVersion.BUILD); + + private final List> comparatorSets; + private final String raw; + + private NpmRange(List> comparatorSets, String raw) { + this.comparatorSets = comparatorSets; + this.raw = raw; + } + + /** Parse a range, returning {@code null} when it is not a valid strict-mode semver range. */ + public static @Nullable NpmRange parse(@Nullable String range) { + if (range == null) { + return null; + } + Optional cached = PARSE_CACHE.get(range); + if (cached == null) { + if (PARSE_CACHE.size() >= PARSE_CACHE_LIMIT) { + PARSE_CACHE.clear(); + } + cached = Optional.ofNullable(parseUncached(range)); + PARSE_CACHE.put(range, cached); + } + return cached.orElse(null); + } + + private static @Nullable NpmRange parseUncached(String range) { + List> sets = new ArrayList<>(); + for (String set : range.trim().split("\\|\\|", -1)) { + List comparators; + try { + comparators = parseComparatorSet(set.trim()); + } catch (NumberFormatException e) { + return null; + } + if (comparators == null) { + return null; + } + sets.add(comparators); + } + return sets.isEmpty() ? null : new NpmRange(sets, range.trim()); + } + + private static @Nullable List parseComparatorSet(String set) { + String range = BUILD_STRIP.matcher(set).replaceAll(""); + Matcher hyphen = HYPHEN_RANGE.matcher(range); + if (hyphen.matches()) { + range = hyphenReplace(hyphen); + } + range = replaceAll(COMPARATOR_TRIM, range, m -> m.group(1) + m.group(2) + m.group(3)); + range = TILDE_TRIM.matcher(range).replaceAll("$1~"); + range = CARET_TRIM.matcher(range).replaceAll("$1^"); + + StringBuilder joined = new StringBuilder(); + for (String comp : range.trim().split("\\s+", -1)) { + if (joined.length() > 0) { + joined.append(' '); + } + joined.append(parseComparator(comp)); + } + List out = new ArrayList<>(); + for (String comp : joined.toString().trim().split("\\s+", -1)) { + comp = GTE0.matcher(comp).replaceAll(""); + if (comp.isEmpty()) { + continue; + } + NpmComparator parsed = NpmComparator.parse(comp); + if (parsed == null) { + return null; + } + out.add(parsed); + } + if (out.isEmpty()) { + out.add(NpmComparator.ANY); + } + return out; + } + + private static String parseComparator(String comp) { + comp = replaceCaret(comp); + comp = replaceTilde(comp); + comp = replaceXRange(comp); + comp = STAR.matcher(comp.trim()).replaceAll(""); + return comp; + } + + private static boolean isX(@Nullable String id) { + return id == null || id.isEmpty() || "x".equalsIgnoreCase(id) || "*".equals(id); + } + + private static String hyphenReplace(Matcher m) { + String from = m.group(1); + String fM = m.group(2), fm = m.group(3), fp = m.group(4), fpr = m.group(5); + String to = m.group(7); + String tM = m.group(8), tm = m.group(9), tp = m.group(10), tpr = m.group(11); + + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = ">=" + fM + ".0.0"; + } else if (isX(fp)) { + from = ">=" + fM + "." + fm + ".0"; + } else { + from = ">=" + from; + } + + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = "<" + (Long.parseLong(tM) + 1) + ".0.0-0"; + } else if (isX(tp)) { + to = "<" + tM + "." + (Long.parseLong(tm) + 1) + ".0-0"; + } else if (tpr != null) { + to = "<=" + tM + "." + tm + "." + tp + "-" + tpr; + } else { + to = "<=" + to; + } + return (from + " " + to).trim(); + } + + private static String replaceTilde(String comp) { + Matcher m = TILDE.matcher(comp.trim()); + if (!m.matches()) { + return comp; + } + String M = m.group(1), mn = m.group(2), p = m.group(3), pr = m.group(4); + if (isX(M)) { + return ""; + } + if (isX(mn)) { + return ">=" + M + ".0.0 <" + (Long.parseLong(M) + 1) + ".0.0-0"; + } + if (isX(p)) { + return ">=" + M + "." + mn + ".0 <" + M + "." + (Long.parseLong(mn) + 1) + ".0-0"; + } + String base = pr != null ? M + "." + mn + "." + p + "-" + pr : M + "." + mn + "." + p; + return ">=" + base + " <" + M + "." + (Long.parseLong(mn) + 1) + ".0-0"; + } + + private static String replaceCaret(String comp) { + Matcher m = CARET.matcher(comp.trim()); + if (!m.matches()) { + return comp; + } + String M = m.group(1), mn = m.group(2), p = m.group(3), pr = m.group(4); + if (isX(M)) { + return ""; + } + if (isX(mn)) { + return ">=" + M + ".0.0 <" + (Long.parseLong(M) + 1) + ".0.0-0"; + } + if (isX(p)) { + if ("0".equals(M)) { + return ">=" + M + "." + mn + ".0 <" + M + "." + (Long.parseLong(mn) + 1) + ".0-0"; + } + return ">=" + M + "." + mn + ".0 <" + (Long.parseLong(M) + 1) + ".0.0-0"; + } + String base = pr != null ? M + "." + mn + "." + p + "-" + pr : M + "." + mn + "." + p; + if ("0".equals(M)) { + if ("0".equals(mn)) { + return ">=" + base + " <" + M + "." + mn + "." + (Long.parseLong(p) + 1) + "-0"; + } + return ">=" + base + " <" + M + "." + (Long.parseLong(mn) + 1) + ".0-0"; + } + return ">=" + base + " <" + (Long.parseLong(M) + 1) + ".0.0-0"; + } + + private static String replaceXRange(String comp) { + Matcher m = XRANGE.matcher(comp.trim()); + if (!m.matches()) { + return comp; + } + String gtlt = m.group(1); + String M = m.group(2), mn = m.group(3), p = m.group(4); + boolean xM = isX(M); + boolean xm = xM || isX(mn); + boolean xp = xm || isX(p); + boolean anyX = xp; + + if ("=".equals(gtlt) && anyX) { + gtlt = ""; + } + if (xM) { + if (">".equals(gtlt) || "<".equals(gtlt)) { + return "<0.0.0-0"; + } + return "*"; + } + if (!gtlt.isEmpty() && anyX) { + long major = Long.parseLong(M); + long minor = xm ? 0 : Long.parseLong(mn); + long patch = 0; + if (">".equals(gtlt)) { + gtlt = ">="; + if (xm) { + major = major + 1; + minor = 0; + } else { + minor = minor + 1; + } + } else if ("<=".equals(gtlt)) { + gtlt = "<"; + if (xm) { + major = major + 1; + } else { + minor = minor + 1; + } + } + String pr = "<".equals(gtlt) ? "-0" : ""; + return gtlt + major + "." + minor + "." + patch + pr; + } + if (xm) { + return ">=" + M + ".0.0 <" + (Long.parseLong(M) + 1) + ".0.0-0"; + } + if (xp) { + return ">=" + M + "." + mn + ".0 <" + M + "." + (Long.parseLong(mn) + 1) + ".0-0"; + } + return comp; + } + + private static String replaceAll(Pattern pattern, String input, + java.util.function.Function replacer) { + Matcher m = pattern.matcher(input); + StringBuffer sb = new StringBuffer(); + while (m.find()) { + m.appendReplacement(sb, Matcher.quoteReplacement(replacer.apply(m))); + } + m.appendTail(sb); + return sb.toString(); + } + + /** node-semver {@code satisfies(version, range)} with default options. */ + public boolean satisfies(NpmVersion version) { + for (List set : comparatorSets) { + if (testSet(set, version)) { + return true; + } + } + return false; + } + + public boolean satisfies(@Nullable String version) { + NpmVersion v = NpmVersion.parse(version); + return v != null && satisfies(v); + } + + private static boolean testSet(List set, NpmVersion version) { + for (NpmComparator c : set) { + if (!c.test(version)) { + return false; + } + } + if (version.hasPrerelease()) { + // Prerelease versions only satisfy a set that mentions a prerelease + // of the same [major, minor, patch] tuple. + for (NpmComparator c : set) { + NpmVersion cv = c.getVersion(); + if (cv != null && cv.hasPrerelease() && cv.sameTuple(version)) { + return true; + } + } + return false; + } + return true; + } + + /** Highest satisfying version, or {@code null} when none satisfies. */ + public static @Nullable String maxSatisfying(Collection versions, NpmRange range) { + NpmVersion best = null; + String bestRaw = null; + for (String raw : versions) { + NpmVersion v = NpmVersion.parse(raw); + if (v == null || !range.satisfies(v)) { + continue; + } + if (best == null || v.compareTo(best) > 0) { + best = v; + bestRaw = raw; + } + } + return bestRaw; + } + + /** + * npm's version selection (npm-pick-manifest): the version tagged {@code latest} + * wins when it satisfies the range, even when a higher satisfying version exists; + * otherwise the highest satisfying version is chosen. + */ + public static @Nullable String pickVersion(Collection versions, + @Nullable String latestTag, + NpmRange range) { + if (latestTag != null && versions.contains(latestTag) && range.satisfies(latestTag)) { + return latestTag; + } + return maxSatisfying(versions, range); + } + + @Override + public String toString() { + return raw; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmVersion.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmVersion.java new file mode 100644 index 00000000000..85dddbf77c7 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/semver/NpmVersion.java @@ -0,0 +1,166 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.semver; + +import org.jspecify.annotations.Nullable; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A strict node-semver version: {@code v?major.minor.patch(-prerelease)?(+build)?}. + * Comparison semantics are ported from npm/node-semver {@code classes/semver.js} + * and validated against node-semver's own comparison/equality fixtures. + */ +public final class NpmVersion implements Comparable { + + private static final String NUMERIC_ID = "0|[1-9]\\d*"; + private static final String NON_NUMERIC_ID = "\\d*[a-zA-Z-][a-zA-Z0-9-]*"; + private static final String PRERELEASE_ID = "(?:" + NON_NUMERIC_ID + "|" + NUMERIC_ID + ")"; + static final String PRERELEASE = "(?:-(" + PRERELEASE_ID + "(?:\\." + PRERELEASE_ID + ")*))"; + static final String BUILD = "(?:\\+([a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*))"; + private static final Pattern FULL = Pattern.compile( + "^v?(" + NUMERIC_ID + ")\\.(" + NUMERIC_ID + ")\\.(" + NUMERIC_ID + ")" + + PRERELEASE + "?" + BUILD + "?$"); + + private final long major; + private final long minor; + private final long patch; + private final String[] prerelease; + private final String raw; + + private NpmVersion(long major, long minor, long patch, String[] prerelease, String raw) { + this.major = major; + this.minor = minor; + this.patch = patch; + this.prerelease = prerelease; + this.raw = raw; + } + + // node-semver rejects components above Number.MAX_SAFE_INTEGER as invalid. + static final long MAX_SAFE_COMPONENT = 9007199254740991L; + + public static @Nullable NpmVersion parse(@Nullable String version) { + if (version == null) { + return null; + } + Matcher m = FULL.matcher(version.trim()); + if (!m.matches()) { + return null; + } + long major, minor, patch; + try { + major = Long.parseLong(m.group(1)); + minor = Long.parseLong(m.group(2)); + patch = Long.parseLong(m.group(3)); + } catch (NumberFormatException e) { + return null; + } + if (major > MAX_SAFE_COMPONENT || minor > MAX_SAFE_COMPONENT || patch > MAX_SAFE_COMPONENT) { + return null; + } + String pre = m.group(4); + String[] preIds = pre == null ? new String[0] : pre.split("\\."); + return new NpmVersion(major, minor, patch, preIds, version.trim()); + } + + public boolean hasPrerelease() { + return prerelease.length > 0; + } + + boolean sameTuple(NpmVersion other) { + return major == other.major && minor == other.minor && patch == other.patch; + } + + @Override + public int compareTo(NpmVersion o) { + int c = Long.compare(major, o.major); + if (c != 0) { + return c; + } + c = Long.compare(minor, o.minor); + if (c != 0) { + return c; + } + c = Long.compare(patch, o.patch); + if (c != 0) { + return c; + } + return comparePrerelease(o); + } + + private int comparePrerelease(NpmVersion o) { + if (prerelease.length == 0 && o.prerelease.length == 0) { + return 0; + } + if (prerelease.length == 0) { + return 1; + } + if (o.prerelease.length == 0) { + return -1; + } + for (int i = 0; ; i++) { + if (i >= prerelease.length && i >= o.prerelease.length) { + return 0; + } + if (i >= prerelease.length) { + return -1; + } + if (i >= o.prerelease.length) { + return 1; + } + int c = compareIdentifier(prerelease[i], o.prerelease[i]); + if (c != 0) { + return c; + } + } + } + + private static int compareIdentifier(String a, String b) { + boolean aNum = a.chars().allMatch(Character::isDigit); + boolean bNum = b.chars().allMatch(Character::isDigit); + if (aNum && bNum) { + return new BigInteger(a).compareTo(new BigInteger(b)); + } + if (aNum) { + return -1; + } + if (bNum) { + return 1; + } + return Integer.signum(a.compareTo(b)); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof NpmVersion)) { + return false; + } + return compareTo((NpmVersion) o) == 0; + } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[]{major, minor, patch, Arrays.hashCode(prerelease)}); + } + + @Override + public String toString() { + return raw; + } +} diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/table/NodeLockRegenerationFailures.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/table/NodeLockRegenerationFailures.java new file mode 100644 index 00000000000..ae4399761b7 --- /dev/null +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/table/NodeLockRegenerationFailures.java @@ -0,0 +1,54 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.table; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Value; +import org.jspecify.annotations.Nullable; +import org.openrewrite.Column; +import org.openrewrite.DataTable; +import org.openrewrite.Recipe; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NodeLockRegenerationFailures extends DataTable { + + public NodeLockRegenerationFailures(Recipe recipe) { + super(recipe, + "Node lock file regeneration failures", + "Records why a lock file could not be regenerated after a dependency recipe " + + "changed a `package.json`, so fleet-scale runs can aggregate causes. " + + "On any failure the manifest edit still applies and the old lock is left untouched."); + } + + @Value + public static class Row { + @Column(displayName = "Source path", + description = "The lock file that was not regenerated.") + String sourcePath; + + @Column(displayName = "Package name", + description = "The package whose resolution caused the failure, when attributable.") + @Nullable String packageName; + + @Column(displayName = "Reason", + description = "The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.") + String reason; + + @Column(displayName = "Detail", + description = "Human-readable detail of the failure.") + String detail; + } +} diff --git a/rewrite-javascript/src/main/resources/META-INF/rewrite/recipes.csv b/rewrite-javascript/src/main/resources/META-INF/rewrite/recipes.csv index d5811ff90f5..560fc8be744 100644 --- a/rewrite-javascript/src/main/resources/META-INF/rewrite/recipes.csv +++ b/rewrite-javascript/src/main/resources/META-INF/rewrite/recipes.csv @@ -1,7 +1,7 @@ ecosystem,packageName,name,displayName,description,recipeCount,category1,category2,options,dataTables -maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.AddDependency,Add npm dependency,"Add an npm dependency to `package.json` and regenerate the lock file by running the package manager. If the dependency already exists in any scope, the recipe is a no-op. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the npm package to add (e.g., `lodash`, `@types/node`)."",""example"":""lodash"",""required"":true},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version constraint to set (e.g., `^5.0.0`, `~2.1.0`, `3.0.0`)."",""example"":""^5.0.0"",""required"":true},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope: `dependencies`, `devDependencies`, `peerDependencies`, or `optionalDependencies`. Defaults to `dependencies`."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies""]}]", -maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.ChangeDependency,Change npm dependency,"Renames an npm dependency in `package.json` and optionally updates its version constraint. After modifying the package.json, the lock file is regenerated by running the package manager. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""oldPackageName"",""type"":""String"",""displayName"":""Old package name"",""description"":""The current name of the npm package to rename."",""example"":""lodash"",""required"":true},{""name"":""newPackageName"",""type"":""String"",""displayName"":""New package name"",""description"":""The new name to use for the package."",""example"":""lodash-es"",""required"":true},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""Optional new version constraint to set on the renamed package."",""example"":""^5.0.0""},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope: `dependencies`, `devDependencies`, etc. When omitted, all scopes are searched."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies"",""bundledDependencies""]}]", -maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.RemoveDependency,Remove npm dependency,"Remove an npm dependency from `package.json` and regenerate the lock file. If the dependency does not exist in any scope, the recipe is a no-op.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the npm package to remove (e.g., `lodash`, `@types/node`)."",""example"":""lodash"",""required"":true},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope to remove from: `dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`, or `bundledDependencies`. If not specified, removes from all scopes."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies"",""bundledDependencies""]}]", -maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.UpgradeDependencyVersion,Upgrade npm dependency version,Upgrades the version constraint of matching npm dependencies in `package.json` and regenerates the lock file by running the package manager. Matching is by exact package name or glob pattern. v1 uses simple string inequality for the upgrade check (always overwrites). A future version will use semver to skip already-up-to-date constraints. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.,1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""Exact package name to match. Mutually exclusive with `packagePattern`; at least one is required."",""example"":""lodash""},{""name"":""packagePattern"",""type"":""String"",""displayName"":""Package pattern"",""description"":""Glob pattern matching package names (e.g., `@types/*`). Mutually exclusive with `packageName`; at least one is required."",""example"":""@types/*""},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""The new version constraint to set on matching dependencies."",""example"":""^5.0.0"",""required"":true}]", -maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.UpgradeTransitiveDependencyVersion,Upgrade transitive npm dependency,"Pins or upgrades a transitive npm dependency by adding an override entry to `package.json` and regenerating the lock file. For npm and Bun, adds to the `overrides` field; for Yarn, adds to `resolutions`; for pnpm, adds to `pnpm.overrides`. The override is idempotent — if the entry already exists with the same version, no change is made. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the transitive npm dependency to upgrade."",""example"":""lodash"",""required"":true},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""The version constraint to set on the override entry."",""example"":""^5.0.0"",""required"":true},{""name"":""dependencyPath"",""type"":""String"",""displayName"":""Dependency path"",""description"":""Optional dependency path (pnpm-style `a>b>c` or yarn-style `a/b/c`) to scope the override. When omitted, applies as a global override."",""example"":""express>accepts""}]", +maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.AddDependency,Add npm dependency,"Add an npm dependency to `package.json` and regenerate the lock file (natively for npm, by running the package manager otherwise). If the dependency already exists in any scope, the recipe is a no-op. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the npm package to add (e.g., `lodash`, `@types/node`)."",""example"":""lodash"",""required"":true},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version constraint to set (e.g., `^5.0.0`, `~2.1.0`, `3.0.0`)."",""example"":""^5.0.0"",""required"":true},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope: `dependencies`, `devDependencies`, `peerDependencies`, or `optionalDependencies`. Defaults to `dependencies`."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies""]}]","[{""name"":""org.openrewrite.javascript.table.NodeLockRegenerationFailures"",""displayName"":""Node lock file regeneration failures"",""instanceName"":""Node lock file regeneration failures"",""description"":""Records why a lock file could not be regenerated after a dependency recipe changed a `package.json`, so fleet-scale runs can aggregate causes. On any failure the manifest edit still applies and the old lock is left untouched."",""columns"":[{""name"":""sourcePath"",""type"":""String"",""displayName"":""Source path"",""description"":""The lock file that was not regenerated.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The package whose resolution caused the failure, when attributable.""},{""name"":""reason"",""type"":""String"",""displayName"":""Reason"",""description"":""The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.""},{""name"":""detail"",""type"":""String"",""displayName"":""Detail"",""description"":""Human-readable detail of the failure.""}]}]" +maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.ChangeDependency,Change npm dependency,"Renames an npm dependency in `package.json` and optionally updates its version constraint. After modifying the package.json, the lock file is regenerated (natively for npm, by running the package manager otherwise). Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""oldPackageName"",""type"":""String"",""displayName"":""Old package name"",""description"":""The current name of the npm package to rename."",""example"":""lodash"",""required"":true},{""name"":""newPackageName"",""type"":""String"",""displayName"":""New package name"",""description"":""The new name to use for the package."",""example"":""lodash-es"",""required"":true},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""Optional new version constraint to set on the renamed package."",""example"":""^5.0.0""},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope: `dependencies`, `devDependencies`, etc. When omitted, all scopes are searched."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies"",""bundledDependencies""]}]","[{""name"":""org.openrewrite.javascript.table.NodeLockRegenerationFailures"",""displayName"":""Node lock file regeneration failures"",""instanceName"":""Node lock file regeneration failures"",""description"":""Records why a lock file could not be regenerated after a dependency recipe changed a `package.json`, so fleet-scale runs can aggregate causes. On any failure the manifest edit still applies and the old lock is left untouched."",""columns"":[{""name"":""sourcePath"",""type"":""String"",""displayName"":""Source path"",""description"":""The lock file that was not regenerated.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The package whose resolution caused the failure, when attributable.""},{""name"":""reason"",""type"":""String"",""displayName"":""Reason"",""description"":""The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.""},{""name"":""detail"",""type"":""String"",""displayName"":""Detail"",""description"":""Human-readable detail of the failure.""}]}]" +maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.RemoveDependency,Remove npm dependency,"Remove an npm dependency from `package.json` and regenerate the lock file. If the dependency does not exist in any scope, the recipe is a no-op.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the npm package to remove (e.g., `lodash`, `@types/node`)."",""example"":""lodash"",""required"":true},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""The dependency scope to remove from: `dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`, or `bundledDependencies`. If not specified, removes from all scopes."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies"",""bundledDependencies""]}]","[{""name"":""org.openrewrite.javascript.table.NodeLockRegenerationFailures"",""displayName"":""Node lock file regeneration failures"",""instanceName"":""Node lock file regeneration failures"",""description"":""Records why a lock file could not be regenerated after a dependency recipe changed a `package.json`, so fleet-scale runs can aggregate causes. On any failure the manifest edit still applies and the old lock is left untouched."",""columns"":[{""name"":""sourcePath"",""type"":""String"",""displayName"":""Source path"",""description"":""The lock file that was not regenerated.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The package whose resolution caused the failure, when attributable.""},{""name"":""reason"",""type"":""String"",""displayName"":""Reason"",""description"":""The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.""},{""name"":""detail"",""type"":""String"",""displayName"":""Detail"",""description"":""Human-readable detail of the failure.""}]}]" +maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.UpgradeDependencyVersion,Upgrade npm dependency version,"Upgrades the version constraint of matching npm dependencies in `package.json` and regenerates the lock file (natively for npm, by running the package manager otherwise). Matching is by exact package name or glob pattern. v1 uses simple string inequality for the upgrade check (always overwrites). A future version will use semver to skip already-up-to-date constraints. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""Exact package name to match. Mutually exclusive with `packagePattern`; at least one is required."",""example"":""lodash""},{""name"":""packagePattern"",""type"":""String"",""displayName"":""Package pattern"",""description"":""Glob pattern matching package names (e.g., `@types/*`). Mutually exclusive with `packageName`; at least one is required."",""example"":""@types/*""},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""The new version constraint to set on matching dependencies."",""example"":""^5.0.0"",""required"":true}]","[{""name"":""org.openrewrite.javascript.table.NodeLockRegenerationFailures"",""displayName"":""Node lock file regeneration failures"",""instanceName"":""Node lock file regeneration failures"",""description"":""Records why a lock file could not be regenerated after a dependency recipe changed a `package.json`, so fleet-scale runs can aggregate causes. On any failure the manifest edit still applies and the old lock is left untouched."",""columns"":[{""name"":""sourcePath"",""type"":""String"",""displayName"":""Source path"",""description"":""The lock file that was not regenerated.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The package whose resolution caused the failure, when attributable.""},{""name"":""reason"",""type"":""String"",""displayName"":""Reason"",""description"":""The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.""},{""name"":""detail"",""type"":""String"",""displayName"":""Detail"",""description"":""Human-readable detail of the failure.""}]}]" +maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.UpgradeTransitiveDependencyVersion,Upgrade transitive npm dependency,"Pins or upgrades a transitive npm dependency by adding an override entry to `package.json` and regenerating the lock file. For npm and Bun, adds to the `overrides` field; for Yarn, adds to `resolutions`; for pnpm, adds to `pnpm.overrides`. The override is idempotent — if the entry already exists with the same version, no change is made. Not safe to use as a precondition: invokes the package manager and publishes per-project state shared with other dependency recipes.",1,,Javascript,"[{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the transitive npm dependency to upgrade."",""example"":""lodash"",""required"":true},{""name"":""newVersion"",""type"":""String"",""displayName"":""New version"",""description"":""The version constraint to set on the override entry."",""example"":""^5.0.0"",""required"":true},{""name"":""dependencyPath"",""type"":""String"",""displayName"":""Dependency path"",""description"":""Optional dependency path (pnpm-style `a>b>c` or yarn-style `a/b/c`) to scope the override. When omitted, applies as a global override."",""example"":""express>accepts""}]","[{""name"":""org.openrewrite.javascript.table.NodeLockRegenerationFailures"",""displayName"":""Node lock file regeneration failures"",""instanceName"":""Node lock file regeneration failures"",""description"":""Records why a lock file could not be regenerated after a dependency recipe changed a `package.json`, so fleet-scale runs can aggregate causes. On any failure the manifest edit still applies and the old lock is left untouched."",""columns"":[{""name"":""sourcePath"",""type"":""String"",""displayName"":""Source path"",""description"":""The lock file that was not regenerated.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The package whose resolution caused the failure, when attributable.""},{""name"":""reason"",""type"":""String"",""displayName"":""Reason"",""description"":""The failure category, e.g. `RESOLUTION_REQUIRED` or `REGISTRY_UNREACHABLE`.""},{""name"":""detail"",""type"":""String"",""displayName"":""Detail"",""description"":""Human-readable detail of the failure.""}]}]" maven,org.openrewrite:rewrite-javascript,org.openrewrite.javascript.search.DependencyInsight,Node.js dependency insight,Find direct and transitive npm dependencies matching a package name pattern. Results include dependencies that either directly match or transitively include a matching dependency.,1,Search,Javascript,"[{""name"":""packageNamePattern"",""type"":""String"",""displayName"":""Package name pattern"",""description"":""A glob pattern to match npm package names. Use `*` as a wildcard."",""example"":""@types/*"",""required"":true},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""Match dependencies in the specified scope. All scopes are searched by default."",""example"":""dependencies"",""valid"":[""dependencies"",""devDependencies"",""peerDependencies"",""optionalDependencies"",""bundledDependencies""]},{""name"":""onlyDirect"",""type"":""Boolean"",""displayName"":""Only direct"",""description"":""If enabled, transitive dependencies will not be considered. All dependencies are searched by default."",""example"":""true""}]","[{""name"":""org.openrewrite.javascript.table.NodeDependenciesInUse"",""displayName"":""Node.js dependencies in use"",""instanceName"":""Node.js dependencies in use"",""description"":""Direct and transitive dependencies in use in Node.js projects."",""columns"":[{""name"":""projectName"",""type"":""String"",""displayName"":""Project name"",""description"":""The name of the project that contains the dependency (from package.json).""},{""name"":""projectPath"",""type"":""String"",""displayName"":""Project path"",""description"":""The path to the project.""},{""name"":""packageName"",""type"":""String"",""displayName"":""Package name"",""description"":""The name of the npm package.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The resolved version of the package.""},{""name"":""versionConstraint"",""type"":""String"",""displayName"":""Version constraint"",""description"":""The version constraint as declared in package.json.""},{""name"":""scope"",""type"":""String"",""displayName"":""Scope"",""description"":""Dependency scope: dependencies, devDependencies, peerDependencies, optionalDependencies, or bundledDependencies.""},{""name"":""direct"",""type"":""Boolean"",""displayName"":""Direct"",""description"":""Whether this is a direct dependency (true) or transitive dependency (false).""},{""name"":""count"",""type"":""Integer"",""displayName"":""Count"",""description"":""How many times this dependency appears in the dependency tree.""},{""name"":""license"",""type"":""String"",""displayName"":""License"",""description"":""The SPDX license identifier of the package, if available.""}]}]" diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/UpgradeDependencyVersionNpmLockTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/UpgradeDependencyVersionNpmLockTest.java new file mode 100644 index 00000000000..43b8ca7124c --- /dev/null +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/UpgradeDependencyVersionNpmLockTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript; + +import org.junit.jupiter.api.Test; +import org.openrewrite.ExecutionContext; +import org.openrewrite.HttpSenderExecutionContextView; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.javascript.internal.npmlock.NpmLockEngineTest.RoutedHttp; +import org.openrewrite.javascript.marker.NodeResolutionResult; +import org.openrewrite.javascript.marker.NodeResolutionResult.Dependency; +import org.openrewrite.javascript.marker.NodeResolutionResult.PackageManager; +import org.openrewrite.javascript.table.NodeLockRegenerationFailures; +import org.openrewrite.marker.Markup; +import org.openrewrite.test.RewriteTest; + +import java.util.UUID; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.openrewrite.json.Assertions.json; +import static org.openrewrite.javascript.internal.npmlock.NpmLockWriterTest.resource; + +/** + * End-to-end recipe runs over the recorded fixtures: the recipe edits the manifest, + * the native engine rewrites the lock byte-identically to real npm, and failures + * surface as warnings on both files plus a data table row — all pure JVM, offline. + */ +class UpgradeDependencyVersionNpmLockTest implements RewriteTest { + + private static NodeResolutionResult npmMarker(Dependency... dependencies) { + return new NodeResolutionResult( + UUID.randomUUID(), "fixture", "1.0.0", null, ".", + null, + asList(dependencies), + emptyList(), emptyList(), emptyList(), emptyList(), + emptyList(), + PackageManager.Npm, + null, null); + } + + private static ExecutionContext offlineCtx(String scenario, String... packages) { + RoutedHttp http = new RoutedHttp(); + for (String pkg : packages) { + http.route(pkg, scenario); + } + ExecutionContext ctx = new InMemoryExecutionContext(t -> { + throw new RuntimeException(t); + }); + HttpSenderExecutionContextView.view(ctx).setHttpSender(http); + return ctx; + } + + @Test + void upgradesManifestAndLockNatively() { + rewriteRun( + spec -> spec.recipe(new UpgradeDependencyVersion("is-number", null, "^6.0.0")) + .executionContext(offlineCtx("upgrade-leaf", "is-number")), + json( + resource("/npmlock/upgrade-leaf/package.json.before"), + s -> { + s.path("package.json"); + s.markers(npmMarker(new Dependency("is-number", "^4.0.0", null))); + s.noTrim().after(actual -> resource("/npmlock/upgrade-leaf/package.json")); + } + ), + json( + resource("/npmlock/upgrade-leaf/package-lock.before.json"), + s -> s.path("package-lock.json").noTrim() + .after(actual -> resource("/npmlock/upgrade-leaf/package-lock.after.json")) + ) + ); + } + + @Test + void cascadeFailureWarnsBothFilesAndRecordsRow() { + rewriteRun( + spec -> spec.recipe(new UpgradeDependencyVersion("is-odd", null, "^3.0.1")) + .executionContext(offlineCtx("cascade-fails", "is-odd")) + .dataTable(NodeLockRegenerationFailures.Row.class, rows -> { + assertThat(rows).hasSize(1); + assertThat(rows.get(0).getSourcePath()).isEqualTo("package-lock.json"); + assertThat(rows.get(0).getPackageName()).isEqualTo("is-odd"); + assertThat(rows.get(0).getReason()).isEqualTo("RESOLUTION_REQUIRED"); + }), + json( + resource("/npmlock/cascade-fails/package.json.before"), + s -> { + s.path("package.json"); + s.markers(npmMarker(new Dependency("is-odd", "^2.0.0", null))); + s.noTrim().after(actual -> { + assertThat(actual) + .startsWith("/*~~(lock regeneration failed: RESOLUTION_REQUIRED") + .endsWith(resource("/npmlock/cascade-fails/package.json")); + return actual; + }); + s.afterRecipe(doc -> assertThat(doc.getMarkers().findFirst(Markup.Warn.class)) + .as("manifest carries the lock-regeneration-failure warning") + .isPresent()); + } + ), + json( + resource("/npmlock/cascade-fails/package-lock.before.json"), + s -> { + s.path("package-lock.json"); + s.noTrim().after(actual -> { + assertThat(actual) + .startsWith("/*~~(lock regeneration failed: RESOLUTION_REQUIRED") + .endsWith(resource("/npmlock/cascade-fails/package-lock.before.json")); + return actual; + }); + s.afterRecipe(doc -> assertThat(doc.getMarkers().findFirst(Markup.Warn.class)) + .as("the untouched lock also carries the warning") + .isPresent()); + } + ) + ); + } +} diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/PackageJsonHelperTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/PackageJsonHelperTest.java index 3f750fab22c..cc173f58306 100644 --- a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/PackageJsonHelperTest.java +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/PackageJsonHelperTest.java @@ -303,7 +303,8 @@ void editAndRegenerateSkipsOverlayForUnsupportedPm() { withMarker, d -> PackageJsonHelper.addDependency(d, "uuid", "^9.0.0", "dependencies"), null, - null); + null, + new org.openrewrite.InMemoryExecutionContext()); assertThat(result.isChanged()).isTrue(); NodeResolutionResult after = result.getModifiedPackageJson().getMarkers() diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngineTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngineTest.java new file mode 100644 index 00000000000..20b8686ecc8 --- /dev/null +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockEngineTest.java @@ -0,0 +1,367 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import org.junit.jupiter.api.Test; +import org.openrewrite.ExecutionContext; +import org.openrewrite.HttpSenderExecutionContextView; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.ipc.http.HttpSender; +import org.openrewrite.javascript.internal.LockFileRegeneration.Reason; +import org.openrewrite.javascript.internal.LockFileRegeneration.Result; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.openrewrite.javascript.internal.npmlock.NpmLockWriterTest.resource; + +/** + * Offline replays of scenarios recorded from real npm: the before-lock, the golden + * after-lock, and the packuments were captured together (see + * {@code src/test/resources/npmlock/record.sh}), so the engine's output is asserted + * byte-identical to what npm itself produced for the same edit. The routed sender + * both serves the recordings and proves nothing escaped to the network. + */ +public class NpmLockEngineTest { + + private static final String REGISTRY = "https://registry.npmjs.org/"; + + public static final class RoutedHttp implements HttpSender { + final Map routes = new LinkedHashMap<>(); + final List requests = new ArrayList<>(); + + public void route(String packageName, String scenario) { + String encoded = packageName.replace("/", "%2f"); + routes.put(REGISTRY + encoded, + resource("/npmlock/" + scenario + "/http/" + encoded + ".json") + .getBytes(StandardCharsets.UTF_8)); + } + + void routeBody(String packageName, String body) { + routes.put(REGISTRY + packageName.replace("/", "%2f"), body.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public Response send(Request request) { + String url = request.getUrl().toString(); + requests.add(url); + byte[] body = routes.get(url); + if (body == null) { + return new Response(404, new ByteArrayInputStream(new byte[0]), () -> { + }); + } + return new Response(200, new ByteArrayInputStream(body), () -> { + }); + } + } + + private RoutedHttp http; + + private ExecutionContext ctx() { + http = new RoutedHttp(); + ExecutionContext ctx = new InMemoryExecutionContext(t -> { + throw new RuntimeException(t); + }); + HttpSenderExecutionContextView.view(ctx).setHttpSender(http); + return ctx; + } + + private Result replay(String scenario, String... recordedPackuments) { + ExecutionContext ctx = ctx(); + for (String packageName : recordedPackuments) { + http.route(packageName, scenario); + } + return NpmLockEngine.regenerate( + resource("/npmlock/" + scenario + "/package.json"), + resource("/npmlock/" + scenario + "/package.json.before"), + resource("/npmlock/" + scenario + "/package-lock.before.json"), + null, + ctx); + } + + private void assertGolden(String scenario, Result result) { + assertThat(result.getErrorMessage()).isNull(); + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getLockFileContent()) + .isEqualTo(resource("/npmlock/" + scenario + "/package-lock.after.json")); + } + + @Test + void upgradeMovesLeafPin() { + Result result = replay("upgrade-leaf", "is-number"); + assertGolden("upgrade-leaf", result); + assertThat(http.requests).containsExactly(REGISTRY + "is-number"); + } + + /** + * The edit set is diffed against the lock's recorded root entry, so an edit made + * by an earlier recipe in the same run (already in the manifest, not yet in the + * captured lock) is reconciled even though this recipe's own before-state + * already contained it. + */ + @Test + void reconcilesEditsFromEarlierRecipesInTheSameRun() { + ExecutionContext ctx = ctx(); + http.route("is-number", "upgrade-leaf"); + String manifest = resource("/npmlock/upgrade-leaf/package.json"); + Result result = NpmLockEngine.regenerate(manifest, manifest, + resource("/npmlock/upgrade-leaf/package-lock.before.json"), null, ctx); + assertGolden("upgrade-leaf", result); + } + + @Test + void rangeEditSatisfiedByPinTouchesOnlyRecordedRanges() { + Result result = replay("range-satisfied"); + assertGolden("range-satisfied", result); + assertThat(http.requests).as("a still-valid pin needs no network").isEmpty(); + } + + @Test + void cascadingUpgradeFailsLoud() { + Result result = replay("cascade-fails", "is-odd"); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure()).isNotNull(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.RESOLUTION_REQUIRED); + assertThat(result.getFailure().getDetail()).contains("is-number"); + assertThat(result.getLockFileContent()).isNull(); + } + + @Test + void removalSweepsOrphanedSubtree() { + Result result = replay("remove-orphans"); + assertGolden("remove-orphans", result); + assertThat(http.requests).isEmpty(); + } + + @Test + void upgradeSweepsDependenciesTheNewVersionDropped() { + Result result = replay("upgrade-orphans", "chalk"); + assertGolden("upgrade-orphans", result); + assertThat(http.requests).containsExactly(REGISTRY + "chalk"); + } + + @Test + void addsLeafDependencyAtTopLevel() { + Result result = replay("add-leaf", "is-buffer"); + assertGolden("add-leaf", result); + assertThat(http.requests).containsExactly(REGISTRY + "is-buffer"); + } + + /** + * The recorded golden shows npm handles an override that moves a pin by + * re-placing the package (dropping the hoisted copy, nesting a fresh one under + * the dependent) — placement the engine must not guess at. It fails loud, and + * the fixture documents the behavior a future placement-aware phase must match. + */ + @Test + void overrideMovingAPinFailsLoud() { + Result result = replay("override"); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.RESOLUTION_REQUIRED); + assertThat(result.getFailure().getPackageName()).isEqualTo("is-buffer"); + assertThat(http.requests).as("fails before any registry traffic").isEmpty(); + } + + @Test + void removalRecolorsSurvivorsReachableOnlyThroughDev() { + Result result = replay("dev-recolor"); + assertGolden("dev-recolor", result); + assertThat(http.requests).isEmpty(); + } + + /** + * Recorded from real npm: a root declaring the same package in both + * devDependencies and peerDependencies gets a dev edge (arborist loads peer + * first and lets dev replace it), so npm writes the entry with "dev": true. + * The replay would fail with a flag-drift MALFORMED_LOCK if the engine's edge + * precedence disagreed with npm's. + */ + @Test + void devEdgeWinsOverPeerEdgeAtTheRoot() { + Result result = replay("dev-peer-overlap", "is-number"); + assertGolden("dev-peer-overlap", result); + } + + @Test + void scopedPackagesEncodeTheRegistryPath() { + Result result = replay("scoped", "@isaacs/string-locale-compare"); + assertGolden("scoped", result); + assertThat(http.requests).containsExactly(REGISTRY + "@isaacs%2fstring-locale-compare"); + } + + // --- Fail-loud guards over synthetic inputs ---------------------------- + + private static final String MANIFEST_V1 = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"dependencies\": {\n \"is-number\": \"^6.0.0\"\n }\n}\n"; + + @Test + void lockfileVersion2FailsLoud() { + String lock = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n \"lockfileVersion\": 2,\n" + + " \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"fixture\",\n" + + " \"version\": \"1.0.0\"\n }\n }\n}\n"; + Result result = NpmLockEngine.regenerate(MANIFEST_V1, null, lock, null, ctx()); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.UNSUPPORTED_LOCK_VERSION); + assertThat(http.requests).isEmpty(); + } + + @Test + void workspacesFailLoud() { + String manifest = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"workspaces\": [\n \"packages/*\"\n ]\n}\n"; + String lock = resource("/npmlock/range-satisfied/package-lock.before.json"); + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx()); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.RESOLUTION_REQUIRED); + assertThat(http.requests).isEmpty(); + } + + @Test + void gitDependencyEditFailsLoud() { + String manifest = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"dependencies\": {\n \"is-number\": \"github:jonschlinkert/is-number\"\n }\n}\n"; + String lock = resource("/npmlock/range-satisfied/package-lock.before.json"); + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx()); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.UNSUPPORTED_ENTRY_TYPE); + assertThat(http.requests).isEmpty(); + } + + @Test + void handEditedLockFailsLoud() { + String canonical = resource("/npmlock/range-satisfied/package-lock.before.json"); + String reordered = canonical.replace( + " \"name\": \"fixture\",\n \"version\": \"1.0.0\",", + " \"version\": \"1.0.0\",\n \"name\": \"fixture\","); + assertThat(reordered).isNotEqualTo(canonical); + Result result = NpmLockEngine.regenerate(MANIFEST_V1, null, reordered, null, ctx()); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.MALFORMED_LOCK); + } + + @Test + void unreachableRegistryFailsLoud() { + String manifest = resource("/npmlock/upgrade-leaf/package.json"); + String lock = resource("/npmlock/upgrade-leaf/package-lock.before.json"); + // No routes: the packument request 404s. + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx()); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.PACKAGE_NOT_FOUND); + assertThat(result.getFailure().getRegistryUrl()).isEqualTo(REGISTRY); + } + + @Test + void versionOutsidePublishedRangeFailsLoud() { + ExecutionContext ctx = ctx(); + http.route("is-number", "upgrade-leaf"); + String manifest = resource("/npmlock/upgrade-leaf/package.json") + .replace("^6.0.0", "^99.0.0"); + String lock = resource("/npmlock/upgrade-leaf/package-lock.before.json"); + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.VERSION_NOT_FOUND); + } + + @Test + void malformedShasumFailsLoud() { + ExecutionContext ctx = ctx(); + http.routeBody("tiny-sha1", "{\n" + + " \"name\": \"tiny-sha1\",\n" + + " \"dist-tags\": { \"latest\": \"1.0.1\" },\n" + + " \"versions\": {\n" + + " \"1.0.1\": {\n" + + " \"name\": \"tiny-sha1\",\n" + + " \"version\": \"1.0.1\",\n" + + " \"dist\": {\n" + + " \"tarball\": \"https://registry.npmjs.org/tiny-sha1/-/tiny-sha1-1.0.1.tgz\",\n" + + " \"shasum\": \"xyz\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + String manifest = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"dependencies\": {\n \"tiny-sha1\": \"^1.0.0\"\n }\n}\n"; + String lock = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n \"lockfileVersion\": 3,\n" + + " \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"fixture\",\n" + + " \"version\": \"1.0.0\"\n }\n }\n}\n"; + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx); + assertThat(result.isSuccess()).isFalse(); + assertThat(result.getFailure().getReason()).isEqualTo(Reason.INTEGRITY_UNAVAILABLE); + } + + @Test + void stringBinNormalizesToBasenamedObject() { + ExecutionContext ctx = ctx(); + http.routeBody("@scope/tiny-bin", "{\n" + + " \"name\": \"@scope/tiny-bin\",\n" + + " \"dist-tags\": { \"latest\": \"1.0.0\" },\n" + + " \"versions\": {\n" + + " \"1.0.0\": {\n" + + " \"name\": \"@scope/tiny-bin\",\n" + + " \"version\": \"1.0.0\",\n" + + " \"bin\": \"./cli.js\",\n" + + " \"dist\": {\n" + + " \"tarball\": \"https://registry.npmjs.org/@scope/tiny-bin/-/tiny-bin-1.0.0.tgz\",\n" + + " \"integrity\": \"sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + String manifest = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"dependencies\": {\n \"@scope/tiny-bin\": \"^1.0.0\"\n }\n}\n"; + String lock = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n \"lockfileVersion\": 3,\n" + + " \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"fixture\",\n" + + " \"version\": \"1.0.0\"\n }\n }\n}\n"; + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx); + assertThat(result.getErrorMessage()).isNull(); + assertThat(result.getLockFileContent()) + .contains("\"bin\": {\n \"tiny-bin\": \"cli.js\"\n }"); + } + + @Test + void sha1OnlyDistFallsBackToShasumConversion() { + ExecutionContext ctx = ctx(); + // npm converts a hex shasum to "sha1-" when the registry has no integrity. + http.routeBody("tiny-sha1", "{\n" + + " \"name\": \"tiny-sha1\",\n" + + " \"dist-tags\": { \"latest\": \"1.0.1\" },\n" + + " \"versions\": {\n" + + " \"1.0.1\": {\n" + + " \"name\": \"tiny-sha1\",\n" + + " \"version\": \"1.0.1\",\n" + + " \"dist\": {\n" + + " \"tarball\": \"https://registry.npmjs.org/tiny-sha1/-/tiny-sha1-1.0.1.tgz\",\n" + + " \"shasum\": \"5f2eaa1bc1e34d0f64101bc7e64e8fdd9e50634a\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + String manifest = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n" + + " \"dependencies\": {\n \"tiny-sha1\": \"^1.0.0\"\n }\n}\n"; + String lock = "{\n \"name\": \"fixture\",\n \"version\": \"1.0.0\",\n \"lockfileVersion\": 3,\n" + + " \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"fixture\",\n" + + " \"version\": \"1.0.0\"\n }\n }\n}\n"; + Result result = NpmLockEngine.regenerate(manifest, null, lock, null, ctx); + assertThat(result.getErrorMessage()).isNull(); + assertThat(result.getLockFileContent()) + .contains("\"integrity\": \"sha1-Xy6qG8HjTQ9kEBvH5k6P3Z5QY0o=\""); + } +} diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriterTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriterTest.java new file mode 100644 index 00000000000..ed1605f1e9c --- /dev/null +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/npmlock/NpmLockWriterTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.npmlock; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.openrewrite.internal.StringUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NpmLockWriterTest { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + public static String resource(String name) { + try (InputStream is = NpmLockWriterTest.class.getResourceAsStream(name)) { + assertThat(is).as(name).isNotNull(); + return StringUtils.readFully(is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * npm's emission is a deterministic full-document re-serialization, so parsing + * any npm-written lock and re-emitting it must reproduce the input byte-for-byte. + */ + @ParameterizedTest + @ValueSource(strings = { + "/npmlock/upgrade-leaf/package-lock.before.json", + "/npmlock/upgrade-leaf/package-lock.after.json", + "/npmlock/range-satisfied/package-lock.before.json", + "/npmlock/cascade-fails/package-lock.before.json", + "/npmlock/cascade-fails/package-lock.after.json", + "/npmlock/remove-orphans/package-lock.before.json", + "/npmlock/remove-orphans/package-lock.after.json", + "/npmlock/upgrade-orphans/package-lock.before.json", + "/npmlock/upgrade-orphans/package-lock.after.json", + "/npmlock/add-leaf/package-lock.before.json", + "/npmlock/add-leaf/package-lock.after.json", + "/npmlock/override/package-lock.before.json", + "/npmlock/override/package-lock.after.json", + "/npmlock/dev-recolor/package-lock.before.json", + "/npmlock/dev-recolor/package-lock.after.json", + "/npmlock/dev-peer-overlap/package-lock.before.json", + "/npmlock/dev-peer-overlap/package-lock.after.json", + "/npmlock/scoped/package-lock.before.json", + "/npmlock/scoped/package-lock.after.json" + }) + void roundTripByteIdentity(String fixture) throws IOException { + String content = resource(fixture); + String out = NpmLockWriter.write(MAPPER.readTree(content), + NpmLockWriter.detectIndent(content), NpmLockWriter.detectEol(content)); + assertThat(out).isEqualTo(content); + } + + /** + * Key ordering must match {@code localeCompare('en')} exactly; the vectors were + * sorted by Node's own Intl collator (see record provenance in the README). + */ + @Test + void collationMatchesNodeIntl() { + List sorted = new ArrayList<>(); + for (String line : resource("/npmlock/locale-sorted-keys.txt").split("\n", -1)) { + sorted.add(line); + } + if (!sorted.isEmpty() && sorted.get(sorted.size() - 1).isEmpty()) { + sorted.remove(sorted.size() - 1); + } + for (int i = 1; i < sorted.size(); i++) { + String prev = sorted.get(i - 1); + String next = sorted.get(i); + assertThat(NpmLockWriter.localeCompareEn(prev, next)) + .as("expected %s <= %s", prev, next) + .isLessThanOrEqualTo(0); + } + } + + @Test + void crlfPreserved() throws IOException { + String content = resource("/npmlock/upgrade-leaf/package-lock.before.json"); + String crlf = content.replace("\n", "\r\n"); + String out = NpmLockWriter.write(MAPPER.readTree(crlf), " ", NpmLockWriter.detectEol(crlf)); + assertThat(out).isEqualTo(crlf); + } + + @Test + void indentDetection() { + assertThat(NpmLockWriter.detectIndent("{\n \"a\": 1\n}")).isEqualTo(" "); + assertThat(NpmLockWriter.detectIndent("{\n\t\"a\": 1\n}")).isEqualTo("\t"); + assertThat(NpmLockWriter.detectIndent("{}")).isEqualTo(" "); + } +} diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfigTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfigTest.java new file mode 100644 index 00000000000..0e7374d1d89 --- /dev/null +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/registry/NpmRegistryConfigTest.java @@ -0,0 +1,128 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.registry; + +import org.junit.jupiter.api.Test; +import org.openrewrite.ExecutionContext; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.javascript.JavaScriptExecutionContextView; +import org.openrewrite.javascript.NpmRegistryCredentials; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class NpmRegistryConfigTest { + + private static NpmRegistryConfig config(String npmrc, ExecutionContext ctx, Map env) { + return new NpmRegistryConfig(NpmRegistryConfig.parseNpmrc(npmrc), ctx, env::get); + } + + private static NpmRegistryConfig config(String npmrc) { + return config(npmrc, new InMemoryExecutionContext(), singletonMap("NPM_TOKEN", "s3cret")); + } + + @Test + void defaultsToNpmjs() { + NpmRegistryConfig config = config(""); + assertThat(config.registryFor("lodash")).isEqualTo("https://registry.npmjs.org/"); + assertThat(config.authorizationFor("https://registry.npmjs.org/")).isNull(); + } + + @Test + void scopedRegistryWinsOverDefault() { + NpmRegistryConfig config = config( + "registry=https://npm.corp.example/\n" + + "@myorg:registry=https://npm.myorg.example/sub/\n"); + assertThat(config.registryFor("lodash")).isEqualTo("https://npm.corp.example/"); + assertThat(config.registryFor("@myorg/pkg")).isEqualTo("https://npm.myorg.example/sub/"); + assertThat(config.registryFor("@other/pkg")).isEqualTo("https://npm.corp.example/"); + } + + @Test + void authTokenMatchedByHostAndPathWalk() { + NpmRegistryConfig config = config( + "@myorg:registry=https://npm.example.com/org/registry/\n" + + "//npm.example.com/org/registry/:_authToken=deep-token\n" + + "//npm.example.com/:_authToken=host-token\n"); + assertThat(config.authorizationFor("https://npm.example.com/org/registry/")) + .isEqualTo("Bearer deep-token"); + assertThat(config.authorizationFor("https://npm.example.com/elsewhere/")) + .isEqualTo("Bearer host-token"); + assertThat(config.authorizationFor("https://other.example.com/")).isNull(); + } + + @Test + void usernamePasswordDecodesBase64Password() { + String encoded = Base64.getEncoder().encodeToString("hunter2".getBytes(StandardCharsets.UTF_8)); + NpmRegistryConfig config = config( + "//npm.example.com/:username=alice\n" + + "//npm.example.com/:_password=" + encoded + "\n"); + String expected = "Basic " + Base64.getEncoder() + .encodeToString("alice:hunter2".getBytes(StandardCharsets.UTF_8)); + assertThat(config.authorizationFor("https://npm.example.com/")).isEqualTo(expected); + } + + @Test + void environmentPlaceholdersExpand() { + NpmRegistryConfig config = config("//npm.example.com/:_authToken=${NPM_TOKEN}\n"); + assertThat(config.authorizationFor("https://npm.example.com/")).isEqualTo("Bearer s3cret"); + } + + @Test + void unsetPlaceholderFailsOnlyWhenUsed() { + NpmRegistryConfig config = config( + "//npm.example.com/:_authToken=${MISSING_VAR}\n", + new InMemoryExecutionContext(), + singletonMap("OTHER", "x")); + assertThat(config.registryFor("lodash")).isEqualTo("https://registry.npmjs.org/"); + assertThatThrownBy(() -> config.authorizationFor("https://npm.example.com/")) + .isInstanceOf(NpmRegistryException.class) + .hasMessageContaining("MISSING_VAR"); + } + + @Test + void executionContextViewOverridesNpmrc() { + ExecutionContext ctx = new InMemoryExecutionContext(); + JavaScriptExecutionContextView.view(ctx) + .setNpmDefaultRegistry("https://mirror.example.com") + .setNpmScopedRegistries(singletonMap("@myorg", "https://scoped.example.com/")) + .setRegistryCredentials(singletonList( + NpmRegistryCredentials.token("mirror.example.com", "view-token"))); + NpmRegistryConfig config = config( + "registry=https://npm.corp.example/\n" + + "//mirror.example.com/:_authToken=npmrc-token\n", + ctx, singletonMap("X", "y")); + assertThat(config.registryFor("lodash")).isEqualTo("https://mirror.example.com/"); + assertThat(config.registryFor("@myorg/pkg")).isEqualTo("https://scoped.example.com/"); + assertThat(config.authorizationFor("https://mirror.example.com/")) + .as("host-supplied credentials win over .npmrc") + .isEqualTo("Bearer view-token"); + } + + @Test + void commentsAndQuotesInNpmrc() { + Map props = NpmRegistryConfig.parseNpmrc( + "# comment\n; also comment\nregistry=\"https://npm.example.com/\"\n\nbad-line\n"); + assertThat(props).containsExactly( + java.util.Map.entry("registry", "https://npm.example.com/")); + } +} diff --git a/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/semver/NpmSemverConformanceTest.java b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/semver/NpmSemverConformanceTest.java new file mode 100644 index 00000000000..edebe191977 --- /dev/null +++ b/rewrite-javascript/src/test/java/org/openrewrite/javascript/internal/semver/NpmSemverConformanceTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.javascript.internal.semver; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Conformance against node-semver's own test fixtures ({@code test/fixtures/} in + * npm/node-semver), transposed to TSV with loose-mode and includePrerelease rows + * removed. Regenerate per the README in {@code src/test/resources/npm-semver/}. + */ +class NpmSemverConformanceTest { + + private static Stream corpus(String resource) { + BufferedReader reader = new BufferedReader(new InputStreamReader( + NpmSemverConformanceTest.class.getResourceAsStream("/npm-semver/" + resource), + StandardCharsets.UTF_8)); + return reader.lines().filter(l -> !l.isEmpty()) + .map(l -> org.junit.jupiter.params.provider.Arguments.of((Object[]) l.split("\t", -1))); + } + + static Stream satisfies() { + return corpus("satisfies.tsv"); + } + + static Stream comparisons() { + return corpus("comparisons.tsv"); + } + + static Stream equality() { + return corpus("equality.tsv"); + } + + @ParameterizedTest + @MethodSource("satisfies") + void satisfiesCorpus(String rangeStr, String version, String expectedStr) { + NpmRange range = NpmRange.parse(rangeStr); + boolean expected = Boolean.parseBoolean(expectedStr); + if (range == null) { + assertThat(expected).as("unparseable range %s must only appear in exclude rows", rangeStr).isFalse(); + } else { + assertThat(range.satisfies(version)) + .as("satisfies(%s, %s)", version, rangeStr) + .isEqualTo(expected); + } + } + + @ParameterizedTest + @MethodSource("comparisons") + void greaterThanCorpus(String greater, String lesser) { + NpmVersion v0 = NpmVersion.parse(greater); + NpmVersion v1 = NpmVersion.parse(lesser); + assertThat(v0).isNotNull(); + assertThat(v1).isNotNull(); + assertThat(v0.compareTo(v1)).as("%s > %s", greater, lesser).isPositive(); + assertThat(v1.compareTo(v0)).as("%s < %s", lesser, greater).isNegative(); + } + + @ParameterizedTest + @MethodSource("equality") + void equalityCorpus(String left, String right) { + NpmVersion v0 = NpmVersion.parse(left); + NpmVersion v1 = NpmVersion.parse(right); + assertThat(v0).isNotNull(); + assertThat(v1).isNotNull(); + assertThat(v0.compareTo(v1)).as("%s == %s", left, right).isZero(); + } + + @Test + void pickVersionPrefersLatestDistTag() { + List versions = asList("1.0.0", "1.5.0", "2.0.0", "2.1.0"); + NpmRange range = NpmRange.parse(">=1.0.0"); + assertThat(range).isNotNull(); + // "latest" pinned behind the newest satisfying version still wins. + assertThat(NpmRange.pickVersion(versions, "2.0.0", range)).isEqualTo("2.0.0"); + // "latest" outside the range falls back to maxSatisfying. + assertThat(NpmRange.pickVersion(versions, "2.0.0", NpmRange.parse("^1.0.0"))).isEqualTo("1.5.0"); + assertThat(NpmRange.pickVersion(versions, null, range)).isEqualTo("2.1.0"); + } + + @Test + void prereleaseExclusionRule() { + assertThat(NpmRange.parse("^1.2.3").satisfies("1.9.0-beta.1")).isFalse(); + assertThat(NpmRange.parse("^1.2.3-beta.2").satisfies("1.2.3-beta.4")).isTrue(); + assertThat(NpmRange.parse("^1.2.3-beta.2").satisfies("1.2.4-beta.1")).isFalse(); + assertThat(NpmRange.parse("*").satisfies("1.0.0-rc.1")).isFalse(); + } + + @Test + void componentsAboveMaxSafeIntegerAreInvalid() { + assertThat(NpmVersion.parse("9007199254740992.0.0")).isNull(); + assertThat(NpmVersion.parse("99999999999999999999.0.0")).isNull(); + assertThat(NpmVersion.parse("9007199254740991.0.0")).isNotNull(); + assertThat(NpmRange.parse("^99999999999999999999.0.0")).isNull(); + assertThat(NpmRange.parse(">=1.0.0 <99999999999999999999.0.0")).isNull(); + } + + @Test + void nonRegistrySpecsDoNotParse() { + assertThat(NpmRange.parse("github:user/repo")).isNull(); + assertThat(NpmRange.parse("file:../local")).isNull(); + assertThat(NpmRange.parse("npm:other-pkg@^1.0.0")).isNull(); + assertThat(NpmRange.parse("https://example.com/x.tgz")).isNull(); + assertThat(NpmRange.parse("workspace:*")).isNull(); + assertThat(NpmRange.parse("latest")).isNull(); + } + + @Test + void wildcardAndEmptyRanges() { + List all = collectSatisfying("*", asList("1.0.0", "2.3.4", "0.0.1")); + assertThat(all).containsExactly("1.0.0", "2.3.4", "0.0.1"); + assertThat(NpmRange.parse("").satisfies("1.2.3")).isTrue(); + assertThat(NpmRange.parse("1.2.3 || ").satisfies("9.9.9")).isTrue(); + } + + private static List collectSatisfying(String range, List versions) { + NpmRange r = NpmRange.parse(range); + assertThat(r).isNotNull(); + return versions.stream().filter(r::satisfies).collect(Collectors.toList()); + } +} diff --git a/rewrite-javascript/src/test/resources/npm-semver/comparisons.tsv b/rewrite-javascript/src/test/resources/npm-semver/comparisons.tsv new file mode 100644 index 00000000000..3715cf62c5b --- /dev/null +++ b/rewrite-javascript/src/test/resources/npm-semver/comparisons.tsv @@ -0,0 +1,19 @@ +0.0.0 0.0.0-foo +0.0.1 0.0.0 +1.0.0 0.9.9 +0.10.0 0.9.0 +0.99.0 0.10.0 +2.0.0 1.2.3 +1.2.3 1.2.3-asdf +1.2.3 1.2.3-4 +1.2.3 1.2.3-4-foo +1.2.3-5-foo 1.2.3-5 +1.2.3-5 1.2.3-4 +1.2.3-5-foo 1.2.3-5-Foo +3.0.0 2.7.2+asdf +1.2.3-a.10 1.2.3-a.5 +1.2.3-a.b 1.2.3-a.5 +1.2.3-a.b 1.2.3-a +1.2.3-a.b.c.10.d.5 1.2.3-a.b.c.5.d.100 +1.2.3-r2 1.2.3-r100 +1.2.3-r100 1.2.3-R2 diff --git a/rewrite-javascript/src/test/resources/npm-semver/equality.tsv b/rewrite-javascript/src/test/resources/npm-semver/equality.tsv new file mode 100644 index 00000000000..f18c055cd8c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npm-semver/equality.tsv @@ -0,0 +1,3 @@ +1.2.3-beta+build 1.2.3-beta+otherbuild +1.2.3+build 1.2.3+otherbuild + v1.2.3+build 1.2.3+otherbuild diff --git a/rewrite-javascript/src/test/resources/npm-semver/satisfies.tsv b/rewrite-javascript/src/test/resources/npm-semver/satisfies.tsv new file mode 100644 index 00000000000..9e775cf7f5b --- /dev/null +++ b/rewrite-javascript/src/test/resources/npm-semver/satisfies.tsv @@ -0,0 +1,178 @@ +1.0.0 - 2.0.0 1.2.3 true +^1.2.3+build 1.2.3 true +^1.2.3+build 1.3.0 true +1.2.3-pre+asdf - 2.4.3-pre+asdf 1.2.3 true +1.2.3-pre+asdf - 2.4.3-pre+asdf 1.2.3-pre.2 true +1.2.3-pre+asdf - 2.4.3-pre+asdf 2.4.3-alpha true +1.2.3+asdf - 2.4.3+asdf 1.2.3 true +1.0.0 1.0.0 true +>=* 0.2.4 true + 1.0.0 true +* 1.2.3 true +>=1.0.0 1.0.0 true +>=1.0.0 1.0.1 true +>=1.0.0 1.1.0 true +>1.0.0 1.0.1 true +>1.0.0 1.1.0 true +<=2.0.0 2.0.0 true +<=2.0.0 1.9999.9999 true +<=2.0.0 0.2.9 true +<2.0.0 1.9999.9999 true +<2.0.0 0.2.9 true +>= 1.0.0 1.0.0 true +>= 1.0.0 1.0.1 true +>= 1.0.0 1.1.0 true +> 1.0.0 1.0.1 true +> 1.0.0 1.1.0 true +<= 2.0.0 2.0.0 true +<= 2.0.0 1.9999.9999 true +<= 2.0.0 0.2.9 true +< 2.0.0 1.9999.9999 true +< 2.0.0 0.2.9 true +>=0.1.97 0.1.97 true +0.1.20 || 1.2.4 1.2.4 true +>=0.2.3 || <0.0.1 0.0.0 true +>=0.2.3 || <0.0.1 0.2.3 true +>=0.2.3 || <0.0.1 0.2.4 true +|| 1.3.4 true +2.x.x 2.1.3 true +1.2.x 1.2.3 true +1.2.x || 2.x 2.1.3 true +1.2.x || 2.x 1.2.3 true +x 1.2.3 true +2.*.* 2.1.3 true +1.2.* 1.2.3 true +1.2.* || 2.* 2.1.3 true +1.2.* || 2.* 1.2.3 true +* 1.2.3 true +2 2.1.2 true +2.3 2.3.1 true +~0.0.1 0.0.1 true +~0.0.1 0.0.2 true +~x 0.0.9 true +~2 2.0.9 true +~2.4 2.4.0 true +~2.4 2.4.5 true +~>3.2.1 3.2.2 true +~1 1.2.3 true +~>1 1.2.3 true +~> 1 1.2.3 true +~1.0 1.0.2 true +~ 1.0 1.0.2 true +~ 1.0.3 1.0.12 true +>=1 1.0.0 true +>= 1 1.0.0 true +<1.2 1.1.1 true +< 1.2 1.1.1 true +~v0.5.4-pre 0.5.5 true +~v0.5.4-pre 0.5.4 true +=0.7.x 0.7.2 true +<=0.7.x 0.7.2 true +>=0.7.x 0.7.2 true +<=0.7.x 0.6.2 true +~1.2.1 >=1.2.3 1.2.3 true +~1.2.1 =1.2.3 1.2.3 true +~1.2.1 1.2.3 1.2.3 true +~1.2.1 >=1.2.3 1.2.3 1.2.3 true +~1.2.1 1.2.3 >=1.2.3 1.2.3 true +>=1.2.1 1.2.3 1.2.3 true +1.2.3 >=1.2.1 1.2.3 true +>=1.2.3 >=1.2.1 1.2.3 true +>=1.2.1 >=1.2.3 1.2.3 true +>=1.2 1.2.8 true +^1.2.3 1.8.1 true +^0.1.2 0.1.2 true +^0.1 0.1.2 true +^0.0.1 0.0.1 true +^1.2 1.4.2 true +^1.2 ^1 1.4.2 true +^1.2.3-alpha 1.2.3-pre true +^1.2.0-alpha 1.2.0-pre true +^0.0.1-alpha 0.0.1-beta true +^0.0.1-alpha 0.0.1 true +^0.1.1-alpha 0.1.1-beta true +^x 1.2.3 true +x - 1.0.0 0.9.7 true +x - 1.x 0.9.7 true +1.0.0 - x 1.9.7 true +1.x - x 1.9.7 true +<=7.x 7.9.9 true +1.0.0 - 2.0.0 2.2.3 false +1.2.3+asdf - 2.4.3+asdf 1.2.3-pre.2 false +1.2.3+asdf - 2.4.3+asdf 2.4.3-alpha false +^1.2.3+build 2.0.0 false +^1.2.3+build 1.2.0 false +^1.2.3 1.2.3-pre false +^1.2 1.2.0-pre false +>1.2 1.3.0-beta false +<=1.2.3 1.2.3-beta false +^1.2.3 1.2.3-beta false +=0.7.x 0.7.0-asdf false +>=0.7.x 0.7.0-asdf false +<=0.7.x 0.7.0-asdf false +1.0.0 1.0.1 false +>=1.0.0 0.0.0 false +>=1.0.0 0.0.1 false +>=1.0.0 0.1.0 false +>1.0.0 0.0.1 false +>1.0.0 0.1.0 false +<=2.0.0 3.0.0 false +<=2.0.0 2.9999.9999 false +<=2.0.0 2.2.9 false +<2.0.0 2.9999.9999 false +<2.0.0 2.2.9 false +>=0.1.97 0.1.93 false +0.1.20 || 1.2.4 1.2.3 false +>=0.2.3 || <0.0.1 0.0.3 false +>=0.2.3 || <0.0.1 0.2.2 false +2.x.x 1.1.3 false +2.x.x 3.1.3 false +1.2.x 1.3.3 false +1.2.x || 2.x 3.1.3 false +1.2.x || 2.x 1.1.3 false +2.*.* 1.1.3 false +2.*.* 3.1.3 false +1.2.* 1.3.3 false +1.2.* || 2.* 3.1.3 false +1.2.* || 2.* 1.1.3 false +2 1.1.2 false +2.3 2.4.1 false +~0.0.1 0.1.0-alpha false +~0.0.1 0.1.0 false +~2.4 2.5.0 false +~2.4 2.3.9 false +~>3.2.1 3.3.2 false +~>3.2.1 3.2.0 false +~1 0.2.3 false +~>1 2.2.3 false +~1.0 1.1.0 false +<1 1.0.0 false +>=1.2 1.1.1 false +~v0.5.4-beta 0.5.4-alpha false +=0.7.x 0.8.2 false +>=0.7.x 0.6.2 false +<0.7.x 0.7.2 false +<1.2.3 1.2.3-beta false +=1.2.3 1.2.3-beta false +>1.2 1.2.8 false +^0.0.1 0.0.2-alpha false +^0.0.1 0.0.2 false +^1.2.3 2.0.0-alpha false +^1.2.3 1.2.2 false +^1.2 1.1.9 false +* not a version false +>=2 glorp false +>=2 false false +^1.0.0 2.0.0-rc1 false +1 - 2 2.0.0-pre false +1 - 2 1.0.0-pre false +1.0 - 2 1.0.0-pre false +1.1.x 1.0.0-a false +1.1.x 1.1.0-a false +1.1.x 1.2.0-a false +1.x 1.0.0-a false +1.x 1.1.0-a false +1.x 1.2.0-a false +>=1.0.0 <1.1.0 1.1.0 false +>=1.0.0 <1.1.0 1.1.0-pre false +>=1.0.0 <1.1.0-pre 1.1.0-pre false diff --git a/rewrite-javascript/src/test/resources/npmlock/README.md b/rewrite-javascript/src/test/resources/npmlock/README.md new file mode 100644 index 00000000000..e41fdd966fc --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/README.md @@ -0,0 +1,31 @@ +# npm lock engine fixtures + +Scenario fixtures for `NpmLockEngine` / `NpmLockWriter` tests. Each directory holds a +before/after manifest pair, the lock real npm produced for each, and the full +packuments for every package the edit moves, so the offline tests can assert the +engine's output **byte-identical** to real npm without network access. + +## Provenance + +Recorded with `./record.sh` against `https://registry.npmjs.org` on **2026-07-29** +using **npm 11.17.0** on **node v26.4.0** (macOS). Regenerating on a different npm +version may change emission details or resolution outcomes; re-record all scenarios +together and update this section. + +`locale-sorted-keys.txt` was generated with Node's `Intl` collator +(`arr.sort((a, b) => a.localeCompare(b, 'en'))` over ~2800 realistic lock keys and +random strings, node v26.4.0) and pins `NpmLockWriter`'s key-ordering comparator. + +## Scenarios + +| Directory | Edit | Engine behavior under test | +|---|---|---| +| `upgrade-leaf` | `is-number ^4.0.0 → ^6.0.0` | version move of a leaf pin | +| `range-satisfied` | `is-number ^6.0.0 → >=4.0.0` | pin already satisfies: no network, ranges only | +| `cascade-fails` | `is-odd ^2.0.0 → ^3.0.1` | new version forces a transitive move → fail loud (`package-lock.after.json` documents the cascade npm performs) | +| `remove-orphans` | drop dev `is-even` | orphan sweep of the abandoned subtree | +| `upgrade-orphans` | `chalk ^4.1.2 → ^5.0.0` | new version drops deps → sweep; `funding` string normalization | +| `add-leaf` | add `is-buffer ^2.0.5` | top-level (hoisted) addition | +| `override` | add `overrides: {"is-buffer": "1.1.5"}` | fail loud (`package-lock.after.json` documents npm nesting the overridden copy under its dependent — placement) | +| `dev-recolor` | drop prod `kind-of`, keep dev `is-number` | dev/optional flag recomputation on survivors | +| `scoped` | `@isaacs/string-locale-compare 1.0.1 → ^1.1.0` | scoped-name registry URL encoding | diff --git a/rewrite-javascript/src/test/resources/npmlock/add-leaf/http/is-buffer.json b/rewrite-javascript/src/test/resources/npmlock/add-leaf/http/is-buffer.json new file mode 100644 index 00000000000..5ec3b07e34d --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/add-leaf/http/is-buffer.json @@ -0,0 +1 @@ +{"_id":"is-buffer","_rev":"28-73311ada934bee2c9de88d107cbcfe1d","name":"is-buffer","description":"Determine if an object is a Buffer","dist-tags":{"latest":"2.0.5"},"versions":{"1.0.0":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^3.0.1"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"tape test/*.js"},"testling":{"files":"test/*.js","browsers":["ie/6..latest","chrome/4..latest","firefox/3..latest","safari/5.1..latest","opera/11.0..latest","iphone/6","ipad/6"]},"gitHead":"fdb526a9a5abd518bfc007f9f919bbd478744311","_id":"is-buffer@1.0.0","_shasum":"680b48b0cb42ee3d38f0955bcb9855ee945e96fd","_from":".","_npmVersion":"2.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"680b48b0cb42ee3d38f0955bcb9855ee945e96fd","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.0.tgz","integrity":"sha512-6jQz/P5E/2ZZvtEABMrCjBsGX+u/6asGpaGZlWgGoVkkoK+kO4E89ZByoOJyqRMES/K2ZKoF6hNaYRKPKW12ig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCu+gjaka98lin9rOIEiMslLTlYZ9+GDpgJVFYllZutTQIgHvF6yyqyG0hTDEBkD2hPNy3TZ0XEUSqdOMmQSqY6C4M="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.0.1":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^3.0.1","zuul":"^1.13.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"66496a59f1e0ed0d57bf4834113aa62ed874c9b7","_id":"is-buffer@1.0.1","_shasum":"d4050649838354e87ec59c964c1fa1f4bb7de00d","_from":".","_npmVersion":"2.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"d4050649838354e87ec59c964c1fa1f4bb7de00d","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.1.tgz","integrity":"sha512-v5AmIvDrnYZZuFRYKUvb12Z89TysfucZn9X5e7ZGo2eTGYhtpJrNaTDFAaKWzTRKgSKIYfg9/ekeH/HGaZ5d+Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHqy2oP7TAzbzrfvQB9WjDtVeHxX8fsGdn3KLeD63grOAiEAkdEZ0Cr9TPZ0RLWUHec2/VBeLLMIP+3ILdj5qwT06qQ="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.0.2":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"cad65fd0f6844c296c743c4ec521c130224de90e","_id":"is-buffer@1.0.2","_shasum":"f5c6c051d73f86f11b4ee14267cc1029fce261d0","_from":".","_npmVersion":"2.7.4","_nodeVersion":"0.12.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"f5c6c051d73f86f11b4ee14267cc1029fce261d0","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.2.tgz","integrity":"sha512-LxnVw0B8/L3u3LDQGh9k+c9h0eO9rEDup9f4itjqAZ68b5hvUnJTwmLtnuiuY+4WELfq13vu19kiFdxDBLqrGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICLyWm5reQS8J7CzRFptn7D077RU2fKHi6T2tG+3w91WAiEA/DPIf6pSovP1VL+8MBG/TnoYmO/YLRQLPOgjR0iDgfY="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.0":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"6ca106240e155ea4cfe13e2e1c83aadab91d2ec1","_id":"is-buffer@1.1.0","_shasum":"36f7850c0d077a71b041f3565664155f07035bd0","_from":".","_npmVersion":"2.14.2","_nodeVersion":"4.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"36f7850c0d077a71b041f3565664155f07035bd0","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.0.tgz","integrity":"sha512-wu87Ow/wnXpH9Ahk3X9HNEpEuFFeDtuG1+CRBPiprlwwR6FS5cCjQul3uuWP8z/xUa+YR3vb6UB9DqT+4KD6jg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdUQmUy+OKoxc650apjPrIfHMMu2p3/8YTpbEfHr5egwIhALFm6QMOQ56MuRCv/nmtXmJSr4dOXQ06aTJBdjYOj9rr"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.1":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"9ccd67d6ca6476d1cb7b38fd9fc7d9d71d212f5c","_id":"is-buffer@1.1.1","_shasum":"3058de9ca454564e8bbe5b8dd2719a8d7089e7d7","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.3","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"3058de9ca454564e8bbe5b8dd2719a8d7089e7d7","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.1.tgz","integrity":"sha512-03w4ew2ozAWFhFOYg8YE+iuXmysBtd4mdDK8wOQK56j5E9iXpdE/Ael/vxrxW5IVOPn+tTTCbgH9rfrOsEermg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEkLQedBqPfASnZpdpre9GZN3yZFyCnMxxw58SoIMZRRAiBRjR1fGQeUHLtA3PJ18+bSl766j69C81b18io9Yq3oQg=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.2":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^5.4.1","tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"ba9a9f359e4412c90c583e14492072c9f4f2d45c","_id":"is-buffer@1.1.2","_shasum":"fa1226588fa0048b005c47e4fb1bb1555d5edeaa","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.2.6","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"fa1226588fa0048b005c47e4fb1bb1555d5edeaa","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.2.tgz","integrity":"sha512-+SAQKwgmiLKfRw7j5xmb2NGzekvz2bTSsNdMDDg4WkXBQvcB5dVz3oKWHQid8oQCMJzDR2CxRqx8XqZD9voH3Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEgqFfCbYOW/j+D9RNNvTTJudba9Jvw/FPfUzWYnU0Q8AiA5chCLOjpiqHxjnJjo0UnhXt8tGvTB195hE98WpSwdBw=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.3":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.3","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^6.0.5","tape":"^4.0.0","zuul":"^3.0.0"},"engines":{"node":">=0.12"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"dfd658d887e6b63254b89d22af1a755a39313455","homepage":"https://github.com/feross/is-buffer","_id":"is-buffer@1.1.3","_shasum":"db897fc3f7aca2d50de94b6c8c2896a4771627af","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"db897fc3f7aca2d50de94b6c8c2896a4771627af","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz","integrity":"sha512-x2bhGIVgreQwjcLvzJRsdrs2wyguhnLgfrOWIK/+6rEJmWO3IS3VedcLYcGZiVwlCzhIIR8JngztGjJyqEs5Nw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSGBDaNE3l/CHjUBIMxoqZtodlqbjeeiu+xzI8sUJsLgIgBV0/eSbTUETloInCVdjj80k1P3mvn7nd0flhGQ72edw="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.3.tgz_1457390977775_0.6384289276320487"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.4":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.4","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^7.0.0","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"fd1a429f6ab8092f2e39cb5cc7175b5d9a986c31","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.4","_shasum":"cfc86ccd5dc5a52fa80489111c6920c457e2d98b","_from":".","_npmVersion":"2.15.1","_nodeVersion":"0.10.46","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"cfc86ccd5dc5a52fa80489111c6920c457e2d98b","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz","integrity":"sha512-LdKAPZcV+EfT6PvN90Un/Rnn1g8cL1BfzEBdz6d3Y6CUzMyUVWHewXxyuiNFkLwRKgpDMYHrocdqjMsYTDkOow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1P8GIhF9+E6/P2FbZolCrtNplQtwv4jHQZ7xT8b2QcQIhAMl5wfPPyGfOABP3B3rVaUdXdxoR65VwiuzqmecjG1Vb"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.4.tgz_1470267365943_0.6724087686743587"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.5":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.5","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"56dc50e7b271c7d2968269430cbd4f717bbcf6c0","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.5","_shasum":"1f3b26ef613b214b88cbca23cc6c01d87961eecc","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"1f3b26ef613b214b88cbca23cc6c01d87961eecc","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz","integrity":"sha512-miqftL8E53hH0dtQqLdN+3JwClyJiITcif3gy+RiUlnLJUhEwdyRC29/gpYbuC9IhazGSnP8TjbvxWw2AZylWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAv+Vaqofnno8Drwu3I23xGZGjOI7wZXM8aLjw8Tq1fSAiEAzZLzlH8vWqNn0uR7z2sv9gXoOGQlHlmqG5Aq06YWz8E="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.5.tgz_1489193465717_0.9356542676687241"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.6":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.6","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"1e84e7ee31cf6b660b12500f3111a05501da387f","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.6","_npmVersion":"5.5.1","_nodeVersion":"8.6.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==","shasum":"efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDQAnODX01K6w5cJdtd+M5OyeiiFZL0r/VpvrwjdJcEEAiEA1n9Pq+avL75FrFQdoA84fBlUmeqf25sOcbsEXxHQh7c="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer-1.1.6.tgz_1508967388794_0.03916449216194451"},"directories":{}},"2.0.0":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"1a8ab13257c3bb000b51ee1892c194a1be9f2759","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-wsnW8g48qGzmZRy7yregikay4LbHR4yKdiGIhNnZobvTlEEy9O8cOh7jmo7J83nYdJM+4Qi635zgq4YLQwSt/A==","shasum":"224d784b0ca3dcc2ec42c5e75a4150fb7d8fdede","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBhK78myUJs2IKqHkIiLrZKKKsxNl/4CN6blEyu09hbNAiEAmyDi9jFzNTtgmh8Af5YCUxdCnrK1nvQS6e+kGojXpJs="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer-2.0.0.tgz_1517211799580_0.7924200457055122"},"directories":{}},"2.0.1":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.4","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"f5b7d4018818037cc3bd88e6e5d85b15e0012552","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.1","_npmVersion":"5.7.1","_nodeVersion":"8.10.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-eDHjNN2G4M3hNNPs4dWwomvv0oNChLEAgoJ1TUiBNbEfQDrfG+kA8BLmBKh+A30klH8tOVimp5j5IDkmEBcEsA==","shasum":"e14769efa70ba71162bda9852dc32362e01cca07","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.1.tgz","fileCount":7,"unpackedSize":6009,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB65TjJXMz/JTM1KPIFXv89jmXZuHhHG4rsuynzAZ87tAiAFwTmYimVL+7dmRVOKNiF2Y5ceXLdeQcS3qoxoYbRtuA=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.1_1521286431970_0.9562908337278884"},"_hasShrinkwrap":false},"2.0.2":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.4","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"f9ef52cfcf235a84ce8167120b539b540a3a60e4","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.2","_npmVersion":"5.7.1","_nodeVersion":"8.10.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-imvkm8cOGKeZ/NwkAd+FAURi0hsL9gr3kvdi0r3MnqChcOdPaQRIOQiOU+sD40XzUIe6nFmSHYtQjbkDvaQbEg==","shasum":"f83a0c5bc453f6431bf83cc2ceff6cbc9d50a83b","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.2.tgz","fileCount":5,"unpackedSize":5234,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuyQCp0CPE+UpLWsBx4jMLhoHEDV77g0HVAJcce17PnQIgZzKEUcH/KDGY16okocQ4xE8nDtJEcqjFSmJBK1rEH4A="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.2_1521286476893_0.01566582587333687"},"_hasShrinkwrap":false},"2.0.3":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.3","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.7","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"e05c7852e1a978b81c7eb6d677c861a7dc935ead","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.3","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==","shasum":"4ecf3fcf749cbd1e472689e109ac66261a25e725","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz","fileCount":4,"unpackedSize":4263,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbHF+HCRA9TVsSAnZWagAAJV8P/1beDL56nRgP75wKwit1\nu7VHWrRQpqFhqmWs2EFEfOtfAh2CsHUJjfuYcG+eI9Lzblc5uJ1YzDZOEuEn\nRz1in3WDtuR/+YUxzVFla/jTUUFql/PC747aDXnaPd1HcWsxJBmvbtDfl9bU\nnsbahrPd3asehz9quWdDSfK8q7u1/S1ZnbykZJuJLLfpOyM7zRqAYYVUAA/1\nm/58ITilRc2ewIn0cWqsU6rmJYAPP8jpIm2z0DK0sWriuPhaNxKeFspW5MDB\ncphOgno7wy733FH7KK5pDVnKLLk3ABAtjV2DjrmF03Nqk+TPb0lCvEaFDcx7\nUXJLrek2cPXzwkixfzQ6q5GQFvZFQ88Ts7nXzGSo1+dHm1sfEXFEp8HpKfA2\nB+YhzCtEWYTWzIteEgfTD6s6zk6TgWE00bBZ98NUYnAfIEuTBMuuKSJMWbVh\nghnRWsSECCgyYtLI0lEASNHaCTqohgISJjQWEi4EN7OXXo5BinXJfuNfqzNm\nJwqbL3PiHmUSMfNFIMeWWWI+8jZ6EVQpw27C0z4L8JdUC6gFfHJ5Z0jPLmfv\nAvJK2w4oYnnNP2Fw4Jg5HHE/lkXTyabwOAT4O9zqUfVPieNnAFvLgOdlo6kD\nUXgPJ+YqHTY6n2l/s7WciMuV9u2AO+WtSKB+fpm0yHENKwUe1Wc2Ln+sJTn/\nnQSL\r\n=FeKt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/5ae6Fzj0Jx08b/2/ksoyAZF9i6wHFE+vow/LmwGhLgIhAO9/EiXe44IRHmU3SMYsLzCLUsZTctIyJfMqIu4DXNwe"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.3_1528586118955_0.08977150560838787"},"_hasShrinkwrap":false},"2.0.4":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.4","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"^2.0.3","standard":"*","tape":"^4.11.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"gitHead":"65d2f6ba6c4e336be90c3cb6a656a69ce8f24210","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.4","_nodeVersion":"12.10.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==","shasum":"3e572f23c8411a5cfd9557c849e3665e0b290623","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz","fileCount":5,"unpackedSize":4491,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdktqzCRA9TVsSAnZWagAAV5kQAJz2tApv60yY1cu9hU+Q\nuCPH64nGM/49IWWLtcX8dDjV1PkNwtp32MpspkMMmPE8nfzAuDaHequ6AEjP\nD/+usRbT8PoD0dDixzlR5a9H+FFohDvJOXVzNATQna/b9Q2dj7XOjEnhsEf9\nbRkJq2U1N/Qb+9Rgg9sgLmsZR1UCCdTR5PKPpVbHs0axQyeghaXPlenQoa20\nq2aDE/xQihsI4If3aQmLkrkpUYUsjDwEYTKXTPQNosGmQg5XsZK89PCFLVu5\n9t0qAZffJJFP+HER7BfszmE5F4yDFhvBNWyu2NtPtv0KiSNkGYo/D6Xd55j8\nIfq5SHuvc/Jy7fyrg3HRUBVzYJqOtlICjLdHv4L573eNPaJryR1TIzcMY33K\nBuHBjJ4ZSlGi0spS8JnR+xbT9JQ1siNDrl9gaAzoSvmJi6CnSTwusb6Ht2fG\nXs7a6v5lbClrONeOSbgTJWv4yC9rFmTr1YfrqVrVJG++4Q588AU4PfRn5KlS\nh//hylruEZrlAhFsSjWsK1AJLd+mNDchaFzWQ78bvosOw6mez/aGz2LBdlX5\nx74RvWY07lfwPwDjCvO+dCbKsSuAhigDUOj+I19ugYkq+LWP0zDFUtB1NM1i\nFqQYChp/FaCdMRKqNGwoN9LL20B9gSXNZW4R85AxvPn0wxvZl/PL7KH6riZM\n6ua4\r\n=DYpP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMPwxaKFo0xSzRWmLS86WkiEalo9AF+tGcZaR1j4IY7QIhAPfgXxctuV8LpKNOvYyhv/Q0drYAk/3Htr2wronuuRTL"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmUser":{"name":"feross","email":"feross@feross.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.4_1569905330837_0.24488814934632286"},"_hasShrinkwrap":false},"2.0.5":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.5","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"^3.0.0","standard":"*","tape":"^5.0.1"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"funding":[{"type":"github","url":"https://github.com/sponsors/feross"},{"type":"patreon","url":"https://www.patreon.com/feross"},{"type":"consulting","url":"https://feross.org/support"}],"gitHead":"ec4bf3415108e8971375e6717ad63dde752faebf","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.5","_nodeVersion":"14.15.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==","shasum":"ebc252e400d22ff8d77fa09888821a24a658c191","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz","fileCount":5,"unpackedSize":4587,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoa1GCRA9TVsSAnZWagAAfIwQAJr4549srmyEUJaCF5Pd\nyQ3SwaxS4IyycILtQyyyOBHlbLcAS7LvuatpnyrRDr0bSx2EEHqVfo9jyuGw\n5L17J1WuUbddlCikCy1z0jzHROW1zR8inwd8Li4f/1FMbHlbTgWKpmQ/P6YI\nkYdP83CKgyVIKr6H8Qxk4oU5aGLN/YGT8AHlVLRL1N/d1m6c92QKTQnroEzY\naYjiKdpXeUfXq0vmuosT39mSBUFvNWEtkN51sgJyS9jBFMEcdA/SzFULgBfN\niScNvarNUCFG6UpIoagqYwwqQTrmrucCVoC8G1zkVgPBUYIKKeTq2hbAg4rP\n2yeHrEWYb8JsdkxfzSNR7xEsTeRx9+n/zY/QxQ/Bpzt5eiYFSNVU+xXOn6TG\npqEKgE2v0rdcGYMpMZCvr9TA5iChjEWg/LFlygCKGc9r5b5kIUcQ2hWU5+Hw\nyNpA5xwsev5erAYd8fq8hz7np8mnBj3d5hWLVTdFEvKBgTx3FcrVWPxNnEzc\nhmM5MndgOoiosIW6/Aq0UArTYYTnb+OIxZhscu+N3QMxjkX0DNfefGquy7AU\ndkA3ZG3TQSsoB1Qxblr4/CxbU32wIeBzfXEfddbBLl8zQOmf/BDKY+sZs97y\nUg0E9CkpWwMeVSxSDXOjuXMaIl4YehcO7hp9Xn3napfZ3R+dMPnurROwb9MC\nAR/e\r\n=DLTF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQm0iQk4fBuBsWIfDybHoSHV2rBcSai2o2gjHAdNyXQAIhAMg/omtFuJ9DyNMJQawXYSs2D3NXfDZO7Fc5b1FusD+F"}]},"_npmUser":{"name":"feross","email":"feross@feross.org"},"directories":{},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.5_1604431173638_0.6067186377033973"},"_hasShrinkwrap":false}},"readme":"# is-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]\n\n[travis-image]: https://img.shields.io/travis/feross/is-buffer/master.svg\n[travis-url]: https://travis-ci.org/feross/is-buffer\n[npm-image]: https://img.shields.io/npm/v/is-buffer.svg\n[npm-url]: https://npmjs.org/package/is-buffer\n[downloads-image]: https://img.shields.io/npm/dm/is-buffer.svg\n[downloads-url]: https://npmjs.org/package/is-buffer\n[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg\n[standard-url]: https://standardjs.com\n\n#### Determine if an object is a [`Buffer`](http://nodejs.org/api/buffer.html) (including the [browserify Buffer](https://github.com/feross/buffer))\n\n[![saucelabs][saucelabs-image]][saucelabs-url]\n\n[saucelabs-image]: https://saucelabs.com/browser-matrix/is-buffer.svg\n[saucelabs-url]: https://saucelabs.com/u/is-buffer\n\n## Why not use `Buffer.isBuffer`?\n\nThis module lets you check if an object is a `Buffer` without using `Buffer.isBuffer` (which includes the whole [buffer](https://github.com/feross/buffer) module in [browserify](http://browserify.org/)).\n\nIt's future-proof and works in node too!\n\n## install\n\n```bash\nnpm install is-buffer\n```\n\n## usage\n\n```js\nvar isBuffer = require('is-buffer')\n\nisBuffer(new Buffer(4)) // true\nisBuffer(Buffer.alloc(4)) //true\n\nisBuffer(undefined) // false\nisBuffer(null) // false\nisBuffer('') // false\nisBuffer(true) // false\nisBuffer(false) // false\nisBuffer(0) // false\nisBuffer(1) // false\nisBuffer(1.0) // false\nisBuffer('string') // false\nisBuffer({}) // false\nisBuffer(function foo () {}) // false\n```\n\n## license\n\nMIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org).\n","maintainers":[{"name":"feross","email":"feross@feross.org"}],"time":{"modified":"2022-06-19T02:37:46.020Z","created":"2014-10-31T01:58:42.247Z","1.0.0":"2014-10-31T01:58:42.247Z","1.0.1":"2014-10-31T03:37:00.562Z","1.0.2":"2015-05-05T01:52:11.559Z","1.1.0":"2015-09-17T05:02:36.041Z","1.1.1":"2016-01-03T21:09:34.798Z","1.1.2":"2016-01-29T12:52:12.824Z","1.1.3":"2016-03-07T22:49:39.950Z","1.1.4":"2016-08-03T23:36:07.367Z","1.1.5":"2017-03-11T00:51:05.973Z","1.1.6":"2017-10-25T21:36:28.871Z","2.0.0":"2018-01-29T07:43:20.568Z","2.0.1":"2018-03-17T11:33:52.032Z","2.0.2":"2018-03-17T11:34:36.945Z","2.0.3":"2018-06-09T23:15:19.035Z","2.0.4":"2019-10-01T04:48:50.958Z","2.0.5":"2020-11-03T19:19:33.762Z"},"homepage":"https://github.com/feross/is-buffer#readme","keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"license":"MIT","readmeFilename":"README.md","users":{"mojaray2k":true,"monjer":true,"rocket0191":true,"edwardxyt":true}} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.after.json new file mode 100644 index 00000000000..2db14cde1cf --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.after.json @@ -0,0 +1,60 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-buffer": "^2.0.5", + "is-odd": "^3.0.1" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz", + "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==", + "license": "MIT", + "dependencies": { + "is-number": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.before.json new file mode 100644 index 00000000000..e65266a1b4c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package-lock.before.json @@ -0,0 +1,36 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz", + "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==", + "license": "MIT", + "dependencies": { + "is-number": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json new file mode 100644 index 00000000000..93506e37d87 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json @@ -0,0 +1,8 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-buffer": "^2.0.5", + "is-odd": "^3.0.1" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json.before b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json.before new file mode 100644 index 00000000000..3f68122bbea --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/add-leaf/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/cascade-fails/http/is-odd.json b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/http/is-odd.json new file mode 100644 index 00000000000..14f4cea4a15 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/http/is-odd.json @@ -0,0 +1 @@ +{"_id":"is-odd","_rev":"17-b1f96ea3c62e53b66584e3743a1945a3","name":"is-odd","dist-tags":{"latest":"3.0.1"},"versions":{"0.1.0":{"name":"is-odd","version":"0.1.0","keywords":["array","count","even","filter","integer","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@0.1.0","maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"1031f78cac2710cba44820e73c898571bb83d3c3","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-0.1.0.tgz","integrity":"sha512-3RKAybrJxq3zCUC+TJ5Ao0sBsbacAT3OBeNVcCbsQsHUC70qWK2R4JsIvax4OTjeGWnB8FumAWATUtS1jd+KYw==","signatures":[{"sig":"MEYCIQC0Up0F8WXEWA3Vfjh5n6qWp+kO61ftwLMfBD580D9pZAIhAOn4/7a6erENjhSjCOD6RSLDpFph8MqA2a1bbi8ZSnoP","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","files":["index.js"],"_shasum":"1031f78cac2710cba44820e73c898571bb83d3c3","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"https://github.com/jonschlinkert/is-odd","type":"git"},"_npmVersion":"2.5.1","description":"Returns true if the given number is odd.","directories":{},"_nodeVersion":"0.12.0","dependencies":{"is-number":"^1.1.0"},"devDependencies":{"mocha":"*","should":"*"}},"0.1.1":{"name":"is-odd","version":"0.1.1","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@0.1.1","maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"51508f7d39eafb0282fbb98957b2d1d28e72a3e7","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-0.1.1.tgz","integrity":"sha512-MryzYFJV3tn8l7PJdvCLVJvwjB3zdS+qKdopFQyo9uOlJ4AHeLoaIDElZTwDvcwk/vmcNqoIob2bBN4pFEsYCg==","signatures":[{"sig":"MEYCIQDu3TG2/++wuCRCLdBQI1g7vkjzEy2jQbBabe6RFL2/UAIhAKiOVQECOwXs/cb59+dX7fsl+FfPKKMJS1oegklcYuqz","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":[]},"reflinks":["verb","verb-generate-readme"]},"_from":".","files":["index.js"],"_shasum":"51508f7d39eafb0282fbb98957b2d1d28e72a3e7","engines":{"node":">=0.10.0"},"gitHead":"b8fc75839e341f23e2d7cb2d4b6a173ccbc1e364","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"3.10.3","description":"Returns true if the given number is odd.","directories":{},"_nodeVersion":"6.7.0","dependencies":{"is-number":"^1.1.0"},"devDependencies":{"mocha":"^3.2.0","gulp-format-md":"^0.1.11"},"_npmOperationalInternal":{"tmp":"tmp/is-odd-0.1.1.tgz_1481095079315_0.8302227731328458","host":"packages-12-west.internal.npmjs.com"}},"0.1.2":{"name":"is-odd","version":"0.1.2","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@0.1.2","maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"bc573b5ce371ef2aad6e6f49799b72bef13978a7","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-0.1.2.tgz","integrity":"sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==","signatures":[{"sig":"MEQCIHI63jfRjPRbhpolQPjSEwwTdVf8yV/im1aqm5QrLDrbAiBPeyyXzmbqFY+l6K7EFNmlKaVmC8rMF7inILRu3jT9NQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":[]},"reflinks":["verb","verb-generate-readme"]},"_from":".","files":["index.js"],"_shasum":"bc573b5ce371ef2aad6e6f49799b72bef13978a7","engines":{"node":">=0.10.0"},"gitHead":"59270f5a05b03bdeb0b06c95d922deb59ae31923","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"4.6.1","description":"Returns true if the given number is odd.","directories":{},"_nodeVersion":"7.7.3","dependencies":{"is-number":"^3.0.0"},"devDependencies":{"mocha":"^3.2.0","gulp-format-md":"^0.1.11"},"_npmOperationalInternal":{"tmp":"tmp/is-odd-0.1.2.tgz_1495890277574_0.012756465701386333","host":"s3://npm-registry-packages"}},"1.0.0":{"name":"is-odd","version":"1.0.0","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@1.0.0","maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"http://dym.sh","name":"DYM"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"3b8a932eb028b3775c39bb09e91767accdb69088","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz","integrity":"sha512-yIhxkKCK7pZnj48WBvaTQ36Or7PymGYqmZrSNqkrhmU3pakkp2TWhuN7hH25bqJgH+Xq4IZ3QNd3+QVshldEHA==","signatures":[{"sig":"MEQCIHPczqNcas1Hy0uIrewgEkKs4DS2N2r3E8VjhvFqaM3yAiAO2TKhXzzkA+HS3GlWWNzPmwbf5MqYzxVFkJP/8wFY6w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":["exponential-moving-average","is-even","sma"]}},"_from":".","files":["index.js"],"_shasum":"3b8a932eb028b3775c39bb09e91767accdb69088","engines":{"node":">=0.10.0"},"gitHead":"71747ca9a8324f9201205ad46a09fd3e60250edb","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"4.6.1","description":"Returns true if the given number is odd.","directories":{},"_nodeVersion":"7.7.3","dependencies":{"is-number":"^3.0.0"},"devDependencies":{"mocha":"^3.2.0","gulp-format-md":"^0.1.11"},"_npmOperationalInternal":{"tmp":"tmp/is-odd-1.0.0.tgz_1495909096816_0.9196002101525664","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"is-odd","version":"2.0.0","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@2.0.0","maintainers":[{"name":"doowb","email":"brian.woodward@gmail.com"},{"name":"jonschlinkert","email":"github@sellside.com"}],"contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"https://dym.sh","name":"DYM"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"},{"url":"www.rouvenwessling.de","name":"Rouven Weßling"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"7646624671fd7ea558ccd9a2795182f2958f1b24","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz","integrity":"sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==","signatures":[{"sig":"MEUCICBh5NPa7ZKJMYqhDcFMHzEdMpgvxa2rhLt5k4pUCA8TAiEAmWfGhzoPInC5t0pFQ+5pkPrqlulGkX1QwauXh3tpoXY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":["exponential-moving-average","is-even","sma"]}},"files":["index.js"],"engines":{"node":">=0.10.0"},"gitHead":"b29f7e82fc879ad23e925fd669f624c131e3e307","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"5.5.1","description":"Returns true if the given number is odd.","directories":{},"_nodeVersion":"8.7.0","dependencies":{"is-number":"^4.0.0"},"devDependencies":{"mocha":"^4.0.1","gulp-format-md":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/is-odd-2.0.0.tgz_1509514503241_0.6080242525786161","host":"s3://npm-registry-packages"}},"3.0.0":{"name":"is-odd","version":"3.0.0","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@3.0.0","maintainers":[{"name":"doowb","email":"brian.woodward@gmail.com"},{"name":"jonschlinkert","email":"github@sellside.com"}],"contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"https://dym.sh","name":"DYM"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"},{"url":"www.rouvenwessling.de","name":"Rouven Weßling"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"299227de776cc212813d674ffae0dcde1d9618af","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-3.0.0.tgz","fileCount":4,"integrity":"sha512-204vE5IJ0Cd6pA6x1dMyLooGk6/xeKuq90imFuJN/ndMDBP4Sk9tJpBlTedHPvt6KDbtTDTsjVzzgctFqNV7FQ==","signatures":[{"sig":"MEYCIQCOx0OcsEhJhYUaIn9rWNS6n7L4dWX0crWKiC3r/6f+kAIhAJjl8jRUWpUuB59QXK3R9jCL1H36M8GmqiFsNJxjc94p","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6689,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDubYCRA9TVsSAnZWagAAFfoQAJP21QulOJ/tXdogFRAC\nUwdJeiRI4ON79/QvaTPDsZyRZ3zre7crTqAAHMXEMMHuFvAlZhIeoSAw6UEU\nudoPZvgRPhUOfFK9ACJ74bVOVGLp5K+GcdprvZUZAPn54H8WWrpZaTF4lFyr\nsUva33wOx/PgnDYBcn65i7CZ3PC/u88FilZhyag2gX7Ffu8PyajHyOi98TUG\nhVkzb7wF0DhcezGHIDUXe3M7hetCY3gIkwGQsQWhWCV8CNuqG7UUOCG4LoNt\nDfvzhzWoBYHImBay0oFNax1a/UwWK2oDKb+3hlQzHi4jXAS02V+xkc3SC9vK\nhJqA1v4fNS73bTrE3Gk8pvAEiDbW39R4ZMfQbI9yfihI6Jcg4MY9EjaJW5g6\nwda0/Fx3NSWnJkAdbWl5Jyz+x6oN42kZ2+yFqqED1g0FiKt9AbGH4n31RH4M\nX5dNcGuLB+WrEOZ8SvTu8BKDz2lw91Otey0Wu5Y+j+ppHmuKwbzrDyqE0OZf\nz0kLwfN+EhYScGlN0b3eq5ssB6mifcE/wksLE+MWoYfCzB4rQYH/+BqxNd2C\nQ5HMewQKOT/w3QXkQUyvRKufhiCCC0lyIFLh/9lHwhuegY+FaE777AvBzsGy\nSAoTpGTb7edqEOorwdd1FL5/0jJ8suLSQXSfv051ZyzbG/gJdm17xPKfS1fJ\nMz9h\r\n=mJrU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":["exponential-moving-average","is-even","sma"]}},"files":["index.js"],"engines":{"node":">=4"},"gitHead":"75e749a7926a3ae2dfd5b2eaab6d15956f73381a","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"6.0.1","description":"Returns true if the given number is odd, and is an integer that does not exceed the JavaScript MAXIMUM_SAFE_INTEGER.","directories":{},"_nodeVersion":"10.0.0","dependencies":{"is-number":"^6.0.0"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^3.5.3","gulp-format-md":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/is-odd_3.0.0_1527703255498_0.6094765546992205","host":"s3://npm-registry-packages"}},"3.0.1":{"name":"is-odd","version":"3.0.1","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","_id":"is-odd@3.0.1","maintainers":[{"name":"doowb","email":"brian.woodward@gmail.com"},{"name":"jonschlinkert","email":"github@sellside.com"}],"contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"https://dym.sh","name":"DYM"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"},{"url":"www.rouvenwessling.de","name":"Rouven Weßling"}],"homepage":"https://github.com/jonschlinkert/is-odd","bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"dist":{"shasum":"65101baf3727d728b66fa62f50cda7f2d3989601","tarball":"https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz","fileCount":4,"integrity":"sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==","signatures":[{"sig":"MEUCIQCMOGfdVwpDV0N3zGD53ALBsYE5kZQYLWIB3+N7azYZVQIgAvuHQ8A7YhfAH29wbfqe1ZCmHbaByq1ns9ovSgbw+4I=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6510,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbEFVmCRA9TVsSAnZWagAA4OoP/1JqMTJChn+EZEZUOQxh\nqrdWNeXXjMn2I8SknESo/qEjMJx+hSsovfEm3sDbh8sT0S1gHJMJ3/AML/uT\n6dd4tFSJUF9hD5zGjo95hEKSunnBnKIS39Vui26XKf86axjq4AzCvUWmtkMd\ntwQ2iiAX+sAFtfcNv7phJkjr90OYLQsL9fEAiSbVG25fnobZEX7eD1UuHfHI\nFY/RHDgQ357r4smwLAvEy90Szr5L0sw+qs3NPn7D1jlMKeQ8uwzwEmQuNw2K\nP0VSo69jQNa/8+usCCX+Y6IrORx5cNSjQSgUrHQYrf9O2VHLXKm37PaHlGbN\nWmC7e67OK+zqyVlIwmpOTmS5ZlT85b7R9AyyZv/BHnyfkLZ8z0nqCqO6zlY/\nawfBwIq0eWTZp4SS3q0y/jg1W2+KL/Kk3ST70VFl+gJmy4I9BSTnyU0Cb1YH\nXq8qXpAbkznlpY23awbhDx+v3OZ9Tc3pSpxM3vbNFr288H8B9TzIFbmeDwnx\nhx5wNb/6UwyqQv0iussW4ZtVZyiWJ1F1rZOzNQa3jSz3pMiNeOMdXR9mlH35\n/BviGk8txvQtyQiXsTjl1CREM3CyE+kqimMwQ7x0cEFKHuJMxaTd//6TvrLk\nu1BiYYznJnPyMF8Nzw//vw93r9UUY9a7WrpW36GjnYk6hhHBIbf+D7iVZZIO\nj+a+\r\n=Dd8F\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","verb":{"toc":false,"lint":{"reflinks":true},"tasks":["readme"],"layout":"default","plugins":["gulp-format-md"],"related":{"list":["exponential-moving-average","is-even","sma"]}},"files":["index.js"],"engines":{"node":">=4"},"gitHead":"a80ee0d831a8ee69f1fad5b4673491847975eb26","scripts":{"test":"mocha"},"_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"_npmVersion":"6.0.1","description":"Returns true if the given number is odd, and is an integer that does not exceed the JavaScript MAXIMUM_SAFE_INTEGER.","directories":{},"_nodeVersion":"10.0.0","dependencies":{"is-number":"^6.0.0"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^3.5.3","gulp-format-md":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/is-odd_3.0.1_1527797093116_0.1399721569178909","host":"s3://npm-registry-packages"}}},"time":{"created":"2015-02-24T05:53:13.392Z","modified":"2026-04-14T14:26:11.557Z","0.1.0":"2015-02-24T05:53:13.392Z","0.1.1":"2016-12-07T07:18:01.205Z","0.1.2":"2017-05-27T13:04:38.481Z","1.0.0":"2017-05-27T18:18:17.696Z","2.0.0":"2017-11-01T05:35:04.104Z","3.0.0":"2018-05-30T18:00:55.554Z","3.0.1":"2018-05-31T20:04:53.306Z"},"bugs":{"url":"https://github.com/jonschlinkert/is-odd/issues"},"author":{"url":"https://github.com/jonschlinkert","name":"Jon Schlinkert"},"license":"MIT","homepage":"https://github.com/jonschlinkert/is-odd","keywords":["array","count","even","filter","integer","is","math","numeric","odd","string"],"repository":{"url":"git+https://github.com/jonschlinkert/is-odd.git","type":"git"},"description":"Returns true if the given number is odd, and is an integer that does not exceed the JavaScript MAXIMUM_SAFE_INTEGER.","contributors":[{"url":"http://brainstorage.me/semigradsky","name":"Dmitry Semigradsky"},{"url":"https://dym.sh","name":"DYM"},{"url":"http://twitter.com/jonschlinkert","name":"Jon Schlinkert"},{"url":"www.rouvenwessling.de","name":"Rouven Weßling"}],"maintainers":[{"name":"doowb","email":"brian.woodward@gmail.com"},{"name":"jonschlinkert","email":"github@sellside.com"}],"readme":"# is-odd [![NPM version](https://img.shields.io/npm/v/is-odd.svg?style=flat)](https://www.npmjs.com/package/is-odd) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-odd.svg?style=flat)](https://npmjs.org/package/is-odd) [![NPM total downloads](https://img.shields.io/npm/dt/is-odd.svg?style=flat)](https://npmjs.org/package/is-odd) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-odd.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-odd)\n\n> Returns true if the given number is odd, and is an integer that does not exceed the JavaScript MAXIMUM_SAFE_INTEGER.\n\nPlease consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.\n\n## Install\n\nInstall with [npm](https://www.npmjs.com/):\n\n```sh\n$ npm install --save is-odd\n```\n\n## Usage\n\nWorks with strings or numbers.\n\n```js\nconst isOdd = require('is-odd');\n\nconsole.log(isOdd('1')); //=> true\nconsole.log(isOdd('3')); //=> true\n\nconsole.log(isOdd(0)); //=> false\nconsole.log(isOdd(2)); //=> false\n```\n\n## About\n\n

\nContributing\n\nPull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).\n\n
\n\n
\nRunning Tests\n\nRunning 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:\n\n```sh\n$ npm install && npm test\n```\n\n
\n\n
\nBuilding docs\n\n_(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.)_\n\nTo generate the readme, run the following command:\n\n```sh\n$ npm install -g verbose/verb#dev verb-generate-readme && verb\n```\n\n
\n\n### Related projects\n\nYou might also be interested in these projects:\n\n* [exponential-moving-average](https://www.npmjs.com/package/exponential-moving-average): Calculate an exponential moving average from an array of numbers. | [homepage](https://github.com/jonschlinkert/exponential-moving-average \"Calculate an exponential moving average from an array of numbers.\")\n* [is-even](https://www.npmjs.com/package/is-even): Return true if the given number is even. | [homepage](https://github.com/jonschlinkert/is-even \"Return true if the given number is even.\")\n* [sma](https://www.npmjs.com/package/sma): Calculate the simple moving average of an array. | [homepage](https://github.com/doowb/sma \"Calculate the simple moving average of an array.\")\n\n### Contributors\n\n| **Commits** | **Contributor** | \n| --- | --- |\n| 20 | [jonschlinkert](https://github.com/jonschlinkert) |\n| 2 | [dym-sh](https://github.com/dym-sh) |\n| 1 | [Semigradsky](https://github.com/Semigradsky) |\n| 1 | [realityking](https://github.com/realityking) |\n\n### Author\n\n**Jon Schlinkert**\n\n* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)\n* [GitHub Profile](https://github.com/jonschlinkert)\n* [Twitter Profile](https://twitter.com/jonschlinkert)\n\n### License\n\nCopyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).\nReleased under the [MIT License](LICENSE).\n\n***\n\n_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 31, 2018._","readmeFilename":"README.md","users":{"gugadev":true,"hackey9":true,"zkochan":true}} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.after.json new file mode 100644 index 00000000000..e65266a1b4c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.after.json @@ -0,0 +1,36 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz", + "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==", + "license": "MIT", + "dependencies": { + "is-number": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.before.json new file mode 100644 index 00000000000..b02495dd987 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package-lock.before.json @@ -0,0 +1,36 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^2.0.0" + } + }, + "node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "license": "MIT", + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json new file mode 100644 index 00000000000..3f68122bbea --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json.before b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json.before new file mode 100644 index 00000000000..292dfc50c70 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/cascade-fails/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^2.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/http/is-number.json b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/http/is-number.json new file mode 100644 index 00000000000..32716549277 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/http/is-number.json @@ -0,0 +1 @@ +{"_id":"is-number","_rev":"43-3fe877efbeead423ee53a12d5ca44395","name":"is-number","description":"Returns true if a number or string value is a finite number. Useful for regex matches, parsing, user input, etc.","dist-tags":{"latest":"7.0.0"},"versions":{"0.1.0":{"name":"is-number","description":"Is the value a number?","version":"0.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"licenses":[{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"}],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"devDependencies":{"verb-tag-jscomments":">= 0.2.0","verb":">= 0.2.6","mocha":"*"},"keywords":["docs","documentation","generate","generator","markdown","templates","verb"],"_id":"is-number@0.1.0","_shasum":"4407a37aec259352affb5548886744ba4903f8bd","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"4407a37aec259352affb5548886744ba4903f8bd","tarball":"https://registry.npmjs.org/is-number/-/is-number-0.1.0.tgz","integrity":"sha512-WWl3iAruYOePW5iMf0IMcPiTsOTOu/FFsPyfx/ywixw7VmN6dI3/8/rgo4pdN6kVVjC5ByZ0Zk8xHLGEUSCdYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGbjmJymNMyy+kX9QMWNiNDpyXcRARCBG/qWG5AH3BHwIgYPJPxD0DLlmMlQ82J2/kw9xjNGwnqmZwv1iu2dhCtQo="}]},"directories":{}},"0.1.1":{"name":"is-number","description":"Is the value a number? Has extensive tests.","version":"0.1.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"licenses":[{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"}],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"devDependencies":{"verb-tag-jscomments":">= 0.2.0","verb":">= 0.2.6","mocha":"*"},"keywords":["coerce","coercion","integer","is","istype","javascript","math","number","test","type","typeof","util","utility","value"],"_id":"is-number@0.1.1","_shasum":"69a7af116963d47206ec9bd9b48a14216f1e3806","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"69a7af116963d47206ec9bd9b48a14216f1e3806","tarball":"https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz","integrity":"sha512-la5kPULwIgkSSaZj9w7/A1uHqOBAgOhDUKQ5CkfL8LZ4Si6r4+2D0hI6b4o60MW4Uj2yNJARWIZUDPxlvOYQcw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGGOUnPaovBe5O7zmgOovRl4e6Dzx6aMobYRtKHOiWV+AiEA4Qufb/miuS6rDGp7Zd20/e0JoxviUgTnqu21xGF2DhY="}]},"directories":{}},"1.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"},"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"files":["index.js"],"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"3183207ab31bb09c65ad8999c39090a3c0530526","_id":"is-number@1.0.0","_shasum":"de821e3936a8996badeb879ca6f93605e769d498","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"de821e3936a8996badeb879ca6f93605e769d498","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.0.0.tgz","integrity":"sha512-chlxkgJp4PZIiff6kUe/MWLp5+soELWNYA2IsOTus1YwKj8d9JZS6QsU7Ryqwhb1f4i0nQ5SsoUj6d5kGgq0KQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2AOAMGpyuvqtfmVFBdULwtBCwI1cATJ1E2SXCu7KrqAIgN3FVeMU5CjRuw21s50tzEalrZmgvbJxkjizEvjLl+Xk="}]},"directories":{}},"1.1.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"},"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"files":["index.js"],"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"3183207ab31bb09c65ad8999c39090a3c0530526","_id":"is-number@1.1.0","_shasum":"620db9e22fded44d43d8e3e47044319083d31855","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"620db9e22fded44d43d8e3e47044319083d31855","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.0.tgz","integrity":"sha512-zRllTDrNKDRvVEhjEqDVkT9eKzC7HJ+9SFbfBdZnbjBVt9t0SwbEn0F/NSwdk5GkkEdKZA6ZQ0Hfd4akty5Pfg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnVnl9/SgNEemmb1M0T1tlfm4YRTqvWw3ja961FsqrVAIhANd7v0o1uT3CVfC9pzaFfvmwZcKBnxD+UHWlKvlIU4SJ"}]},"directories":{}},"1.1.1":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"5184d76c622b97d45486340a85147c6d59d14e25","_id":"is-number@1.1.1","_shasum":"e393e7ec07c17770dbb67941e7f89c675feb110f","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"e393e7ec07c17770dbb67941e7f89c675feb110f","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.1.tgz","integrity":"sha512-3/f2eabVTjIGjSVaQIIv33g1d2tYdSUnCNJuPpHcjwRzx8A2IPtCB2ayK2R3aS7SCF/LHlTjdaRjNmfG+RpFlA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1MN/tZFRjbwiG0H63P4dD6Qsem1lVPlOlJuJfdJP8iAiAoX6Lk3FLlI0dqigZPFyFZi1CXFk0W8dN9yJw7P2IW+Q=="}]},"directories":{}},"1.1.2":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.2","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"a902495bca1f471beaa8deb6193ba628bf80c0e4","_id":"is-number@1.1.2","_shasum":"9d82409f3a8a8beecf249b1bc7dada49829966e4","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"9d82409f3a8a8beecf249b1bc7dada49829966e4","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.2.tgz","integrity":"sha512-dRKHHq76sZAXFf823ziHIOx5fXbuV1IrR892LugLDmyEBVMZzGoske4sY6lf+l3YPH/VyWNiKzNDXAPiQhx9Yg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpH37H0WboBtQM2deQbMGTh2WMRYWVosLWdpoz+wqyoQIhAIutpIYs8sNTY2MaxDpnJmvhoUfxrNVDIUs4+J5JffHf"}]},"directories":{}},"2.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"d5ac0584ee9ae7bd9288220a39780f155b9ad4c8","_id":"is-number@2.0.0","_shasum":"451c78bfe6c427f37bc2a406226e0cde449f3b5a","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"451c78bfe6c427f37bc2a406226e0cde449f3b5a","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.0.tgz","integrity":"sha512-LRme8p0WzIN9lrlP9/wJKs6242c9KYvDj6JlW9N9Up28wFxzyLNyNtnWu1j9nIuoWliquNRQx6+/OZ5mI2yVpQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEJz5PkAW3hcxfgUxotR5OLxeQFXF+vEsj3qRlIMuZj9AiAH3YXd7HMtFrJZqPGBE7DOjTqFWYWiPbm696CW+v1zDA=="}]},"directories":{}},"2.0.1":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"dependencies":{"kind-of":"^1.1.0"},"gitHead":"bb9b2e19a9aa2ed4b1e7a5d27e43417c8c9570c0","_id":"is-number@2.0.1","_shasum":"a3754e651f0df489f290ee0a1102c87cc5a0db02","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"a3754e651f0df489f290ee0a1102c87cc5a0db02","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.1.tgz","integrity":"sha512-lDXqMCs22DpNe5F5HqfrhwdCWXjlMccky+nhZ1+iFjnGvL7F7R7Q6Fd1FswLUrqueFab/6/k1Wd9LkIXJcBSWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBlSPRMBjwALDvd9fjWuuBR4PSdICIZh8q3IucTdXt6xAiA/4FirIMH2gtXtxkCZ/FLtO2+W5CJQVYHnvPGUY6nIaA=="}]},"directories":{}},"2.0.2":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.2","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"dependencies":{"kind-of":"^1.1.0"},"gitHead":"63d5b26c793194bf7f341a7203e0e5568c753539","_id":"is-number@2.0.2","_shasum":"c7542a0f420610655834cd3825bc2f0eb72afe21","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"c7542a0f420610655834cd3825bc2f0eb72afe21","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.2.tgz","integrity":"sha512-MzbGCUNsyTujsn2O9E2wL8n65cXdeWV1Jgd8khIA8VuN1q9ExsYQD6CwUwX6i8VGNLQy1skQugZ5RkvM1vbeqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9XsZ2zEA+6vg8VayjaUNxJIUDkYbvrvxC4uW8u0L3iAiEAgmolYRoJJEsPK3k30eWySMUIHqn3GHaYsWysUhMsqjs="}]},"directories":{}},"2.1.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"dependencies":{"kind-of":"^3.0.2"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"*"},"keywords":["check","coerce","coercion","integer","is","is number","is-number","istype","kind of","math","number","test","type","typeof","value"],"verb":{"related":{"list":["kind-of","is-primitive","even","odd","is-even","is-odd"]}},"gitHead":"d06c6e2cc048d3cad016cb8dfb055bb14d86fffa","_id":"is-number@2.1.0","_shasum":"01fcbbb393463a548f2f466cce16dece49db908f","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"dist":{"shasum":"01fcbbb393463a548f2f466cce16dece49db908f","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz","integrity":"sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBsAMHxq3xfm/burDf3PmG8CCLKR4UncouEdSDdRwglAAiEAxMTfaixUr2K2XsrRDCg7R6dRYawh8RqjO/VkIJSFNA8="}]},"directories":{}},"3.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"3.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Charlike Mike Reagent","url":"http://www.tunnckocore.tk"},{"name":"Jon Schlinkert","email":"jon.schlinkert@sellside.com","url":"http://twitter.com/jonschlinkert"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"dependencies":{"kind-of":"^3.0.2"},"devDependencies":{"benchmarked":"^0.2.5","chalk":"^1.1.3","gulp-format-md":"^0.1.10","mocha":"^3.0.2"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"related":{"list":["even","is-even","is-odd","is-primitive","kind-of","odd"]},"toc":false,"layout":"default","tasks":["readme"],"plugins":["gulp-format-md"],"lint":{"reflinks":true},"reflinks":["verb","verb-generate-readme"]},"gitHead":"af885e2e890b9ef0875edd2b117305119ee5bdc5","_id":"is-number@3.0.0","_shasum":"24fd6201a4782cf50561c810276afc7d12d71195","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"dist":{"shasum":"24fd6201a4782cf50561c810276afc7d12d71195","tarball":"https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz","integrity":"sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEpkuzJnkIAtuDMAI3VLqzFNwNANap4m9nyeUneW72kRAiEAtsctBWg1OtEaj2FSH+9ViALZU1O0hQFCVzwGMWHfVnk="}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-number-3.0.0.tgz_1473555089490_0.21388969756662846"},"directories":{}},"4.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"4.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"tunnckoCore","url":"https://i.am.charlike.online"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"related":{"list":["even","is-even","is-odd","is-primitive","kind-of","odd"]},"toc":false,"layout":"default","tasks":["readme"],"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"0c6b15a88bc10cd47f67a09506399dfc9ddc075d","_id":"is-number@4.0.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==","shasum":"0026e37f5454d73e356dfe6564699867c6a7f0ff","tarball":"https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA4Ju8vfTa5OmCg3qagXNvXHR0wp4GYpv4Jrzzx1Tr6yAiANs8hwximKkGyecUuMhc9/ipdFOP6u5xqFY1kkP37rHQ=="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number-4.0.0.tgz_1508219035603_0.08690439746715128"},"directories":{}},"5.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"5.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"toc":false,"layout":"default","tasks":["readme"],"related":{"list":["isobject","is-plain-object","is-primitive","kind-of"]},"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"7ed43573445149edf10f56967e8d943520ebb1db","_id":"is-number@5.0.0","_npmVersion":"5.6.0","_nodeVersion":"9.1.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-LmVHHP5dTJwrwZg2Jjqp7K5jpvcnYvYD1LMpvGadMsMv5+WXoDSLBQ0+zmuBJmuZGh2J2K845ygj/YukxUnr4A==","shasum":"c393bc471e65de1a10a6abcb20efeb12d2b88166","tarball":"https://registry.npmjs.org/is-number/-/is-number-5.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFRVCaHiES/v9QeFGm0LXGwQmnzQ7rRyYgSkAV0/RfEIAiEAovG90UvuzqTelvVuQdatpyiQ0H43CXLZupcrA2vb2Bs="}]},"maintainers":[{"email":"me@rouvenwessling.de","name":"realityking"},{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number-5.0.0.tgz_1517195201147_0.7769706172402948"},"directories":{}},"6.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"6.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"toc":false,"layout":"default","tasks":["readme"],"related":{"list":["isobject","is-plain-object","is-primitive","kind-of"]},"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"b0953635829711e7dceec0eaa92bc56521a546eb","_id":"is-number@6.0.0","_npmVersion":"5.8.0","_nodeVersion":"9.9.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==","shasum":"e6d15ad31fc262887cccf217ae5f9316f81b1995","tarball":"https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz","fileCount":4,"unpackedSize":8960,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHw0y05qyjN2G0Uw0DINiC25SvWlVSgd2UD/ddJM8scPAiEArxOqwwCq3PKUhw7VEm21DI141kJs/ktPkaANlO5cGOs="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number_6.0.0_1522515759840_0.005598684369539919"},"_hasShrinkwrap":false},"7.0.0":{"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":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"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}},"gitHead":"98e8ff1da1a89f93d1397a24d7413ed15421c139","_id":"is-number@7.0.0","_npmVersion":"6.1.0","_nodeVersion":"10.0.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==","shasum":"7535345b896734d5f80c4d06c50955527a14f12b","tarball":"https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz","fileCount":4,"unpackedSize":9615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPOMKCRA9TVsSAnZWagAABmIP/iUfV7gQnAsn2vRNKWIu\nlxkfXFutnV1Bo5P8mlv37Zg+PN5/Ri/RATtKGEosAvHL/HK2HkFH+rLYkupg\nCYaAVXNOJiFN9vK61YYp0TB0PBtGDQ2UwcElxDQ8OP6Djni4fl2fLjVZ+JeN\nPF1bKPE6oMevNg3GtNMrb1QKZNGjplOKFmlmm9fe653LHwIH1zPYy6QQ+cgG\nQ8Czmhdf+NuX8WXqR1h5mHTKCCVAqzcpJ21uX9292aoWlzlijzg9cc8KEPEY\ncbUjJf4NMLs89/8G6tcpDP5qoVjQnWIgfM0mDXt4P7ESdqjusdyNa+3eS/Yi\nsQuevXmth+41kvQaVy7rLbeAssWNbc7IJ+X1qpgnUqTz4rtiAaRnZ6rzAE2s\nrr723lN2H7ALlnDVm5qzXLTTjHwbdYMYuaYHTOMovytYWeRnwhfNCpKeQcEe\nUYR3sm2tEdxsMI5ciu5ULGj/PEKnSOsQcq2y4QjNFz4F5ReXiv+CtphQubAr\nVkKwrjIovN97YXmyrkfJB1zCInCMUz11YgRY0wNaCJPJ4E0V4KdfWgCEyt+F\nqKcdylewrOAma06WozqUXzRH3uNNbMTfsE1nGqbcofJPNBre/VriCwF7zS/H\nLhGfCe6LJuY2Q+2Eel1vtwnY+vAoaWrr7QisjcvywYHvqWlRob2IxC1Ygp3A\nvUY+\r\n=M7jx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGex85Xx5rKhEgNSkg7z5bBu7vbcFbJnWJZbV3f9Td8GAiEA5wzgLXU41sE6ezCKGrmzsyMtm6M+2OhefJJhkzPEAoc="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number_7.0.0_1530716938183_0.28831183290614004"},"_hasShrinkwrap":false}},"readme":"# 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)\n\n> Returns true if the value is a finite number.\n\nPlease consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.\n\n## Install\n\nInstall with [npm](https://www.npmjs.com/):\n\n```sh\n$ npm install --save is-number\n```\n\n## Why is this needed?\n\nIn 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:\n\n```js\nconsole.log(+[]); //=> 0\nconsole.log(+''); //=> 0\nconsole.log(+' '); //=> 0\nconsole.log(typeof NaN); //=> 'number'\n```\n\nThis library offers a performant way to smooth out edge cases like these.\n\n## Usage\n\n```js\nconst isNumber = require('is-number');\n```\n\nSee the [tests](./test.js) for more examples.\n\n### true\n\n```js\nisNumber(5e3); // true\nisNumber(0xff); // true\nisNumber(-1.1); // true\nisNumber(0); // true\nisNumber(1); // true\nisNumber(1.1); // true\nisNumber(10); // true\nisNumber(10.10); // true\nisNumber(100); // true\nisNumber('-1.1'); // true\nisNumber('0'); // true\nisNumber('012'); // true\nisNumber('0xff'); // true\nisNumber('1'); // true\nisNumber('1.1'); // true\nisNumber('10'); // true\nisNumber('10.10'); // true\nisNumber('100'); // true\nisNumber('5e3'); // true\nisNumber(parseInt('012')); // true\nisNumber(parseFloat('012')); // true\n```\n\n### False\n\nEverything else is false, as you would expect:\n\n```js\nisNumber(Infinity); // false\nisNumber(NaN); // false\nisNumber(null); // false\nisNumber(undefined); // false\nisNumber(''); // false\nisNumber(' '); // false\nisNumber('foo'); // false\nisNumber([1]); // false\nisNumber([]); // false\nisNumber(function () {}); // false\nisNumber({}); // false\n```\n\n## Release history\n\n### 7.0.0\n\n* Refactor. Now uses `.isFinite` if it exists.\n* 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.\n\n### 6.0.0\n\n* Optimizations, thanks to @benaadams.\n\n### 5.0.0\n\n**Breaking changes**\n\n* removed support for `instanceof Number` and `instanceof String`\n\n## Benchmarks\n\nAs with all benchmarks, take these with a grain of salt. See the [benchmarks](./benchmark/index.js) for more detail.\n\n```\n# all\nv7.0 x 413,222 ops/sec ±2.02% (86 runs sampled)\nv6.0 x 111,061 ops/sec ±1.29% (85 runs sampled)\nparseFloat x 317,596 ops/sec ±1.36% (86 runs sampled)\nfastest is 'v7.0'\n\n# string\nv7.0 x 3,054,496 ops/sec ±1.05% (89 runs sampled)\nv6.0 x 2,957,781 ops/sec ±0.98% (88 runs sampled)\nparseFloat x 3,071,060 ops/sec ±1.13% (88 runs sampled)\nfastest is 'parseFloat,v7.0'\n\n# number\nv7.0 x 3,146,895 ops/sec ±0.89% (89 runs sampled)\nv6.0 x 3,214,038 ops/sec ±1.07% (89 runs sampled)\nparseFloat x 3,077,588 ops/sec ±1.07% (87 runs sampled)\nfastest is 'v6.0'\n```\n\n## About\n\n
\nContributing\n\nPull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).\n\n
\n\n
\nRunning Tests\n\nRunning 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:\n\n```sh\n$ npm install && npm test\n```\n\n
\n\n
\nBuilding docs\n\n_(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.)_\n\nTo generate the readme, run the following command:\n\n```sh\n$ npm install -g verbose/verb#dev verb-generate-readme && verb\n```\n\n
\n\n### Related projects\n\nYou might also be interested in these projects:\n\n* [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.\")\n* [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. \")\n* [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.\")\n* [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.\")\n\n### Contributors\n\n| **Commits** | **Contributor** | \n| --- | --- |\n| 49 | [jonschlinkert](https://github.com/jonschlinkert) |\n| 5 | [charlike-old](https://github.com/charlike-old) |\n| 1 | [benaadams](https://github.com/benaadams) |\n| 1 | [realityking](https://github.com/realityking) |\n\n### Author\n\n**Jon Schlinkert**\n\n* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)\n* [GitHub Profile](https://github.com/jonschlinkert)\n* [Twitter Profile](https://twitter.com/jonschlinkert)\n\n### License\n\nCopyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).\nReleased under the [MIT License](LICENSE).\n\n***\n\n_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 15, 2018._","maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"time":{"modified":"2023-05-26T16:12:33.057Z","created":"2014-09-22T01:58:51.592Z","0.1.0":"2014-09-22T01:58:51.592Z","0.1.1":"2014-09-22T03:37:27.931Z","1.0.0":"2015-01-24T10:16:54.470Z","1.1.0":"2015-01-24T10:33:21.598Z","1.1.1":"2015-03-05T18:37:07.633Z","1.1.2":"2015-03-05T18:57:33.841Z","2.0.0":"2015-05-02T08:11:57.926Z","2.0.1":"2015-05-03T04:27:13.630Z","2.0.2":"2015-05-03T05:59:55.976Z","2.1.0":"2015-11-22T13:56:56.624Z","3.0.0":"2016-09-11T00:51:30.912Z","4.0.0":"2017-10-17T05:43:56.559Z","5.0.0":"2018-01-29T03:06:41.225Z","6.0.0":"2018-03-31T17:02:39.953Z","7.0.0":"2018-07-04T15:08:58.238Z"},"homepage":"https://github.com/jonschlinkert/is-number","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"],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"readmeFilename":"README.md","license":"MIT","users":{"jonschlinkert":true,"antanst":true,"rocket0191":true,"papasavva":true,"456wyc":true,"maycon_ribeiro":true,"leix3041":true,"snowdream":true,"fizzvr":true,"jameskrill":true,"rioli":true,"gugadev":true,"fearnbuster":true,"flumpus-dev":true},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}]} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.after.json new file mode 100644 index 00000000000..84044f64afc --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.after.json @@ -0,0 +1,28 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^6.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.before.json new file mode 100644 index 00000000000..7c6f4c3a9db --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package-lock.before.json @@ -0,0 +1,28 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^4.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } + }, + "node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json new file mode 100644 index 00000000000..19edeb6b92e --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json @@ -0,0 +1,10 @@ +{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^6.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json.before b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json.before new file mode 100644 index 00000000000..211eb15295f --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-peer-overlap/package.json.before @@ -0,0 +1,10 @@ +{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^4.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.after.json new file mode 100644 index 00000000000..400ac05b799 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.after.json @@ -0,0 +1,48 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^3.0.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.before.json new file mode 100644 index 00000000000..3c89a3a384c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package-lock.before.json @@ -0,0 +1,49 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "kind-of": "^3.2.2" + }, + "devDependencies": { + "is-number": "^3.0.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json new file mode 100644 index 00000000000..37bd8971bd7 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^3.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json.before b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json.before new file mode 100644 index 00000000000..438b428fb44 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/dev-recolor/package.json.before @@ -0,0 +1,10 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "kind-of": "^3.2.2" + }, + "devDependencies": { + "is-number": "^3.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/locale-sorted-keys.txt b/rewrite-javascript/src/test/resources/npmlock/locale-sorted-keys.txt new file mode 100644 index 00000000000..040e63c0fa1 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/locale-sorted-keys.txt @@ -0,0 +1,2824 @@ + +_ +_~ +_~56i +_~q +_1-0P88 +_1-Uv2 +_3r~0 +_5k6JW-F0 +_5O +_74kNI +_8_fhyB1ug +_86lJBB +_A +_AEBS-Z5 +_Cpfm.pl +_drlTkCL +_eNzn +_FCIka6@sE@ +_FkDTy1QdH1 +_Gn_w +_HM2rua3_f +_IJyP6/ +_MZ5-Kgsb +_NJ6R4A929z +_oRCM +_Q +_rQ +_u +_U +_uH7nK6g +_V2roVUlG2 +_W/hw +_wKu-ar +_X6KBV +_y7/_b5d-2lU +_YYOIrYtmI +- +-1npMAn~kQR +-3Mve~LAIuR +-44MepUyEKc +-7WbIy7- +-B9m1PF +-D~B0h~h7 +-eF58lKr +-I3V2ozXDw +-IvrWa5 +-Jp +-l +-L/eQqxRGi +-loM4ifhMn3F +-MBGWx~A/TO +-MdBT1D +-QVv +-Tcuo3VDB +-Tw_b9t +-ui@Ygrx1 +-Un/Twj +-vZ +-w +-WthYQB5K +-X9rqs~/z +-xY.@oV_ +-Zo3G +. +._j +.-VIrWdp7l +.~bBDKCVRQ7g +.1Jfu6/pJ7i +.1v77eSf.A7 +.2_ +.2LIF.6AuC +.2Rv~bdTl5QT +.4HoIGzB +.5Xa +.68 +.8 +.B +.bxjF +.c0EuMpbd-/ +.h_SVnItoHoU +.ha +.Ic3V +.j0G +.jC0v/zNUEo +.JjADK7oMF~P +.LB9 +.MbSym133i +.n~oLY24v +.N4msttm +.OF0y_Kz +.On +.PAoOfch- +.PiysmY +.PKBi +.rD_etE9 +.S +.S3BfPd-im +.SmlTLxF2cmH +.w +.w2BVuGSFF +.w8 +.x-W7ogZt +.z9E-qZ1PpNf +.ZKVHn7mf9Gk +@ +@-wHXpHL +@@dxEJ9fVc +@@l +@/Xs~PWq2z +@~avPu0Q +@011vPj +@2MXLYVZiIv +@7B81fDvaDw +@7CU7MFWf +@BAZnX9 +@Cqp +@d3ivl +@DmJchj2DUI +@F/@ +@G~DkD +@hu_N +@i7~Evpd +@IPV +@jn/ +@L.D +@LP +@mf6.qp +@mGS6ykwh39S +@ne70VU6 +@OBwa_sytWT +@OY2OnpMO +@pLt7p18Fm +@QNNeTq1jZL7 +@qqJUP2nT@V2 +@RB8 +@rJ@pUrps_Mz +@rR +@S7d0hX. +@ULtP.R/K5Bx +@VaX@ +@Xr0MokhX8Lq +@z +@zK6PY +@ZuDL +/ +/.Ou1EwJ5Y +/02tEPAv0uw +/1mRymrTa~8u +/4 +/5OMd@WMPD6H +/A +/by +/cllRdk~4SG- +/cy-4gspL- +/dgS~2ET7i-5 +/e@_i5 +/eE8R +/EOg59T/d0 +/gL3Y +/gvW0d8pouy +/gYy/lmk8_7y +/H +/i@9-bW@or_ +/I4BsX +/Iy_R +/J0s9KGBd +/JaK3/wOd81 +/JTB6z/M9Mto +/kfyltPm +/lLl +/mC +/MU +/Nls +/nOBj +/o5G +/o6NyMtBode +/OVb68Nxwn +/pZl0 +/R/QM6ZgFc~Q +/TLl +/uC +/v7 +/vy0xW +/W/Z7vp3i.w +/Xb/F18X +/xH9g/3twO +/XPqmj +/XW1c +/yjS9.u +/yt2G6 +~ +~/DjJY.tMf4x +~/r6- +~~e36a~sQck_ +~07Wm3YSy1 +~1 +~1FIiQP1 +~3s-6bqlpO +~5@X~luEmDn +~5p6~U-@EK +~6xb_Uag@ +~8@CpecZJ4nQ +~90rc0YVsL +~9KhMjw +~Afh7 +~bBP_NPDI +~C/B +~E~@VSNA +~f1v@Rzj~ +~FE9 +~fH_PaSa +~G9JqaRrwG +~HE +~hM +~HQ +~M5- +~Mc +~N7rd +~OOoZv +~OXnTe.3YHj +~p +~peVRpZs +~pGT1jeRBddi +~qm +~r7nO2k +~rRqwYg-g_-n +~T/nWIPJ7i +~u +~ugL2eZ~_e +~v9rVV4w8ABF +~WQsx@dloQ +~xBJsgn6 +~ymZBH2g +~Z6hRn9NH +~zwv//c +0 +0_UxTY8 +0.Cc@UAAl +0@Lc +03FDki7Cx +04 +05cbaQR7WNbJ +060HG +06rt~WSDIBI +0A-_cD4W- +0aukaMn437 +0CNt +0CO- +0eQz +0ezWADz9zZ +0f8EqdANLH-1 +0FZYBfF11_IU +0Gt~p +0h5HG@4 +0htdJk +0HV5Pu3nV3 +0izr6 +0K4psNM +0KFee +0kMIO4BekyZi +0KXuFh +0LJ +0M8 +0Mhj/wXegds +0Ou +0P +0PK +0q~8-wZ5tj +0q2QVKEo6OY5 +0R_oui +0rHPw +0Tl8E/4gX +0tlt/ +0tVhdW +0v~ +0vPqbAWn6.5 +0w0R78PjHG_l +0X@r6z +0Xw4Ob +0xX4. +0yIH4vy +0Z.fcDJL +1 +1_A +1@FY3dpxD +1/ZQMUY +1~09Mi06IHBI +1~0owe5z +1~g@Qv~FNbqP +1~icq6B +10 +11K~_MzH7lH +12 +12rzT +13 +13~CMin- +13m +13YJ4VN +17 +18A_Bh3yZsOh +18fWWDvi +19L82 +1arYCOoIrFk +1ASmMKDq6D +1BrJ~ +1EcK/P@E2 +1EKKuF/ +1fUpw +1GqBNe9uF +1H-8DWXP +1HzW_~Q +1kZh +1OAarH.m/Y +1p +1PfWxbU92RW +1pl +1Pow6KaYGc14 +1qEK +1Qz +1R +1Syoer +1WNZH4 +1wTfF2e +1wVaYfjKx +1y +1ydMSJz8 +1Yf6oX +1yP~O +1Zb@ +2 +2_g +2@oa +2@wPkcF5wYa +2/Dty.J0J +20A +20KDbiWb.NK +20WGX +22B@jS +22fgnT-mRqja +23MXpw.fm +23OSieF +26bxGUtqe +27@n/ +28OXT +2a@BjS +2bY8kKZNVlEy +2C/wv66oL +2cBGYrND_Kx +2dIpsf +2E@~gjf +2fr +2FxpS +2Fz +2k +2KbUlUXMJM/b +2KWmG8n5 +2l5G +2N0WUo_o +2ocb +2OYz +2P +2q +2RatGxEwdN +2rSzgi +2SlYGK +2Uz0t. +2v6cDVCqCV_ +2W8Aza +2WITXA61uydK +2wv_FBjyCe +2WVyS. +2wzVA +3 +3_rEN4hDQ +3..jhQ4X +3/dKfzwi +305rtz8d9 +329Y8aPg +32NX2_ +34o-wCtYDLBi +34s +360cdV +36LPzv0y +36LWUn +3aCqrU +3ANw.Bgm0u-2 +3ARP +3B~8p4J +3CdEfK-s +3CpTkoF +3EszY7KAoN@U +3g +3G +3G3cQ4uS +3gNcyFaGaQZo +3H +3HdW3R/DfQ +3hYPY~z1I9CC +3j7h0. +3nGzZoKz_oQ +3nU +3nzV@qKZi_XA +3o +3pfiw1F +3QOAp@4D +3r +3s +3SrUy +3tmrR +3UmHAauy1 +3V.bFULtz +3WUdsSr~x. +3y4z +3YA +3zEXsyuPTH2 +3zX2 +4 +4_c1 +4_ChrzzB_pTR +4- +4@0uU6p +4/SYZg~-P9Uk +4~qz0M +43yqprc.Af +477 +486/YEqLHve +48C +48vg7cnlSV +4ATrlM3Zl +4BK9D83n +4bpJjrHbfB7l +4BQ_ag4.-ce2 +4cP1IuGFy +4CRlvS +4G/O42E3 +4g6-ri +4iew0q3k +4if9 +4Jj5dkFZMgD +4K +4Kg_z28MkLms +4M2idJ +4O2Cc +4qFg1Q +4qJ +4qTQwd7 +4rbyQ3j +4sf. +4TxvpMe +4VoP/ +4W8-c +4wn~ +4x +4XF9CcLr +4xhFn~8 +4Y.x +5 +5.3e +5@kbfGGQK +54ggV +58SW@ocCLeK8 +5aL +5b/Jfjuqv_ +5b1D3REeq +5Bi41L +5c-j6I_Vx8O9 +5CPAT.-Qu +5eujZ +5eUxNqv9svv +5f_ey061d +5HLQ0A +5HX.NVcYO +5i +5IUR9Y9 +5KEVEVeh +5L.-9hS0am0z +5M74L_ +5mHey4LOwJ +5N +5NHHY8DJp +5ofYNx +5oIY +5pmjjx.lDaq +5Q~ELpme +5SR +5syo5OyL9l4 +5w +5wbtWLY +5xB +5xHeArD6 +5XjhtPD0YQ +5yDCZMJ +5Yx5ad6ub +6 +6_8MMeyN8 +6/A0X +6~zreqPzD6RG +63 +65 +65IuUeUTAjZ +67LOhY.qY +6aCkgJRiL7A +6ap1O57Ox +6BiTgS@S +6bTaNG1Q5RQ +6bYX0ae~g +6cRk +6D3a/FxMQRH +6EBujXu +6G@WBECaV1P +6gYDG1 +6hWEy/WaPCR +6iXExTnM7k +6JL6D4 +6nucglIWxLa_ +6O0t~sNOEKks +6oIEE6Gm4KjK +6oy +6R- +6sNWWXSNa +6UON5m5vVe +6Vbs_@Rx +6vd +6W7 +6xnDbKWhK +6y3I5 +6YJf +6zaR +7 +7-FiA +7/@ +7/tqZAZ.AzLW +7~_yi/g +7~AKMjL-2 +70cic-7zQDbi +71tczNs +72omb1eNA/SF +73 +74DgHwwXBG +77VE5 +79cU +7A +7aHEq +7B/.4Y +7b883o.EP +7BWP9cj +7c6G +7fiUg +7FN +7FqR2BYuI +7g55FP_sFNG +7g7s_lmL~P +7JTttA@kp +7lBp +7LCzk.O8-ZD +7lpIVS +7Md.P-HXtBCC +7nnS8eIKD.SL +7O3fUIs +7ooNm4Ax +7oRQekhZAC5 +7oTiE/936K +7Qde.BOe +7sshV5Lf@PMp +7tg0ia +7Vw9j/ +7xoW1 +7xQvhn +7y +7Y_L +7ys/MNwn~ +7zc +7Zf5X/sK7w +7zmst +8 +83puFBScu2f +85D1 +87baL8lz9yi +87vxktijY +8by.gwXNS +8cg3g +8Cn +8EaYr6GHLk +8g~SUebv +8GAdRre +8GqsCZQlb +8GXma +8I0 +8ipucL +8iz8mV4mX +8KT2j0K +8LCHL7l17 +8LYr_qZdF +8MLon +8ms8 +8mtI@dLFysh +8Nq7/89AH +8o22 +8pk +8Q +8qEzaQ +8RE +8Sr1HhxFhI +8u9ap +8w_fvFWUR_cD +8xWOZh9F +8zoUY +8zZNEL +9 +9.4 +9@ +9/i +92Xo3mJWfK +93IdsBhznOpT +93q6 +93swP9~ +95uFFUd +98 +98.ZU +99-I-qIZY8 +9A~sFVZai +9B8eLqMz +9BW-K3.lu7 +9CQk~5vhI +9f2heyibk +9ffPfEsWV +9FHFl2OiU +9G/0WD8D53~4 +9GW +9H0Nn/.f6- +9iubY8ajKPeY +9j +9j1 +9l +9L@-5 +9LS-QeDxM1 +9M +9mYt0C +9N76f8 +9O0Qf +9PhRJ/MblSRu +9Plc5w +9RE +9rG~eUiyH +9tl +9UDVNw3RXge +9V_.X2z +9X +9YBxCDUX +9yVF7sp +9YXEZhtt +a +A +A.mTO/ +A0@ +a0bdmiu2Gw +a0V +a1ABm1 +A1E@Pzc +A1ioSKeVZMw +A1OxZE +a1xsuj +a3KWV +A4 +a4p5 +A5V~3OS +A6q +A6Vho1PlN +A9~TLReETh +aaoSddHK +ABWBgL/T +ACAu +ACE +acU2~_XQwz +ad +ADdFoM_Hc +aE-4q4 +aE6v0SaWi +Af2aPmb_Aeo +aF2ve4sOAUv +afKix~tiT +aFlPeQp0g/l~ +aflQay +Ago-YGAR +Ahs +aHWbcGhMu4u +AI/g +Ai2y7f +aifmHX-zMg +AIM +aInd9 +AiTm7X3KI1o +AiXocGX9V +aIYp.vw5/Ga +aiz~KNV +AJgt +AJW +AK_ +Ak2 +aK9 +AKa2FG +aKDLK- +aKH1Ntqd~Zw +aLiKIYTq@8Q +aMbAlQ +aMf +aMSys6wz +an-DdDZOe +ANTkW-X +aNtw3YMNgu +Ao +ao-9iGOa26o +Ao6qh@bt +AOGAbq +AOqIt +aotkaCp +AP7m1 +apDbdU6zJiLS +Apj3XpSf +arenFN +arfRCrFyWCp +arWudYkhXZB +As +AScasM/O +ASjJQcqa506 +Auw8 +AuY@q~X.wr-M +auZBxCUHZsm +aW4V +AWC4e@pAOQ9/ +aWn7VniC5 +AWW3 +AXce +axO +AyuEgXOzbEU +AZL/_RuYbC +AZVB1j +b +B +B_B_gG~ +B_iLP8uXy@ +B_s +b-RAe7E +b@gIwlja +B/e.LhZlC8f +B0 +b0DAFMPs +B0J +b1My1Cz +B2@ +B3 +B3/a_GOqT +b39Ym87UqgF +b3btsbwo +B3c@l.wY- +B3Dg5~FYxAB +b5lSSxB +b7VkhPy4dwr +B85ajyO +B9F +ba-Ha1i +BBP +Bc +bcEt8E-RH +Bck6opLPUAY +bCP/. +bCR@wVyK +bctSTWhK +BD-_k +Bd-_y2X +bdipUpw6xBk6 +BFHwtx8.Dga +BfzW~u4 +Bg.yCloagn2r +bGVC~GdtO +bH- +Bh3lBEeRMsGc +BH80RLWpkwR8 +bhD +BhpwXEP_ +bhz1 +bin +BIV +bj +bJC5v0aeO +BJrIwD0W5_L +bJukXZp5Y +bJYwgXGNFs +BKjMOIXdJC +Bkk6Vhep-vFL +BL9gm-DC@ +BLexMl./ +blK/lhvTZsz2 +BLT8 +bLv8Ev@J7f +bmidF7 +bMJ_ +BmlPI +bmo8T +bo +BOcD +bOX8CMQTp +bpk0v +bQBvg9y/w +BQfPzvIl +BQQ8 +bR +BRSOJg +bSJn4f +bT +Bt2E +btH +bundleDependencies +bV-R1sGEdG +bv2vQ2E +bVdvvJs +bW +Bw8 +bWh_PQPh-u +BwTA@/bmwT +bX6fjD7 +bXc61kCZfE +bxhD5t@pVx +bxL4ogAjm@cx +bXV850W@HO +bY.P.E6@WAyL +by2bz +BYl29NQQw9 +BZ8GRMQ3 +bzg1 +c +C +C_@gpX +c_HY +c-0bpo2Qgx +c-4ir7 +c-QJezHNw_ +c/JcaJCLi0py +C~DOG. +c~FdRlNWPdv +c0QeY@zw_@ +C1 +C2pME6U +C3YV8 +c4 +C40qb/7kIzuk +C4ccUXq- +c5gP7nnNqK +C5pyHdzK8N +c6_gqmQoa +C6/XFX +C65YZONXu +c6o +c8Pu_83_nnbD +c8Qeegy9E~y +C9_Q3bAf +c9bnJp-RC +c9FK2dym.M~c +C9xaz7M3 +ca +cA +CA6zc +cbgBZPBI +cD0butoaEI_ +cDqOX +CeR7.Yf. +cewx7 +cf6gEtAOdrJe +cfj_yk@kr +CG-x +CGg8 +CHWV +ci +CiiPEnjM +Cj_7.KKUMveq +CJ-/kIG +cjFM0dzx +Ck@-fy +CkG +cL +cl.-P +Cl71mMD@J17v +cLVpmZj/T +cm +cm0eh +cMUcosuz +cmud3 +cnK~Q~9-Lay +Cnltr84nub +cnZWeL44uT2 +cp +CP +cPDvYSNshJDN +cpu +cQP6 +CqWhB~DNK5 +CR1n3Vj +cr97Uc +CrTrs.u3 +cRUOWd +crz +cT +CT- +cTxqI +cTZ/sfekYTs +cVdKZ5J6nN +CVftQ3 +Cx +cX@x5a/nc/PV +CXfrPvc5KC +cXoXD +CxrHWLfDn +Cxvnm +Cy +cya +CycUJEZP +cyK2rLOKk7 +cYrAJA.hV4m +cz +d +D +d-s/V@VXZ +D-TIslfFHgN +D.DGErz +D.U +d.ZHSN +d~683X0mGJp1 +D~7S6 +d~Wu3k +d0eUlYf7NRj +d12@@ +d2D +D2D +d3 +D4 +D5CCGjTvwhOp +D5f~2ZP7 +d7KzgLJWUH +D7S4 +d8uZ.q.XOi +D9Bo +dA +DA +da- +da0Xggj/F8 +da6 +daFjTglu/Thd +dB.eyQWDBKQ +DBhg6 +DBohaGjr +dbsPt2epZqI +dBwN +dc +DCZlc_mB7Z +DDLE5gj0 +dependencies +deprecated +deQTy9l +dev +devDependencies +devOptional +dF- +DFi._vz +dg8Xlb +dgZAq@LTkGuv +Dh +dJOChHOqlmQq +DjUk +DK0 +dKf +DKUG +dl4uNgriH0 +dLBeiD +DmMuQ2 +DMRD0Mvrr +dN +dN7u +DNk. +dnnQM@ +dNsIt_l +doCWdZ79p +DOMo5AP +Dp0 +DP2tsHft8 +dpF +dQ +dqJROH5PHvh +DqL@lo +DRBzVK +dRG +DRhaNI703 +dsHbbkd8ne +DT40RiRfw +DtdRNh +DUFeX9FBt. +DusBg_ugK +dUYueIG3m. +DVOEH +DVuQAIkPBo3 +dw.gK2CWO +dWhHbLJkZ3E +DXhSHP +dxnzxd74aa +DY.-a +DYn-L/7K1 +e +E +e-_Vh +e-.ZgY7 +e-aiS +E-pa7g/PJ1dW +e.9iz +E@Y8YgB +E0XXm +e2-RW +e2C3I +E3 +E3el1MwX +e3WbSywMaI +e54Z6dBD8N6B +E6mWvnD9mSP +e7.Vspyu4 +e71HZ1 +E939t19 +Ea2oeKts7URL +EaHKX +EAKB +eAlOLH +EBlUb@l +ec +Ec~2kYQ +eC1/j.z70n +EEI/T.H@WY~ +eeRX4IcnvO +EevgpCn +EF88ZdrmwiFr +EfCN +egLCmouCfm +EgYxO +eHJcu. +EHY9M +ejbcRk +EJbvEURlmS +EK/FeQ5 +Ekt/g +elx +Em +em~h +EM2Yn-b/nn +EMY0 +engines +eo-iA@Q5 +Eo576QP7 +Eo61WqAb_4o +EpPShb +EpS~pRKpE +Epvo.-Bg_4~ +ePxKZ2 +EQ1Dt +eQDTEE/DL +EqG +eqYbsO +er~2RG +ERWYEsyX +ES~U +et_D@E +eT-E0V8Vxif +etesYpysEl +ETj +EU5iIpP-~6 +eUd8 +Eufq~GyBv~sn +eUt74MH4 +EVDP5k +ew_ +ex_sQ9 +examN.BCl +eXwvPTAjnt7 +EY6PAk2 +EyfPiskAGxu9 +eyh6Huvn8W/ +ez +ezihu +ezVgg +f +F +F_.W/JKcqde +F-t_ +F@ +f@m2oMI +F/1/V_MZ53p +F/Fpj +f0-2G +f0PnzQpq/Jq3 +f1htUNJE3ht +F2oM7acPP4 +F2Vi1uCgoxGB +F3 +F4Rfq +f7Ho0i +f8~jj/QX +f8M4J/MYS +F8T4sO/B +FAf +faGDS +FB_ggPJqKP +FB8J@8 +FBUqF +fC4dN2NTXD_ +FDa9 +FDy~ +FdYgxMZ~fooK +FEDS +fEuBUjGQl +FEv2oAb +ffw9 +fg +fG9hRIk4 +fG9k. +fGbzifSL8vJ +fGg9e3B7YYF +FgMLvl/_idt5 +fHb.jvzJTc +fI3U-Xl54_- +fifH/j6I +FiO5YszAUff3 +fJPI83 +fjprN~p +fjZJGN7N851 +fk@~WR9Qd +fKEikVRe +Fkt@a7CQe +fKx_~ +fkXi +fL-Sx- +fl@Ef2SQ +FluNCNPj +fly-4W +FM6TKJC +fMX +Fo-Kk90q +fo2744@h +FOf +FOnwKdddAgna +FpBoMGgWKjow +fPdLV6Yuqmk +fPfDj8N8yytl +Fr.69 +fR6I +Frq6 +Fs1Rvr3_B65L +FS7jBwWS0o9p +FSCFRT +fsmup_ +fTFKgMVDX +FTh1O +FThdX3bS-K +FtN6nPdKj9 +FUd@M~wMhp +FUINYeHF50H +funding +fuoe@aaQDCI +fV +fvA.Lcp +fVE2bx_Nqf +fvl-o0b +fVtpD_RM +fVx7FssmG-Z +fXHUtFYXQM_a +fy.VWa +FYcTWcTQ0oWf +fZ1cdI +FZfdtwoBIJ +g +G +g-u +G@IVbKQ +G/A +g/zBz-5ix4 +g~cG1y +g2qCNLd +g4MRNW +g5X +GBhiykwR~.68 +gBIi +GDedi_W80 +GdhSIo_4g +GdltiuWp3YP +GDto3@~YEfl +gEssnpnyTx09 +gETQbn +ggHMoQT1 +Ggj@St9Y4O +GhP +gI +GILNXrv +GjkiJ2W/Z +GJr7BNJecWD. +Gk3bjs~Qkp +gL +glCyJpnhCS.7 +gM_j1 +GMQAb +GN1SjXo +gnepNH +GNgiGXrybXw +gNr +gPBVnuV +gptM~U1X +GpVhF6 +Gq_FNtjdJz +GQ/aQei9I2So +gQaUhfa1 +GQd +gQK5JyYf4z +gqLWM@i +gqZRb +Gr5 +GrRaII +gRV1cI2MAS +gSND +GT +gtpd +gU +GV +gV0 +GV1Mu +GVn@FyYmK +gw//U@Hyolo +gw1q/R +Gw9 +GwmRwT.-u +Gx +gx2a +GxICHP~EDbQp +gXTS/ATFSl4I +gYdi +gYklGi +gz4M0c1CSs/A +h +H +H_ +h-GzWAbVlAr +h@KQl/G0 +h@Mu7 +H@xB9sRfo +h/cZIRj.F7 +H/jwg8@ +H~a6qGpv_VDM +H0BJa8-vHF +H0o +h1l-S_8aSgzY +h1W~uwyNWJ +h2 +h2oLB3 +h2wokRDMDIM +h3Ufkz2/v +H4EUDD- +h4uX1 +H5FnZe +H5S-/r0ZfVQ +H61 +h7mKTy59euA +h85 +h8fz9.e5 +h9 +H95Mq1s54 +h9RgF2f2Ef +hasInstallScript +haXpa +hBhVP@mpX +HBq41t9z9wo +hcf +hclFX +hDcT +heT9q4dBMr4Y +hfEwt4zUlo +HfW~ +HFyRkQJAl +HfZtx- +HG +hggK7Ui +hHJN6N +HhMSHO8AXY +HhRZ +hhsQSYlyVWi3 +HIeQ +HIlNKQz_4 +Hiy +Hj +hKI@lEDw +HkK +hL +HLsr6 +Hmhxou5nrr +hMjQjhn2hF +HmQ@vuH1wY +HN +HN8 +HoIJJY +HOpiQ0bOC9 +hOzMYj +hPWmvO +HPZb +hqLg4zAwG0 +Hqu8DYoIZiM +HR +HR5IQedEjTD +HRW@NgkH +hu@nb5G +hU9Fd +HVaMc3oTdv +HVPW +hw +HW0fN +Hw0IXVo@x +HWe7hkvBgTWs +HWFd3nOZyxz +hWIv8h2N +Hx +HXjUoWouMwEn +hY +Hy +hY2mYGn0n +HyM/COuV +HYQ_ir +HZ-oNZrywi +hZrlvxNo- +hZV5b +i +I +i_-b +I_4PbmwM7Nn +I-bwwqQ7ywoU +I.kr~KgJ9 +I.Tq +i/ +I/kg. +i/X +I~LpVQPpYCN +i11zaSxT +I1vURfDk +i37hZ +I3J +i3M9NHnisf +i5j8P6_I +I6e +I7-D~nc +i81qKsjjq0 +i9 +Ia8H087s@ +IaJwc-WBY +IApSfGt0Bxw +iaRwlMy +IbAz_D7P +IbxymrN5xS6u +IBy/j/pRdQh +IBz2qOmGT +iC8COKeE +ICF0xjmF +id@@theC +Idrb1l0~E08x +iEV +IEwbKlw/ +IfN~@ +IH@UOktvgB +IhWl +ihwx/7oDC- +IHZ +ii +IIw18 +ijhFqY/sl-Il +Ikt4_r +il_/Ib@Jp_s +IL08kIKuv +iL25~_9 +iLL6f5eNU +IlO0UR19a +IlP +imGCkwwlSE8~ +InCppNJ +Inj8ios@5z +inN +integrity +iO3nRQXL +IOh +iP1 +ip6yyvi +ipc- +iPIkxOk +IPJqOni +IpLOUVOz/Le9 +IQ +iq8-2_ +IQp7P +Ir +iskCE7AG +ISu-n +it +iva-zJg +ivbf +IVqxECPKgocc +Ivxq +IwGw@ohN +iWKtGkxbu-ty +IWyfV +Ix +ix//FzrfG +iy +Iz +iZd@nnR +izqHZPzA +j +J +j_ +J-Jnj5s9A +j._IdrZHYR +j.7qM- +j.edq +J/Czb@hV +j/so9i.nt +J~hDCLWz5q +J~qVLx-Y +j0h/F4fO_CO +J1hdIxQc-@r +J2vsdC +J37T +J3a@R5d/ +j4f9wCQ +j5 +J6E5cXBAU0OV +J7ki0@UhG2 +J83Oyh.wb +J8laWZCvv9Nn +j9v7~xrg +JahO_B2VN +JBjqG~ +JbvIby +jC7M +jcd +jch4t2EgtMs +jco1~dxI +jCRzseWLi5Cs +jD~g +jDD2/- +jDNAUlB~f +jdsp2 +jdw9O3u +JeBYE8uqq@ +JEE.B +JEmS +jfkjdu4 +jFSt +jFUO- +JG +jg@1QOW +jgHD_m +Jh6eg8Dhg~J7 +Jh91x +JhKVx +JJ +jj4ph +Jjk +Jjl +jJzC8 +jkav3hw +JKtU +JLMMfU~ +jn0 +jO +joywETn_wT +JptoI +JPX +Jq/_qtEBMr/ +jQ2 +jQajKM +jQpabHo~ofp +jQxwme4qrA9e +jRkM3yu +Js1zFC@KWnq +jSdsBXcDn +jSDz6ckP +jSp3 +JSRm +ju +jU9jwzAJ +jUhoq +JunPU +juujOVYAmB +Jw +Jw4hrr@ +jw7gU +jwbuPEC +JWpcV@w +JWQ-L7jb +JWx4 +Jwy~4YLWmC3 +JxDSuBZ +Jyqtpq +JzJ.LVMFVdsG +jzMNpW@9F9ZA +JZT +jzZ@ukoSL +k +K +K_0S +K-X.kJS +k@Ro_@ASOm/ +K/HW-I69F6UB +K08Or_Qg +K1eGS_1W +K1o~nE +K2 +K2je +k2l0.tto +k3fBRE +K3sXU-Re.S +K6 +K7 +K7O@RgIjv9LU +K7tSng +k8~ulyQT +k9G +k9ro +K9wNcm5LMGG8 +ka +kaJwOfYxUU +KaO +kBayE +kBFh0K52i +kc +KcHad7Os4iY +KcIX +KcqdE~0r +kd.1vfG7t24J +kD.MK4W +KDmq418 +ke-Kq63x +keJ/wHnK.. +Kf2 +KFyY +kGEOhwBfcYr +KGTDE.K +kGUPiC~@2wb +Khad_ +Khde +kIDjYEz +kiekBCRZBa +KiiHD80lVLC +KIThZZ1rgH +kJ +kK +kkuP +klD +kM +km~H +KMOh +kmREUoPNK +koS2wj/7U8 +KOtNoBE@Z8 +kP2WR +KPHXGz +kqZBBs1/2 +kr +kre +KReMhHjN1yJ2 +KRKLxbttfp3 +kRNs +krTqM-0 +KrXXZkbL +ks +kt. +KTkMNAA@-/6 +KuQ +KUTX +KuW469 +KVMO +kvUzStvNuT +kvZCccKhUNC +kwD +kx.1NQ +KXjgBhU1ZPQ +KxpwuG +kXwnyzP +kxWuCJqjAd7 +ky2WjsP1l +kyfa2JQ02 +kyfr +KYLksQ9K5jyO +Kym3_nB//1r +kzLtU1b23aF +l +L +l-2hk +L-tPqE +L.HaQEl9 +L@@J@gDh~NYs +L/_dzHnTu +L/8bNRkKn8U +L0I +L1RvQ2 +L2 +L4sEW__AD0 +l6Kk-@Nou +L6QLP +l7bRfkRzzEJ +l7m4G +l7MOP +L8j5DtS3pV +L9xc3ouo +lA6UUr23 +lB6sEZ7hAX +lb7Lx +lb8Hqcn6J +LBwV +lC2Qjh2 +LCrgdGom +LCVlKD2pGsV +LD0frYMKff +lDCrYj +ldh +ldhu@n/Yjy +leQ9qXOkka +LeSR1MS2sDv +lf9ZtL8 +lFadi_V95XW +lFd90k +lfDdL9 +LG70xGPlgilg +LGtFDSy +LHtYkiTQ +Li6o03qOADlm +libc +license +liJen@Ywt +Liz.o~Yd +Lj@9dc8.bIz +Lj5AtGZ. +LjBxWK +ljOcE +lJVn3LKuw2bh +lK~lzTw +lkd8 +LN +lnbA +LnbY +lNgqsr/Oed +Lo6A3XVk3U +lockfileVersion +lOWGAX2 +lPA1~l +lPub9kFRO +lqrVDahR/UC0 +LqW3 +Lr +Lrzy3S-y11SP +lsBVq3-vW +lTSC__m-ey2 +lu +LUT +lvH/lFb/xa +LVIY0 +Lvs.NAO +lVzi9CRGJdN +Lw8 +LWSh~lOLx +lwvG1n5 +LwWrsmQHA~ +lWyLKVTooMrl +lwZcQAiMz +lx7l5unkE +lzQJb8QA3 +lZsCpSs~5aiU +m +M +m_JO +M_PrqAU0 +m_Vh6fYKFbb +m.E4.4s@4 +M/YI +m~ +m~ucqMf +M0 +m0YsM3nYh~o +M1 +M1EpEt +M2AXvR +M2F4/eO~oGv +m3@d1~ +M31~58wh +m3NkfCLopWd. +M55nM +m5WE76ya0 +m6FS3 +m6te +M7HVH8LnI +m7UyLgvDTS +m81aK-4b +ma +mAA2i +maF +MBm +mcbXjH- +MCX6IRJ6 +md +mD5WXh420w +MDAKWnUxc1nb +mDV~K/0K +Me2AsJUb~jb +MEks_0VZ +MEMf1@YKStR +mFF3T8Vo-PT +mfiiP +MFlB05H2FE +mFLQX~QR +MfxIrb0L +Mg4xhGk +MGiUe3K@ +mHu5LzT5/y +miJqae1 +mIupR9Koid +mj0PXo +MjJ +MkVKxPrVz +mKzlULq +MlNaMrv~K +mlqtf~WoUkO +MmVh4 +MNM +mo3M. +mOeUe3VmOS +MogNQP +Moj +MoRU +MOrXX +mp-6Bz +MpE +mQ +MQ@w +MQO00B@ +mqX5u-ffec +mR_.BZr~c5n +mrBX2D067ld. +mRca +mRP +ms~xWa +MSvRVEnZ +MTEgNh@mk0sm +mTErE8ry0 +mtP +mTq1mh~W8 +MuI +mv5hDV-lbH79 +Mv8/m8 +MVQJyzisS@ +MVrG +MwshT_ +MX +mXpl3__ek2 +MXT3w0JlY +mY +My25ugP +mYqq-l75 +mZ +Mz@ +Mz@d1x15g +mZ~Sd +MZS38OC~ +n +N +N-r2E7k48 +n.B5 +n@L +n~Xzc +N1x +n2L8dD/3Wshv +n4NvCRwi +N7mFq.gixOFY +N7u/ +N9ILg8~fCx1x +naJ82 +name +nC +NC5 +ncriga7 +Ndo8-zrua6 +Ne +ne2WAw +NEw-4AdjAu~O +nF +nGR +nHLBy@ +NI-RXHXa +NIw +NJ +NjL71- +nJnhMYglLLH +nkbMU0 +nkm +Nlh1AcAkiDM +NLoqnw +NMVAhNC8Bn +Nn +NOb30zu0T4Uk +node_modules/@scope/pkg +node_modules/a +node_modules/a/node_modules/b +NONByNG +NQ +NqCj6_DQn +NQFC9n +Ns/P0D~I +Nsa_qYDpEq +nSz +nt +nt@ntlg1K1 +NtD9msH +ntuk1.YF.D +NUKu2zuFj +NWy +nZGBWASPyrC4 +NzNW_LY89x3y +o +O +O- +O@ZQJICEB +o/OSFhpbr +o/t +O~r5WIL +O11grJ +O1bihj1Mf +o1WMNhyPU +o2~bPMWIwTum +o2geAh@4uF +O2mdHBTEa7 +o3QXdtBwihIP +O3S +O4IZ.TCRR +o4oO4@v +o6cLczN-LdFv +o6xDyoCyfcpI +O7 +O7~Muu2xgQ +o7b/sJrqgK +O7DY8hOe9 +o7MqGvO7oaEv +O8 +o8/UXpzl-1X +O9cbubP5dJkK +o9Z8iy +oas +OBYm0acjUU6o +oC/E9IUl@ +oCF4Z2MR8D4i +oD_ +oD2zzmVL/UjD +oD3R +OE-DMQUt +OE@RAQnVn +oe1HUq3jFj-l +OF5FJBdXp/17 +OGjg4BF +ogo8 +oh~_JS6osNtL +OHcQ~Ed0N8 +oHLd +OI +OI-s +oi@4gqlLu +OIOmze8vc. +oj~aXhIx +OJiLM +OK +oKjPr4a~6 +OKx +oL@AjMs +oleDgXLp +ON2vWTbC9Uf +ON9L +ONLP +OnqZW4GUAPJw +ONrXt~U/o +OO5r +oOAu6.Cc +Ookn6 +oOxAfLaT +ooxnE +Ope@Bbu6kg +OPJX +optional +optionalDependencies +oqs +Or01W +OrG5 +OriySK +OrrBfX +os +os7pmH1atYI +OsdVDE +OSesp2WuaHeX +OSGls +oT9eWMN/nQC +Otx/~mC~ +OtyqTQ +oUb5ptyU +Ow +OwqPg +owRcj9C +ox_lb4l +oxqTe6Sd +Oycybcj +p +P +p-5F0oG +p-GI +p-syr +p@RxQ +p/ +P/MojRHeQxw +p~7oEx.39tX +P~hOU3GTW9Y +P~StyJ +p0/VQ +P0iPppSenSF +P0pCitpzjNqW +P0Vsm7zQV_ +p1_zLFG +p1JybYy +P2Mu0U +p2XW +P3/trLWE +P6W@a313 +P80WWWkp +p9bcPxOB896h +pa +pA +pAa0kMGsqEX +packages +pAYxE640Rdjf +pbK +PCBJQzQN +PcEWTteF +PcVRc +pCy.KT +PD0 +Pd5bHF-JuR +PdS +pDZ_4nLGJETS +peer +peerDependencies +peerDependenciesMeta +PEHV1BZsOU +PEJ +PEjjoZ +PENeP +pFTP +pfZE +PG_e +pG9wr +PGe.vXeLU@ud +pGec4 +pH +Ph8V@scG +phPSswuaW@cY +PIDR4fq6ur +pINFsNPy +Pj +PJRUjtFe83DO +pK/0xlZ +PkD +Plf25Fcw5Xt +PltgvMa2eWOQ +pm +pMerVVOx_P +PN-iwhpS +pN6 +Pnf +PNN~/1Dm +pnxO1z0 +PO4FMu93m08L +pO8Ov@J +PPB_n1X6W +ppqyzpqzYd +PPTxoG-xh~z +PPZtUC@jEekC +pqAYZI +PqU +PSDHfDS +PstheXcY3 +pt +Ptk7 +PTq28@HJErA4 +PTRlvSaVL +Pu +PU_Zrh~0 +pV +pvL +pvNIiletd +pvT5NjS +PwB2Oztkj +PWqMVV9G +pWr5d1gYSF6 +pwwYy2A +pwylGC_x +px6YPipYK9 +pXEi2_WSFYWu +pXHPwLbr-B +PXzTU +py@lo.acG +pyQ.R386eo +PYRfyOER +pyrh.yBNOL +pZQppZ +q +Q +q_us1alvg +q. +Q. +Q.8~Z@ +q@.cagI-G +q@4EBq0Mb36 +q@gB7bX3Et26 +Q//d.47~ +Q~OPS +q1Nf~P +q1X +q3@s3nwQ~9Wg +q3jnuQ55u9PD +q6JhiMlp1c +Q7kNUSD/JG +Q8lSeIEb-YF +Q8uoF4b8TUw +q9 +qA1stcK +QAg94s +qanx +qB1jQdA_ +qBS@a/lj3M +Qbx +QBzyzIg +qCK +qCon4xwKA_P +qD +qdI/A8kG +QDLu298emnmN +qE.KM1~z4Y +QE6t +QeFzOo +QEWmP0mVd5Z- +qF +Qg7h9GGQ/v6i +qgguSDzHxo +qGqB.nKFrP +qHg +QhPbwX +QI-k0v8wdb +qIw8K +qKd +qkkM +qks +QlE8GtLhi/G +QmnOTOzxg +qn_G9 +qNFzEg +QO8Zhu1 +qox0616V +QpF322D9G4/Z +qpI +qPpSU +qq@bSi3 +qQ7kPIag_ +qR2 +Qr8dXoI_80Fg +Qrko7ZlP +qrQOWfG5 +qRspweCDM2fd +qS8k2l7@gWOs +qU +quk +QunmHCr33Nm_ +qUvKTDH.bHeN +qW +QwG_w.t8O9 +qwkxPSL- +qwoJo +qwXhYsgHVP +QX~w0~lPxVh +qyLzrJ +qyQz_pkXvU +qZ@sSs +qZM +r +R +r_EZ +R_x~3 +R.bgiu +r@Bq6-rh.9t +R@jmGvSz +R/~O2YM0r3T8 +R/sddn-4R +r~OvUe +r~wl +R0ObjMo6p0Nf +r0w7RbFSlF +R1ffqIId +R1v +r20.JI +R3nEVJpC +r48mh8JPR +r6g3B1PWZ +R70/1mGB/ +r85 +R990GkQrKamx +R9v +RA~g4XX +RAbWQrQT9 +RAXSQUQ8D +rBbFPE_@@ +Rbm +RD.tkwomS +Rd6pf4C +rdRxl@k@3Xs +requires +resolved +REya16Db_ +Rf9Ew@vDBF +RfpvyH3O_L +rGk +RGq +RI_SItXZmd4 +Ri-ArRIxH +Rjxy6TO +rKBCGsln +RL +Rl/GsqBa4 +rm +RNF +rnIkb/0qE +Ro +rOnHvoGz +rOq~BUShz_m +rPfj/QR +rpn +rptc~ +rrDFh.yNOPR +RrEIa +rro +RRtxXkr2 +rs9 +rT@3PT +RT5.FbpZ +RT63 +RtC@l +rTiFQk +Rub +RUEQOIzd5 +rUv_ImeY5vCf +ruY3f9sn6nP/ +RVM7nfgA8@pl +RVNDow3 +Rw65MQHE +rW7 +rwFG5 +rwkWn9-YX +Rx~lczQ/2W +rXNOa +RxT-xD8W/._c +Ry6BwEZHzpec +RYF223v +rYwD +rZ@WVNN4D +RZLsve32~ +rzPPXte4 +s +S +S_w9ZnR-R +s-rkoNPs8jMU +s.YfbOe3.e +s@5mv@Hj +s/1Kf +s/QhsTla/t/ +s~avr-H +S~VwkXyrvE +S03pbEs1ts4 +S0ce~ku_AX +S0Eavi +S0gQ~Q.pQVt +S0vhHC +s0Xn8KGLEix +s2M +S3 +s3LrefKm +S5dtX +S61 +S6V@2xLoBT +s7i~/BWMRiz +S7NV@ +s88/zv3f5 +Sb4lHS0B +sb7Ml +Sbc +sBDj.UqyXc +scBZ-di +scf +sCKT +Sd +sd/p6jTsikt/ +sDy +SEJ.b4wM3.~ +sEmJ +seYzL9ABVd +sFjd +sh +shfrbi +ShlThjDdC2EJ +SigVTmX/@Aas +sIj2 +SiLiF +siRcbbAnUE +sJGLRJYz +SjW~Kb +sk4SBU1D7Ed_ +Sl~Gah3 +SL4hapLRU +sluiJk3h +sO +sObIrOxVsy +sOqNE +sos1Om +Sp4y +Sp6gXtgVeH +sp7kAX~cKk5d +SPEl +SpFVmXaebyS +SpXdSM +sqA-k +SQdf_bB6.2 +sqKP8RsK +sQX4gQ_@aF3 +Sqz +SR.Noh +sr99WZ~_g +SrIIsN_f +ssA91ZX +sT@9ZWcTPbYY +sTxwcY +STyN/J +SU~E7 +suJJTZ3Tv4~ +Sv6WN5kZOpXX +SvhI3ve23dX +sWQE_cFLtzi1 +SwXN8x +sX +SY +sY1 +sY3Cwbw@Bh +Sy4iblC1_@8 +sYzfyU +sZH-LR02eZT +t +T +t_GLrcN +T/8RV +T/PGTw@ +t0 +T0kaRHkSBn2 +t3clAnY +T49lYt6 +t4vgRho +t6co0R +t6h-fL +t83sje +t9WW_j0Ga +TaDXPBnhgj +tb +tBe@-UFu +TBqY4xy8 +tC +tcj- +tD +tDDA +TdlKbLVnRB +TdM +tdNbLBOfN +tF +TFC@ +tFN3 +tfNXEfyddx1r +tg~ehX4 +tGRSoN +tgU +Tha2Q4PtrFv +tim70FZ +TiO88hAbd_ +Tj +Tk +TkoMYspoi +tkUwH2 +tl +TL4Y +TLCn1.nEmCW1 +TLU +tmc +TMr7dAM0fpHV +TNog8MJ +tnZghjhNq +tO~ffV6S1I +Tpfj +TPSzGq +tQdA +TQFN9ME6 +tQjbix +trDVqL9Jg-Iz +tshDrmQwG- +tSwUT~qz +Ttbu-DxTv +tTSA5R7klp +tTtZ~ +TUK2@ +tv2 +TVkX4a +TvN4Nn54ADIY +TVNUwzm +twAP1~e +tWs~ +twY0.EEDPk +tx +txgBJ +txkY +txzGF1 +tY3BlGi +TYJ7_8Oa +tYPtkFq7~mc8 +tZ80D4 +tZuXqJb +u +U +u-Nzm +U.Qoi +u@0X1jqf6DLW +U@I.tm2Oujmh +U@jsDF +U/avh49TuE +U/ynzKa@p +U0741p +u0EW +u1KGsd/Fu +U1lV5 +u2qxftCfN +u4 +u41H +u4OWTWwc3Rz +u6Pp +U9WXX/-/C +uanwTEqc6b4r +UAUO2Co +uax0 +uBGlS. +UbgZVAe +uBYXY@ +ucef~-@ +UCjz +uCUxB +uD +UDE/rceSZ-jX +udft1VTE.Cpc +uDQorNqe@h6 +udXIqJ4X8GXI +uEKmNC +Uf8M +UFpo..7_TBLi +ug~mFO +UgOj1.Q +UguuO.zp +UH6 +ui3nUdKU +uiBPuA5~ok +UIivR.OJq8 +uJJhOE2k1S7c +UjoDTal1CHF3 +UjpvrvPMc +UjrM7 +ujxQrybJSdg +UjZnElrtKK0P +Uk0/IdPdg +UKNz6/7a +UKSAZ7t.I_ +Ul6lNSSLG +uleT +umbyFzTK +uMsmOQCF/B +UNu3FLBUj@rC +Uo~ +uo97Rkg2x +uoa6hapnKQTC +upFvD3lgHX +Upw +uQ_12l +uq7q@i4K +UrHlDy +us1dV2qYN +uUb2E1CFC +UuRZ6iu2qrrW +Uv +uvm +uX3l +uY +UY1weohygc +uYKUxR +uYOkV +uYpoD +uyW +UYw9ZI2Nqxi/ +v +V +v_ +v__jZL_ +V_SK +v-OdtTn1K +v-X.h +V.MIEy2O +V/ +v/K_T7 +v/v +V/Xp +v0-~_ +v10cT5D7F8o +v24EL- +V47qGC@418y +V5_47v0o +v58U +v5RIS_dM +v62Dm3 +v69_FuM +V6Q1Qki~k_u +V89_1R +V8t52EO3ZjK +Va1D9bH9eEe +vAI@fC7td@ +vb-4u-G.Q +vbH +vbj3@ick +Vc@3 +VcAMpcUsdgPL +Vd +VDpAeXcSwtP2 +VDqy~_L +Ve@ +VEmX/K +version +VG5S8u +VGR8u9 +vgzNHD +vH +vh-LJem +vHAUSgy2e +vI2YyfoOxN +vI3-i6GiQc +vIiSUp37Mi +vIp4x5mcO +ViUXDZbe +VJ6rH +vj6TjK4yAtRs +Vk_hiObJd +vKiSox26sJ2 +Vkm5OIs +Vlv6~jK7 +VNc +Vo +vo5 +Vq0~BgFDDn +Vqa2cCkQ +vR43CTQhg +vr7RI +vso6jr/OO.V +vsr +vsxLzLk8yE6_ +VTg3ZQTxuP +vU8K3do +vuf5d014@8 +VuM6bzcQrN +vV2pXO7uWWo +VVn~8Hzef +vWr~j_~sE4I +VwTvs7qR3 +vx0OC +vxdjx +VygQs_n2IkhW +VyhKz8Xj1Bk +vYV +vyYj +vZFpDPD +vZgKule@PN~5 +vzgm~ZUzoUQ +vzL/mJJ. +w +W +W_ +w_Y3nJ +w@Hz.Jvti4Z +W/T83G +w0nimV~QV +w1. +w1i_4.0 +w2D@Izx/w +w2fcCry +w2Mao +w32y4DA- +W3gVF +W3OIbJjGxo +W4 +W4@D_PNy +W402SXRqh4AV +w5Y5GLUDiz +w8e- +W8RPcj +W8WseM@bBLl1 +WA~yLxK~k +WbdPyh +wbJp +wBOAO_p78o +WbzmHxlo +wdBV +WDxW +we4TjlvHv +wEOVank +WeSS.W +WfJemSf0 +Wfx5 +WFXMAfQ_ok +wGmUrWKDQf +wguW +wHmmSRMYQ-. +whNWKZs9_99 +whS +Wi +WIgJHeoQBp +wj +wjWFCTVYKR +Wk +Wk6/ +wm0zRfiXwU +Wmr +WnkJf7Maa7n +wObV6NAGM7 +workspaces +Wot +WOVYoSp +WOwxad +wOy22uu0BE +wQ1 +wqUkNg +WRDaJa +WReMMXs +wRi0 +ws@pwavT7s8Q +wtFryHdDe-B +WtmFyMJhNc7u +wuADjs +WUMCE +WUNIFzn5t +WUyxw86XS +wvCSfJwF +wVrnmHTqM0M +Ww_Ykl5 +wx~6ruQq +wXFH +WxN +wxV +WyJ2E702vmM +wzJfIX~OaRZ +x +X +X_HSTJBD.M +x.eXbMMXy +X.h +X@jK +x~ +X~5l +X~Zl +x0B +X0q0K75O. +x2c2N~A +X2Q6 +X2xH1kXslH.U +x33h +x3MH/L +X4 +X4Si +x5XCPkv +X5xDGioPNh4j +X8Ac10QuBiL +X8qM6Ldpl +X9@GZNX@u8yH +X99 +XaQuqR_RnJ +Xb8s +xBo +xC +xcc/4eUg1oq_ +xckzIkeNH_ +xD +xDf +xDF +xE-4uqebfZG4 +XEdYV47J +XeJ +xElB +Xf79iHq +xFDlxip +Xg_uO +XGp3bAikJt +XhZPRVZMcZ- +xi +xIcEqKpoTAiw +XIEaq +xIFV_oUx0b +XIMgiGYG.8k3 +xj3XPv +XKA@9.E7V0De +Xl31KaIO- +XMhASKMxznF +xnERre@L +XNMyd +XolFWpr2uMV +xorz/JZHyds +Xotv3 +xPHIzX0vBXNa +XPye +XQN14sV8DM/b +Xqtvnc~x +xr +XRLqBuVO4lx +xS +xsCOOXN +xsLE@Y/D +xTAuP +Xu.@PS.H1 +Xu97.~3NQV2 +XudE +xUkToq/8cMW +Xul7tV +Xv4xUnSwky +XvDUg9rQUC +XVm8RO/a0 +xxj +xy +Xy +XY-Ef5oMFN_ +XyBqsErkz +xyqG1V +Xz +Xzh6b5krR +xzxHBpXhEOk +y +Y +y_-e4xr6mN +y_F5F6 +y_yACjQL85Nn +Y~klE0Yt +Y0PHb5t88P +y0T +y1 +y1D1B2 +y1emeQLB_@ +y1xlU1K +Y2_.FKK +y2RHhvA7qz8h +y40XkWK_J +y4ArzCI +y6W +y8l +y8Mq +y8Oi~PYyMAr +Y9f +yArk~P7 +YB6h5EJMzG +yBAV +Yc +YCGx/NKjyn +yCR5W +yDpD6U97LT +YeQbeip@to +yf9eL +YFVUxn +YGOVvWdL +YhEk__NA +yhjjV0TtUOY +YhlDy +Yi456EOdFt +yI9J +YIFA +yiK~pC +yizF +YkSBhGw +yLN/oZ3 +YlnxN2 +YlvHTE +ym +yM@2ke +Yms +yMX +Yn.F +yn30EmkHZsS +ynWR +Yo4V +Yp@dO82 +YQG1 +YQM. +YQWtIybSLWUq +yR95D.sgcC +YrjY +yS +ys_F7xLfiz +YS.KZtOek +ySGO~JTz +YsI0kpxHDf +YSNtJWT-QvqK +YSpcoRJV_F1 +YtkiM9e9 +ytr +yU +yUXEdIA +yvYzQ6GPr +yW0pbqf/QBx +YWnG +YY8 +YYfY4k +yz +YZ3XD6I +yzurQ0A +Z +Z_aq8NTg1j +Z-h4d_hTZ +Z-KyxN +z.ZQ +z@M9wyFBb +Z/1 +Z/F~A +z~ +z~8 +z~xSYy +z03leD65Ot +z0II2ItHgK +Z1A/_pEtE +Z28~WrD +Z4@o0NgYt7I +Z4ucdQTOukJN +Z52B_7 +z5ghZBS +Z6_J0 +z7qRwLdMh +z7Z2OITInHb +z8r +z9HR0tz. +zaq.uLYQjx +zbFFZaC +zbJzOHeBfB +zbR +zbv.A +ZC@FbTzq +zcecGXS +ZCpD.ekmX +ZD34~7w@gd +zd8oV +zDWkF@RqQg +zem3lATtt +Zf@ +ZfkD +zfkzVsA2uh +zftP0uz +zGL. +zgtFDCZ9 +ZH.FNJ +zH.o4~Q@PO +Zi2t_fl +zI3hsbX8IL +ZIG +ZIH7 +ziSERe +zJa +zjP +Zk +ZK +zkx89b +ZL +ZLj +zlJX0.L +ZLZ-PSLbMFSA +Zm +ZMOOTJ@C +zn@3WsdDL +ZO-GORc6B +zODU0 +zOHHH.O +ZOPULedHsR. +zOsgRLMM8e +zpziD.4MGGaf +zq~f +zqhwJD4w +zQN +zqnpcIh +zqU5_oa2 +ZRQ4 +zS +zS-H_bju +zSbk +ztMQa1tw +zTzD +zuKTgF~raD5E +zuNe9Uz4TnK +zuT_sOx +zVF5o +zvj7Sy5JNF +zVRcFl~_ +ZWbNl +zX@h +ZXKUPDPr +Zy +ZYlWjwC +ZYy3H +zzai_cjoCQX diff --git a/rewrite-javascript/src/test/resources/npmlock/override/http/is-buffer.json b/rewrite-javascript/src/test/resources/npmlock/override/http/is-buffer.json new file mode 100644 index 00000000000..5ec3b07e34d --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/override/http/is-buffer.json @@ -0,0 +1 @@ +{"_id":"is-buffer","_rev":"28-73311ada934bee2c9de88d107cbcfe1d","name":"is-buffer","description":"Determine if an object is a Buffer","dist-tags":{"latest":"2.0.5"},"versions":{"1.0.0":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^3.0.1"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"tape test/*.js"},"testling":{"files":"test/*.js","browsers":["ie/6..latest","chrome/4..latest","firefox/3..latest","safari/5.1..latest","opera/11.0..latest","iphone/6","ipad/6"]},"gitHead":"fdb526a9a5abd518bfc007f9f919bbd478744311","_id":"is-buffer@1.0.0","_shasum":"680b48b0cb42ee3d38f0955bcb9855ee945e96fd","_from":".","_npmVersion":"2.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"680b48b0cb42ee3d38f0955bcb9855ee945e96fd","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.0.tgz","integrity":"sha512-6jQz/P5E/2ZZvtEABMrCjBsGX+u/6asGpaGZlWgGoVkkoK+kO4E89ZByoOJyqRMES/K2ZKoF6hNaYRKPKW12ig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCu+gjaka98lin9rOIEiMslLTlYZ9+GDpgJVFYllZutTQIgHvF6yyqyG0hTDEBkD2hPNy3TZ0XEUSqdOMmQSqY6C4M="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.0.1":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^3.0.1","zuul":"^1.13.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"66496a59f1e0ed0d57bf4834113aa62ed874c9b7","_id":"is-buffer@1.0.1","_shasum":"d4050649838354e87ec59c964c1fa1f4bb7de00d","_from":".","_npmVersion":"2.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"d4050649838354e87ec59c964c1fa1f4bb7de00d","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.1.tgz","integrity":"sha512-v5AmIvDrnYZZuFRYKUvb12Z89TysfucZn9X5e7ZGo2eTGYhtpJrNaTDFAaKWzTRKgSKIYfg9/ekeH/HGaZ5d+Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHqy2oP7TAzbzrfvQB9WjDtVeHxX8fsGdn3KLeD63grOAiEAkdEZ0Cr9TPZ0RLWUHec2/VBeLLMIP+3ILdj5qwT06qQ="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.0.2":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.0.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"cad65fd0f6844c296c743c4ec521c130224de90e","_id":"is-buffer@1.0.2","_shasum":"f5c6c051d73f86f11b4ee14267cc1029fce261d0","_from":".","_npmVersion":"2.7.4","_nodeVersion":"0.12.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"dist":{"shasum":"f5c6c051d73f86f11b4ee14267cc1029fce261d0","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.0.2.tgz","integrity":"sha512-LxnVw0B8/L3u3LDQGh9k+c9h0eO9rEDup9f4itjqAZ68b5hvUnJTwmLtnuiuY+4WELfq13vu19kiFdxDBLqrGw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICLyWm5reQS8J7CzRFptn7D077RU2fKHi6T2tG+3w91WAiEA/DPIf6pSovP1VL+8MBG/TnoYmO/YLRQLPOgjR0iDgfY="}]},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.0":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"6ca106240e155ea4cfe13e2e1c83aadab91d2ec1","_id":"is-buffer@1.1.0","_shasum":"36f7850c0d077a71b041f3565664155f07035bd0","_from":".","_npmVersion":"2.14.2","_nodeVersion":"4.0.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"36f7850c0d077a71b041f3565664155f07035bd0","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.0.tgz","integrity":"sha512-wu87Ow/wnXpH9Ahk3X9HNEpEuFFeDtuG1+CRBPiprlwwR6FS5cCjQul3uuWP8z/xUa+YR3vb6UB9DqT+4KD6jg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdUQmUy+OKoxc650apjPrIfHMMu2p3/8YTpbEfHr5egwIhALFm6QMOQ56MuRCv/nmtXmJSr4dOXQ06aTJBdjYOj9rr"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.1":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"9ccd67d6ca6476d1cb7b38fd9fc7d9d71d212f5c","_id":"is-buffer@1.1.1","_shasum":"3058de9ca454564e8bbe5b8dd2719a8d7089e7d7","_from":".","_npmVersion":"2.14.7","_nodeVersion":"4.2.3","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"3058de9ca454564e8bbe5b8dd2719a8d7089e7d7","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.1.tgz","integrity":"sha512-03w4ew2ozAWFhFOYg8YE+iuXmysBtd4mdDK8wOQK56j5E9iXpdE/Ael/vxrxW5IVOPn+tTTCbgH9rfrOsEermg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEkLQedBqPfASnZpdpre9GZN3yZFyCnMxxw58SoIMZRRAiBRjR1fGQeUHLtA3PJ18+bSl766j69C81b18io9Yq3oQg=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.2":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^5.4.1","tape":"^4.0.0","zuul":"^3.0.0"},"homepage":"http://feross.org","keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"ba9a9f359e4412c90c583e14492072c9f4f2d45c","_id":"is-buffer@1.1.2","_shasum":"fa1226588fa0048b005c47e4fb1bb1555d5edeaa","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.2.6","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"fa1226588fa0048b005c47e4fb1bb1555d5edeaa","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.2.tgz","integrity":"sha512-+SAQKwgmiLKfRw7j5xmb2NGzekvz2bTSsNdMDDg4WkXBQvcB5dVz3oKWHQid8oQCMJzDR2CxRqx8XqZD9voH3Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEgqFfCbYOW/j+D9RNNvTTJudba9Jvw/FPfUzWYnU0Q8AiA5chCLOjpiqHxjnJjo0UnhXt8tGvTB195hE98WpSwdBw=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.3":{"name":"is-buffer","description":"Determine if an object is Buffer","version":"1.1.3","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^6.0.5","tape":"^4.0.0","zuul":"^3.0.0"},"engines":{"node":">=0.12"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"dfd658d887e6b63254b89d22af1a755a39313455","homepage":"https://github.com/feross/is-buffer","_id":"is-buffer@1.1.3","_shasum":"db897fc3f7aca2d50de94b6c8c2896a4771627af","_from":".","_npmVersion":"2.14.12","_nodeVersion":"4.3.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"db897fc3f7aca2d50de94b6c8c2896a4771627af","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz","integrity":"sha512-x2bhGIVgreQwjcLvzJRsdrs2wyguhnLgfrOWIK/+6rEJmWO3IS3VedcLYcGZiVwlCzhIIR8JngztGjJyqEs5Nw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSGBDaNE3l/CHjUBIMxoqZtodlqbjeeiu+xzI8sUJsLgIgBV0/eSbTUETloInCVdjj80k1P3mvn7nd0flhGQ72edw="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.3.tgz_1457390977775_0.6384289276320487"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.4":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.4","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"^7.0.0","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"fd1a429f6ab8092f2e39cb5cc7175b5d9a986c31","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.4","_shasum":"cfc86ccd5dc5a52fa80489111c6920c457e2d98b","_from":".","_npmVersion":"2.15.1","_nodeVersion":"0.10.46","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"cfc86ccd5dc5a52fa80489111c6920c457e2d98b","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz","integrity":"sha512-LdKAPZcV+EfT6PvN90Un/Rnn1g8cL1BfzEBdz6d3Y6CUzMyUVWHewXxyuiNFkLwRKgpDMYHrocdqjMsYTDkOow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1P8GIhF9+E6/P2FbZolCrtNplQtwv4jHQZ7xT8b2QcQIhAMl5wfPPyGfOABP3B3rVaUdXdxoR65VwiuzqmecjG1Vb"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.4.tgz_1470267365943_0.6724087686743587"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.5":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.5","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"56dc50e7b271c7d2968269430cbd4f717bbcf6c0","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.5","_shasum":"1f3b26ef613b214b88cbca23cc6c01d87961eecc","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.9.5","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"shasum":"1f3b26ef613b214b88cbca23cc6c01d87961eecc","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz","integrity":"sha512-miqftL8E53hH0dtQqLdN+3JwClyJiITcif3gy+RiUlnLJUhEwdyRC29/gpYbuC9IhazGSnP8TjbvxWw2AZylWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAv+Vaqofnno8Drwu3I23xGZGjOI7wZXM8aLjw8Tq1fSAiEAzZLzlH8vWqNn0uR7z2sv9gXoOGQlHlmqG5Aq06YWz8E="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-buffer-1.1.5.tgz_1489193465717_0.9356542676687241"},"directories":{},"deprecated":"This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer"},"1.1.6":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"1.1.6","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"http://feross.org/"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"keywords":["buffer","buffers","type","core buffer","browser buffer","browserify","typed array","uint32array","int16array","int32array","float32array","float64array","browser","arraybuffer","dataview"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"1e84e7ee31cf6b660b12500f3111a05501da387f","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@1.1.6","_npmVersion":"5.5.1","_nodeVersion":"8.6.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==","shasum":"efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDQAnODX01K6w5cJdtd+M5OyeiiFZL0r/VpvrwjdJcEEAiEA1n9Pq+avL75FrFQdoA84fBlUmeqf25sOcbsEXxHQh7c="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer-1.1.6.tgz_1508967388794_0.03916449216194451"},"directories":{}},"2.0.0":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.0","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"standard":"*","tape":"^4.0.0","zuul":"^3.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"zuul -- test/*.js","test-browser-local":"zuul --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"1a8ab13257c3bb000b51ee1892c194a1be9f2759","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-wsnW8g48qGzmZRy7yregikay4LbHR4yKdiGIhNnZobvTlEEy9O8cOh7jmo7J83nYdJM+4Qi635zgq4YLQwSt/A==","shasum":"224d784b0ca3dcc2ec42c5e75a4150fb7d8fdede","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBhK78myUJs2IKqHkIiLrZKKKsxNl/4CN6blEyu09hbNAiEAmyDi9jFzNTtgmh8Af5YCUxdCnrK1nvQS6e+kGojXpJs="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer-2.0.0.tgz_1517211799580_0.7924200457055122"},"directories":{}},"2.0.1":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.1","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.4","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"f5b7d4018818037cc3bd88e6e5d85b15e0012552","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.1","_npmVersion":"5.7.1","_nodeVersion":"8.10.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-eDHjNN2G4M3hNNPs4dWwomvv0oNChLEAgoJ1TUiBNbEfQDrfG+kA8BLmBKh+A30klH8tOVimp5j5IDkmEBcEsA==","shasum":"e14769efa70ba71162bda9852dc32362e01cca07","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.1.tgz","fileCount":7,"unpackedSize":6009,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB65TjJXMz/JTM1KPIFXv89jmXZuHhHG4rsuynzAZ87tAiAFwTmYimVL+7dmRVOKNiF2Y5ceXLdeQcS3qoxoYbRtuA=="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.1_1521286431970_0.9562908337278884"},"_hasShrinkwrap":false},"2.0.2":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.2","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.4","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"f9ef52cfcf235a84ce8167120b539b540a3a60e4","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.2","_npmVersion":"5.7.1","_nodeVersion":"8.10.0","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-imvkm8cOGKeZ/NwkAd+FAURi0hsL9gr3kvdi0r3MnqChcOdPaQRIOQiOU+sD40XzUIe6nFmSHYtQjbkDvaQbEg==","shasum":"f83a0c5bc453f6431bf83cc2ceff6cbc9d50a83b","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.2.tgz","fileCount":5,"unpackedSize":5234,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuyQCp0CPE+UpLWsBx4jMLhoHEDV77g0HVAJcce17PnQIgZzKEUcH/KDGY16okocQ4xE8nDtJEcqjFSmJBK1rEH4A="}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.2_1521286476893_0.01566582587333687"},"_hasShrinkwrap":false},"2.0.3":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.3","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"0.0.7","standard":"*","tape":"^4.0.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"testling":{"files":"test/*.js"},"gitHead":"e05c7852e1a978b81c7eb6d677c861a7dc935ead","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.3","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"feross","email":"feross@feross.org"},"dist":{"integrity":"sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==","shasum":"4ecf3fcf749cbd1e472689e109ac66261a25e725","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz","fileCount":4,"unpackedSize":4263,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbHF+HCRA9TVsSAnZWagAAJV8P/1beDL56nRgP75wKwit1\nu7VHWrRQpqFhqmWs2EFEfOtfAh2CsHUJjfuYcG+eI9Lzblc5uJ1YzDZOEuEn\nRz1in3WDtuR/+YUxzVFla/jTUUFql/PC747aDXnaPd1HcWsxJBmvbtDfl9bU\nnsbahrPd3asehz9quWdDSfK8q7u1/S1ZnbykZJuJLLfpOyM7zRqAYYVUAA/1\nm/58ITilRc2ewIn0cWqsU6rmJYAPP8jpIm2z0DK0sWriuPhaNxKeFspW5MDB\ncphOgno7wy733FH7KK5pDVnKLLk3ABAtjV2DjrmF03Nqk+TPb0lCvEaFDcx7\nUXJLrek2cPXzwkixfzQ6q5GQFvZFQ88Ts7nXzGSo1+dHm1sfEXFEp8HpKfA2\nB+YhzCtEWYTWzIteEgfTD6s6zk6TgWE00bBZ98NUYnAfIEuTBMuuKSJMWbVh\nghnRWsSECCgyYtLI0lEASNHaCTqohgISJjQWEi4EN7OXXo5BinXJfuNfqzNm\nJwqbL3PiHmUSMfNFIMeWWWI+8jZ6EVQpw27C0z4L8JdUC6gFfHJ5Z0jPLmfv\nAvJK2w4oYnnNP2Fw4Jg5HHE/lkXTyabwOAT4O9zqUfVPieNnAFvLgOdlo6kD\nUXgPJ+YqHTY6n2l/s7WciMuV9u2AO+WtSKB+fpm0yHENKwUe1Wc2Ln+sJTn/\nnQSL\r\n=FeKt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/5ae6Fzj0Jx08b/2/ksoyAZF9i6wHFE+vow/LmwGhLgIhAO9/EiXe44IRHmU3SMYsLzCLUsZTctIyJfMqIu4DXNwe"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.3_1528586118955_0.08977150560838787"},"_hasShrinkwrap":false},"2.0.4":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.4","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"^2.0.3","standard":"*","tape":"^4.11.0"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"gitHead":"65d2f6ba6c4e336be90c3cb6a656a69ce8f24210","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.4","_nodeVersion":"12.10.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==","shasum":"3e572f23c8411a5cfd9557c849e3665e0b290623","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz","fileCount":5,"unpackedSize":4491,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdktqzCRA9TVsSAnZWagAAV5kQAJz2tApv60yY1cu9hU+Q\nuCPH64nGM/49IWWLtcX8dDjV1PkNwtp32MpspkMMmPE8nfzAuDaHequ6AEjP\nD/+usRbT8PoD0dDixzlR5a9H+FFohDvJOXVzNATQna/b9Q2dj7XOjEnhsEf9\nbRkJq2U1N/Qb+9Rgg9sgLmsZR1UCCdTR5PKPpVbHs0axQyeghaXPlenQoa20\nq2aDE/xQihsI4If3aQmLkrkpUYUsjDwEYTKXTPQNosGmQg5XsZK89PCFLVu5\n9t0qAZffJJFP+HER7BfszmE5F4yDFhvBNWyu2NtPtv0KiSNkGYo/D6Xd55j8\nIfq5SHuvc/Jy7fyrg3HRUBVzYJqOtlICjLdHv4L573eNPaJryR1TIzcMY33K\nBuHBjJ4ZSlGi0spS8JnR+xbT9JQ1siNDrl9gaAzoSvmJi6CnSTwusb6Ht2fG\nXs7a6v5lbClrONeOSbgTJWv4yC9rFmTr1YfrqVrVJG++4Q588AU4PfRn5KlS\nh//hylruEZrlAhFsSjWsK1AJLd+mNDchaFzWQ78bvosOw6mez/aGz2LBdlX5\nx74RvWY07lfwPwDjCvO+dCbKsSuAhigDUOj+I19ugYkq+LWP0zDFUtB1NM1i\nFqQYChp/FaCdMRKqNGwoN9LL20B9gSXNZW4R85AxvPn0wxvZl/PL7KH6riZM\n6ua4\r\n=DYpP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMPwxaKFo0xSzRWmLS86WkiEalo9AF+tGcZaR1j4IY7QIhAPfgXxctuV8LpKNOvYyhv/Q0drYAk/3Htr2wronuuRTL"}]},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmUser":{"name":"feross","email":"feross@feross.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.4_1569905330837_0.24488814934632286"},"_hasShrinkwrap":false},"2.0.5":{"name":"is-buffer","description":"Determine if an object is a Buffer","version":"2.0.5","author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"dependencies":{},"devDependencies":{"airtap":"^3.0.0","standard":"*","tape":"^5.0.1"},"engines":{"node":">=4"},"keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"scripts":{"test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap -- test/*.js","test-browser-local":"airtap --local -- test/*.js","test-node":"tape test/*.js"},"funding":[{"type":"github","url":"https://github.com/sponsors/feross"},{"type":"patreon","url":"https://www.patreon.com/feross"},{"type":"consulting","url":"https://feross.org/support"}],"gitHead":"ec4bf3415108e8971375e6717ad63dde752faebf","homepage":"https://github.com/feross/is-buffer#readme","_id":"is-buffer@2.0.5","_nodeVersion":"14.15.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==","shasum":"ebc252e400d22ff8d77fa09888821a24a658c191","tarball":"https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz","fileCount":5,"unpackedSize":4587,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoa1GCRA9TVsSAnZWagAAfIwQAJr4549srmyEUJaCF5Pd\nyQ3SwaxS4IyycILtQyyyOBHlbLcAS7LvuatpnyrRDr0bSx2EEHqVfo9jyuGw\n5L17J1WuUbddlCikCy1z0jzHROW1zR8inwd8Li4f/1FMbHlbTgWKpmQ/P6YI\nkYdP83CKgyVIKr6H8Qxk4oU5aGLN/YGT8AHlVLRL1N/d1m6c92QKTQnroEzY\naYjiKdpXeUfXq0vmuosT39mSBUFvNWEtkN51sgJyS9jBFMEcdA/SzFULgBfN\niScNvarNUCFG6UpIoagqYwwqQTrmrucCVoC8G1zkVgPBUYIKKeTq2hbAg4rP\n2yeHrEWYb8JsdkxfzSNR7xEsTeRx9+n/zY/QxQ/Bpzt5eiYFSNVU+xXOn6TG\npqEKgE2v0rdcGYMpMZCvr9TA5iChjEWg/LFlygCKGc9r5b5kIUcQ2hWU5+Hw\nyNpA5xwsev5erAYd8fq8hz7np8mnBj3d5hWLVTdFEvKBgTx3FcrVWPxNnEzc\nhmM5MndgOoiosIW6/Aq0UArTYYTnb+OIxZhscu+N3QMxjkX0DNfefGquy7AU\ndkA3ZG3TQSsoB1Qxblr4/CxbU32wIeBzfXEfddbBLl8zQOmf/BDKY+sZs97y\nUg0E9CkpWwMeVSxSDXOjuXMaIl4YehcO7hp9Xn3napfZ3R+dMPnurROwb9MC\nAR/e\r\n=DLTF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQm0iQk4fBuBsWIfDybHoSHV2rBcSai2o2gjHAdNyXQAIhAMg/omtFuJ9DyNMJQawXYSs2D3NXfDZO7Fc5b1FusD+F"}]},"_npmUser":{"name":"feross","email":"feross@feross.org"},"directories":{},"maintainers":[{"name":"feross","email":"feross@feross.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-buffer_2.0.5_1604431173638_0.6067186377033973"},"_hasShrinkwrap":false}},"readme":"# is-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]\n\n[travis-image]: https://img.shields.io/travis/feross/is-buffer/master.svg\n[travis-url]: https://travis-ci.org/feross/is-buffer\n[npm-image]: https://img.shields.io/npm/v/is-buffer.svg\n[npm-url]: https://npmjs.org/package/is-buffer\n[downloads-image]: https://img.shields.io/npm/dm/is-buffer.svg\n[downloads-url]: https://npmjs.org/package/is-buffer\n[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg\n[standard-url]: https://standardjs.com\n\n#### Determine if an object is a [`Buffer`](http://nodejs.org/api/buffer.html) (including the [browserify Buffer](https://github.com/feross/buffer))\n\n[![saucelabs][saucelabs-image]][saucelabs-url]\n\n[saucelabs-image]: https://saucelabs.com/browser-matrix/is-buffer.svg\n[saucelabs-url]: https://saucelabs.com/u/is-buffer\n\n## Why not use `Buffer.isBuffer`?\n\nThis module lets you check if an object is a `Buffer` without using `Buffer.isBuffer` (which includes the whole [buffer](https://github.com/feross/buffer) module in [browserify](http://browserify.org/)).\n\nIt's future-proof and works in node too!\n\n## install\n\n```bash\nnpm install is-buffer\n```\n\n## usage\n\n```js\nvar isBuffer = require('is-buffer')\n\nisBuffer(new Buffer(4)) // true\nisBuffer(Buffer.alloc(4)) //true\n\nisBuffer(undefined) // false\nisBuffer(null) // false\nisBuffer('') // false\nisBuffer(true) // false\nisBuffer(false) // false\nisBuffer(0) // false\nisBuffer(1) // false\nisBuffer(1.0) // false\nisBuffer('string') // false\nisBuffer({}) // false\nisBuffer(function foo () {}) // false\n```\n\n## license\n\nMIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org).\n","maintainers":[{"name":"feross","email":"feross@feross.org"}],"time":{"modified":"2022-06-19T02:37:46.020Z","created":"2014-10-31T01:58:42.247Z","1.0.0":"2014-10-31T01:58:42.247Z","1.0.1":"2014-10-31T03:37:00.562Z","1.0.2":"2015-05-05T01:52:11.559Z","1.1.0":"2015-09-17T05:02:36.041Z","1.1.1":"2016-01-03T21:09:34.798Z","1.1.2":"2016-01-29T12:52:12.824Z","1.1.3":"2016-03-07T22:49:39.950Z","1.1.4":"2016-08-03T23:36:07.367Z","1.1.5":"2017-03-11T00:51:05.973Z","1.1.6":"2017-10-25T21:36:28.871Z","2.0.0":"2018-01-29T07:43:20.568Z","2.0.1":"2018-03-17T11:33:52.032Z","2.0.2":"2018-03-17T11:34:36.945Z","2.0.3":"2018-06-09T23:15:19.035Z","2.0.4":"2019-10-01T04:48:50.958Z","2.0.5":"2020-11-03T19:19:33.762Z"},"homepage":"https://github.com/feross/is-buffer#readme","keywords":["arraybuffer","browser","browser buffer","browserify","buffer","buffers","core buffer","dataview","float32array","float64array","int16array","int32array","type","typed array","uint32array"],"repository":{"type":"git","url":"git://github.com/feross/is-buffer.git"},"author":{"name":"Feross Aboukhadijeh","email":"feross@feross.org","url":"https://feross.org"},"bugs":{"url":"https://github.com/feross/is-buffer/issues"},"license":"MIT","readmeFilename":"README.md","users":{"mojaray2k":true,"monjer":true,"rocket0191":true,"edwardxyt":true}} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/override/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/override/package-lock.after.json new file mode 100644 index 00000000000..6b889b09176 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/override/package-lock.after.json @@ -0,0 +1,70 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + } + }, + "node_modules/is-even": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-even/-/is-even-1.0.0.tgz", + "integrity": "sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==", + "license": "MIT", + "dependencies": { + "is-odd": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-0.1.2.tgz", + "integrity": "sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==", + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kind-of/node_modules/is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha512-miqftL8E53hH0dtQqLdN+3JwClyJiITcif3gy+RiUlnLJUhEwdyRC29/gpYbuC9IhazGSnP8TjbvxWw2AZylWQ==", + "deprecated": "This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer", + "license": "MIT" + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/override/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/override/package-lock.before.json new file mode 100644 index 00000000000..5c578f98294 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/override/package-lock.before.json @@ -0,0 +1,69 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-even": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-even/-/is-even-1.0.0.tgz", + "integrity": "sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==", + "license": "MIT", + "dependencies": { + "is-odd": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-0.1.2.tgz", + "integrity": "sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==", + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/override/package.json b/rewrite-javascript/src/test/resources/npmlock/override/package.json new file mode 100644 index 00000000000..fadff53488f --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/override/package.json @@ -0,0 +1,10 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + }, + "overrides": { + "is-buffer": "1.1.5" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/override/package.json.before b/rewrite-javascript/src/test/resources/npmlock/override/package.json.before new file mode 100644 index 00000000000..7eae1e3b15f --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/override/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.after.json new file mode 100644 index 00000000000..4dacccdbe27 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.after.json @@ -0,0 +1,24 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": ">=4.0.0" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.before.json new file mode 100644 index 00000000000..72926231ba2 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package-lock.before.json @@ -0,0 +1,24 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json new file mode 100644 index 00000000000..02c092ea30e --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": ">=4.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json.before b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json.before new file mode 100644 index 00000000000..665055ff253 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/range-satisfied/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/record.sh b/rewrite-javascript/src/test/resources/npmlock/record.sh new file mode 100755 index 00000000000..ccbe364bede --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/record.sh @@ -0,0 +1,248 @@ +#!/usr/bin/env bash +# +# Copyright 2026 the original author or authors. +#

+# Licensed under the Moderne Source Available License (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +#

+# https://docs.moderne.io/licensing/moderne-source-available-license +#

+# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Regenerates the npmlock engine fixtures from the live npm registry. +# +# Each scenario directory receives: +# package.json.before manifest before the recipe's edit +# package.json manifest after the edit +# package-lock.before.json lock produced by real npm for the before manifest +# package-lock.after.json lock produced by real npm after the edit (the golden) +# http/.json full packuments for every package the edit moves, +# recorded at the same time as the goldens so the +# offline engine replay sees the registry state npm saw +# +# Byte-identity of the engine's output against package-lock.after.json is only +# meaningful when before-lock, golden, and packuments were recorded together +# with the same npm version. Record the npm/node versions in README.md when +# regenerating. +set -euo pipefail + +cd "$(dirname "$0")" +REGISTRY="https://registry.npmjs.org" +NPM_FLAGS=(--package-lock-only --ignore-scripts --no-audit --no-fund) +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT + +record() { + local dir=$1 before=$2 after=$3 + shift 3 + local movers=("$@") + echo "=== $dir" + mkdir -p "$dir/http" + printf '%s\n' "$before" >"$dir/package.json.before" + printf '%s\n' "$after" >"$dir/package.json" + + rm -rf "$WORK/p" && mkdir "$WORK/p" + cp "$dir/package.json.before" "$WORK/p/package.json" + (cd "$WORK/p" && npm install "${NPM_FLAGS[@]}" >/dev/null 2>&1) + cp "$WORK/p/package-lock.json" "$dir/package-lock.before.json" + + cp "$dir/package.json" "$WORK/p/package.json" + (cd "$WORK/p" && npm install "${NPM_FLAGS[@]}" >/dev/null 2>&1) + cp "$WORK/p/package-lock.json" "$dir/package-lock.after.json" + + for name in "${movers[@]+"${movers[@]}"}"; do + local encoded=${name//\//%2f} + curl -sf -H "Accept: application/json" "$REGISTRY/$encoded" -o "$dir/http/$encoded.json" + done +} + +record upgrade-leaf \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^4.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } +}' \ + is-number + +record range-satisfied \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": ">=4.0.0" + } +}' + +record cascade-fails \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^2.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +}' \ + is-odd + +record remove-orphans \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + }, + "devDependencies": { + "is-even": "^1.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +}' + +record upgrade-orphans \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "chalk": "^4.1.2" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "chalk": "^5.0.0" + } +}' \ + chalk + +record add-leaf \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-buffer": "^2.0.5", + "is-odd": "^3.0.1" + } +}' \ + is-buffer + +record override \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-even": "^1.0.0" + }, + "overrides": { + "is-buffer": "1.1.5" + } +}' \ + is-buffer + +record dev-recolor \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "kind-of": "^3.2.2" + }, + "devDependencies": { + "is-number": "^3.0.0" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^3.0.0" + } +}' + +record dev-peer-overlap \ + '{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^4.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "devDependencies": { + "is-number": "^6.0.0" + }, + "peerDependencies": { + "is-number": ">=4" + } +}' \ + is-number + +record scoped \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "1.0.1" + } +}' \ + '{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0" + } +}' \ + @isaacs/string-locale-compare + +echo "done" diff --git a/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.after.json new file mode 100644 index 00000000000..e65266a1b4c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.after.json @@ -0,0 +1,36 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz", + "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==", + "license": "MIT", + "dependencies": { + "is-number": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.before.json new file mode 100644 index 00000000000..250417bb0be --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package-lock.before.json @@ -0,0 +1,98 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + }, + "devDependencies": { + "is-even": "^1.0.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-even": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-even/-/is-even-1.0.0.tgz", + "integrity": "sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-odd": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-even/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-even/node_modules/is-odd": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-0.1.2.tgz", + "integrity": "sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz", + "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==", + "license": "MIT", + "dependencies": { + "is-number": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json new file mode 100644 index 00000000000..3f68122bbea --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json.before b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json.before new file mode 100644 index 00000000000..6324d0fece9 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/remove-orphans/package.json.before @@ -0,0 +1,10 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-odd": "^3.0.1" + }, + "devDependencies": { + "is-even": "^1.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/scoped/http/@isaacs%2fstring-locale-compare.json b/rewrite-javascript/src/test/resources/npmlock/scoped/http/@isaacs%2fstring-locale-compare.json new file mode 100644 index 00000000000..f09eb901b85 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/scoped/http/@isaacs%2fstring-locale-compare.json @@ -0,0 +1 @@ +{"_id":"@isaacs/string-locale-compare","_rev":"4-e463d762a9436ecc806971f320cfec92","name":"@isaacs/string-locale-compare","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@isaacs/string-locale-compare","version":"1.0.0","main":"index.js","description":"Compare strings with Intl.Collator if available, falling back to String.localeCompare otherwise","repository":{"type":"git","url":"git+https://github.com/isaacs/string-locale-compare.git"},"author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"https://izs.me"},"license":"ISC","scripts":{"test":"tap","snap":"tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"tap":{"check-coverage":true},"devDependencies":{"tap":"^15.0.9"},"gitHead":"3a53b04c69f5020e66b3d59868657527c50d7e45","bugs":{"url":"https://github.com/isaacs/string-locale-compare/issues"},"homepage":"https://github.com/isaacs/string-locale-compare#readme","_id":"@isaacs/string-locale-compare@1.0.0","_nodeVersion":"16.5.0","_npmVersion":"7.23.0","dist":{"integrity":"sha512-R3acQDJm066Tr5Gb+OhiEkKyy94F2p6dkcUI6J8KQuinqgg5HszX/H4vepKxREDbiVR9pGKOD9Jo+RTDux+zLA==","shasum":"2bbd680395d205a022b76aa01910f6d1c48cf948","tarball":"https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.0.0.tgz","fileCount":4,"unpackedSize":2414,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGQIb168FJrWHmlY+gGW7kR+4bHXzldRZ3FKNI7CTGb+AiBJ7Hl2nJ5gq2KksgcDvjupCGIDW8l/XAFXFmHB9QNcFA=="}]},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"directories":{},"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/string-locale-compare_1.0.0_1632261223207_0.21290938050693864"},"_hasShrinkwrap":false},"1.0.1":{"name":"@isaacs/string-locale-compare","version":"1.0.1","main":"index.js","description":"Compare strings with Intl.Collator if available, falling back to String.localeCompare otherwise","repository":{"type":"git","url":"git+https://github.com/isaacs/string-locale-compare.git"},"author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"https://izs.me"},"license":"ISC","scripts":{"test":"tap","snap":"tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"tap":{"check-coverage":true},"devDependencies":{"tap":"^15.0.9"},"gitHead":"81073be4066456f323acc87caed66325a24deba3","bugs":{"url":"https://github.com/isaacs/string-locale-compare/issues"},"homepage":"https://github.com/isaacs/string-locale-compare#readme","_id":"@isaacs/string-locale-compare@1.0.1","_nodeVersion":"16.5.0","_npmVersion":"7.23.0","dist":{"integrity":"sha512-AknEkBKSyAcIpl7SIUp12bs1rOmTDp9ojfDI9hvXl6qHqUCcaswkZOslbfdEbzI+8OPatiixY9AFKaUUpgGoBw==","shasum":"f2852dfe90b4b0caccb3132c36b59a59afc48e05","tarball":"https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.0.1.tgz","fileCount":4,"unpackedSize":2430,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBgfWPafah7qw3FtRWmsL8VFRGS6CKlKDggKhv2AjJ07AiEAjjuzlfyA1/ZPYZKiXjlzw/IaiktU+H9WIFDzVCiR+jc="}]},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"directories":{},"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/string-locale-compare_1.0.1_1632262184670_0.7870204010396045"},"_hasShrinkwrap":false},"1.1.0":{"name":"@isaacs/string-locale-compare","version":"1.1.0","main":"index.js","description":"Compare strings with Intl.Collator if available, falling back to String.localeCompare otherwise","repository":{"type":"git","url":"git+https://github.com/isaacs/string-locale-compare.git"},"author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"https://izs.me"},"license":"ISC","scripts":{"test":"tap","snap":"tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"tap":{"check-coverage":true},"devDependencies":{"tap":"^15.0.9"},"gitHead":"56348d643b863948f33464350d9aa5d540156200","bugs":{"url":"https://github.com/isaacs/string-locale-compare/issues"},"homepage":"https://github.com/isaacs/string-locale-compare#readme","_id":"@isaacs/string-locale-compare@1.1.0","_nodeVersion":"16.5.0","_npmVersion":"7.24.1","dist":{"integrity":"sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==","shasum":"291c227e93fd407a96ecd59879a35809120e432b","tarball":"https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz","fileCount":4,"unpackedSize":3162,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2MFwCRA9TVsSAnZWagAAiRQP/2AUYKPKHT+vNnG8MU/C\nSWLL9j1PEOuuK8qrUOisAPPFoTsax33FPq23BqFfjdMwvB+vRcpUHlJgSrB5\nmcPIOrGZZEo9hbyEFtxf1z+RbArJThIVpb1kiBv74K0mG13fD6TDKTD+XNVc\nrlfTg52u+J48jClpcc1SUTy514hwnLlwZeq1az5gVWBXwJ5dQh4rsODxeC7k\nSQp/uAcBJNXibk0dy7RgdixjA8gnzYyVPw1qu7v+AQDUQRM3rhSFNm5ztwP9\nD692zZ/sf4qcv06J1r9gETI/txNx9h1FlndLL9PCj1I+fRV5vVahLx57sCKo\nEH+K72ZnsaIGwf5Ig5+6u3kxDXcj83JxtLJxq9GI0dXh4YJKRdlg7EpI1LIT\n/g9XWSER4XqO0ZfO6GJ4BE5R29iKFr5r3f8qJnWOdPg7lJQrX+UQ6HgVm/S1\n4QOY8Biv6GFbEkBPOGrqfJ181yynobItDhesPDN2wgUlmCuPgJoTjJIYrFR9\nHsP195b0ZR3w+zVHRWHuZ15l9Quv6sRPkbCkyJfszZJM3ouWgKk/gPDCQEg6\ngLESSYxgGfhjYgof0NFZ74980sRpWyXu81HIJ2LzgLoROazO4h0O4ZJWzhjq\nZfhQlglNDieK5F5I0V3TIlFP6fZl4+jRS0IKOI8HPN1rcvvFNyTpcfhs42RL\nwtV5\r\n=nXSR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCeEW+ZcDwgwMQjI4OjARJ4Fz+KXua4OvULu6PZpgfzLQIgO4cj0rwFjgND2N1WLZ1mW/5Ls4nwLkZtLq0QTsRDAfY="}]},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"directories":{},"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/string-locale-compare_1.1.0_1632852853490_0.11487956384689357"},"_hasShrinkwrap":false}},"time":{"created":"2021-09-21T21:53:43.168Z","1.0.0":"2021-09-21T21:53:43.341Z","modified":"2022-04-05T21:11:22.800Z","1.0.1":"2021-09-21T22:09:44.845Z","1.1.0":"2021-09-28T18:14:13.693Z"},"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"description":"Compare strings with Intl.Collator if available, falling back to String.localeCompare otherwise","homepage":"https://github.com/isaacs/string-locale-compare#readme","repository":{"type":"git","url":"git+https://github.com/isaacs/string-locale-compare.git"},"author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"https://izs.me"},"bugs":{"url":"https://github.com/isaacs/string-locale-compare/issues"},"license":"ISC","readme":"# @isaacs/string-locale-compare\n\nCompare strings with Intl.Collator if available, falling back to\nString.localeCompare otherwise.\n\nThis also forces the use of a specific locale, to avoid using the system\nlocale, which is non-deterministic.\n\n## USAGE\n\n```js\nconst stringLocaleCompare = require('@isaacs/string-locale-compare')\n\nmyArrayOfStrings.sort(stringLocaleCompare('en'))\n\n// can also pass extra options\nmyArrayOfNumericStrings.sort(stringLocaleCompare('en', { numeric: true }))\n```\n\n## API\n\n`stringLocaleCompare(locale, [options])`\n\nLocale is required, must be a valid locale string.\n\nOptions is optional. The following options are supported:\n\n* `sensitivity`\n* `numeric`\n* `ignorePunctuation`\n* `caseFirst`\n","readmeFilename":"README.md"} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.after.json new file mode 100644 index 00000000000..59fefe587f4 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.after.json @@ -0,0 +1,21 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "license": "ISC" + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.before.json new file mode 100644 index 00000000000..d3930e8ee8e --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/scoped/package-lock.before.json @@ -0,0 +1,21 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "1.0.1" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.0.1.tgz", + "integrity": "sha512-AknEkBKSyAcIpl7SIUp12bs1rOmTDp9ojfDI9hvXl6qHqUCcaswkZOslbfdEbzI+8OPatiixY9AFKaUUpgGoBw==", + "license": "ISC" + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/scoped/package.json b/rewrite-javascript/src/test/resources/npmlock/scoped/package.json new file mode 100644 index 00000000000..c730bcf8f8a --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/scoped/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/scoped/package.json.before b/rewrite-javascript/src/test/resources/npmlock/scoped/package.json.before new file mode 100644 index 00000000000..60053166b7e --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/scoped/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "@isaacs/string-locale-compare": "1.0.1" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/http/is-number.json b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/http/is-number.json new file mode 100644 index 00000000000..32716549277 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/http/is-number.json @@ -0,0 +1 @@ +{"_id":"is-number","_rev":"43-3fe877efbeead423ee53a12d5ca44395","name":"is-number","description":"Returns true if a number or string value is a finite number. Useful for regex matches, parsing, user input, etc.","dist-tags":{"latest":"7.0.0"},"versions":{"0.1.0":{"name":"is-number","description":"Is the value a number?","version":"0.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"licenses":[{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"}],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"devDependencies":{"verb-tag-jscomments":">= 0.2.0","verb":">= 0.2.6","mocha":"*"},"keywords":["docs","documentation","generate","generator","markdown","templates","verb"],"_id":"is-number@0.1.0","_shasum":"4407a37aec259352affb5548886744ba4903f8bd","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"4407a37aec259352affb5548886744ba4903f8bd","tarball":"https://registry.npmjs.org/is-number/-/is-number-0.1.0.tgz","integrity":"sha512-WWl3iAruYOePW5iMf0IMcPiTsOTOu/FFsPyfx/ywixw7VmN6dI3/8/rgo4pdN6kVVjC5ByZ0Zk8xHLGEUSCdYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCGbjmJymNMyy+kX9QMWNiNDpyXcRARCBG/qWG5AH3BHwIgYPJPxD0DLlmMlQ82J2/kw9xjNGwnqmZwv1iu2dhCtQo="}]},"directories":{}},"0.1.1":{"name":"is-number","description":"Is the value a number? Has extensive tests.","version":"0.1.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"licenses":[{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"}],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"devDependencies":{"verb-tag-jscomments":">= 0.2.0","verb":">= 0.2.6","mocha":"*"},"keywords":["coerce","coercion","integer","is","istype","javascript","math","number","test","type","typeof","util","utility","value"],"_id":"is-number@0.1.1","_shasum":"69a7af116963d47206ec9bd9b48a14216f1e3806","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"69a7af116963d47206ec9bd9b48a14216f1e3806","tarball":"https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz","integrity":"sha512-la5kPULwIgkSSaZj9w7/A1uHqOBAgOhDUKQ5CkfL8LZ4Si6r4+2D0hI6b4o60MW4Uj2yNJARWIZUDPxlvOYQcw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGGOUnPaovBe5O7zmgOovRl4e6Dzx6aMobYRtKHOiWV+AiEA4Qufb/miuS6rDGp7Zd20/e0JoxviUgTnqu21xGF2DhY="}]},"directories":{}},"1.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"},"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"files":["index.js"],"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"3183207ab31bb09c65ad8999c39090a3c0530526","_id":"is-number@1.0.0","_shasum":"de821e3936a8996badeb879ca6f93605e769d498","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"de821e3936a8996badeb879ca6f93605e769d498","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.0.0.tgz","integrity":"sha512-chlxkgJp4PZIiff6kUe/MWLp5+soELWNYA2IsOTus1YwKj8d9JZS6QsU7Ryqwhb1f4i0nQ5SsoUj6d5kGgq0KQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2AOAMGpyuvqtfmVFBdULwtBCwI1cATJ1E2SXCu7KrqAIgN3FVeMU5CjRuw21s50tzEalrZmgvbJxkjizEvjLl+Xk="}]},"directories":{}},"1.1.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE-MIT"},"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha -R spec"},"files":["index.js"],"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"3183207ab31bb09c65ad8999c39090a3c0530526","_id":"is-number@1.1.0","_shasum":"620db9e22fded44d43d8e3e47044319083d31855","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"620db9e22fded44d43d8e3e47044319083d31855","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.0.tgz","integrity":"sha512-zRllTDrNKDRvVEhjEqDVkT9eKzC7HJ+9SFbfBdZnbjBVt9t0SwbEn0F/NSwdk5GkkEdKZA6ZQ0Hfd4akty5Pfg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnVnl9/SgNEemmb1M0T1tlfm4YRTqvWw3ja961FsqrVAIhANd7v0o1uT3CVfC9pzaFfvmwZcKBnxD+UHWlKvlIU4SJ"}]},"directories":{}},"1.1.1":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"5184d76c622b97d45486340a85147c6d59d14e25","_id":"is-number@1.1.1","_shasum":"e393e7ec07c17770dbb67941e7f89c675feb110f","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"e393e7ec07c17770dbb67941e7f89c675feb110f","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.1.tgz","integrity":"sha512-3/f2eabVTjIGjSVaQIIv33g1d2tYdSUnCNJuPpHcjwRzx8A2IPtCB2ayK2R3aS7SCF/LHlTjdaRjNmfG+RpFlA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1MN/tZFRjbwiG0H63P4dD6Qsem1lVPlOlJuJfdJP8iAiAoX6Lk3FLlI0dqigZPFyFZi1CXFk0W8dN9yJw7P2IW+Q=="}]},"directories":{}},"1.1.2":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"1.1.2","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"a902495bca1f471beaa8deb6193ba628bf80c0e4","_id":"is-number@1.1.2","_shasum":"9d82409f3a8a8beecf249b1bc7dada49829966e4","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"9d82409f3a8a8beecf249b1bc7dada49829966e4","tarball":"https://registry.npmjs.org/is-number/-/is-number-1.1.2.tgz","integrity":"sha512-dRKHHq76sZAXFf823ziHIOx5fXbuV1IrR892LugLDmyEBVMZzGoske4sY6lf+l3YPH/VyWNiKzNDXAPiQhx9Yg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpH37H0WboBtQM2deQbMGTh2WMRYWVosLWdpoz+wqyoQIhAIutpIYs8sNTY2MaxDpnJmvhoUfxrNVDIUs4+J5JffHf"}]},"directories":{}},"2.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"gitHead":"d5ac0584ee9ae7bd9288220a39780f155b9ad4c8","_id":"is-number@2.0.0","_shasum":"451c78bfe6c427f37bc2a406226e0cde449f3b5a","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"451c78bfe6c427f37bc2a406226e0cde449f3b5a","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.0.tgz","integrity":"sha512-LRme8p0WzIN9lrlP9/wJKs6242c9KYvDj6JlW9N9Up28wFxzyLNyNtnWu1j9nIuoWliquNRQx6+/OZ5mI2yVpQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEJz5PkAW3hcxfgUxotR5OLxeQFXF+vEsj3qRlIMuZj9AiAH3YXd7HMtFrJZqPGBE7DOjTqFWYWiPbm696CW+v1zDA=="}]},"directories":{}},"2.0.1":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.1","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"dependencies":{"kind-of":"^1.1.0"},"gitHead":"bb9b2e19a9aa2ed4b1e7a5d27e43417c8c9570c0","_id":"is-number@2.0.1","_shasum":"a3754e651f0df489f290ee0a1102c87cc5a0db02","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"a3754e651f0df489f290ee0a1102c87cc5a0db02","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.1.tgz","integrity":"sha512-lDXqMCs22DpNe5F5HqfrhwdCWXjlMccky+nhZ1+iFjnGvL7F7R7Q6Fd1FswLUrqueFab/6/k1Wd9LkIXJcBSWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBlSPRMBjwALDvd9fjWuuBR4PSdICIZh8q3IucTdXt6xAiA/4FirIMH2gtXtxkCZ/FLtO2+W5CJQVYHnvPGUY6nIaA=="}]},"directories":{}},"2.0.2":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.0.2","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":{"type":"MIT","url":"https://github.com/jonschlinkert/is-number/blob/master/LICENSE"},"files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"^2.1.0"},"keywords":["check","coerce","coercion","integer","is number","is","is-number","istype","kind of","math","number","test","type","typeof","value"],"dependencies":{"kind-of":"^1.1.0"},"gitHead":"63d5b26c793194bf7f341a7203e0e5568c753539","_id":"is-number@2.0.2","_shasum":"c7542a0f420610655834cd3825bc2f0eb72afe21","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"}],"dist":{"shasum":"c7542a0f420610655834cd3825bc2f0eb72afe21","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.0.2.tgz","integrity":"sha512-MzbGCUNsyTujsn2O9E2wL8n65cXdeWV1Jgd8khIA8VuN1q9ExsYQD6CwUwX6i8VGNLQy1skQugZ5RkvM1vbeqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9XsZ2zEA+6vg8VayjaUNxJIUDkYbvrvxC4uW8u0L3iAiEAgmolYRoJJEsPK3k30eWySMUIHqn3GHaYsWysUhMsqjs="}]},"directories":{}},"2.1.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"2.1.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"dependencies":{"kind-of":"^3.0.2"},"devDependencies":{"benchmarked":"^0.1.3","chalk":"^0.5.1","mocha":"*"},"keywords":["check","coerce","coercion","integer","is","is number","is-number","istype","kind of","math","number","test","type","typeof","value"],"verb":{"related":{"list":["kind-of","is-primitive","even","odd","is-even","is-odd"]}},"gitHead":"d06c6e2cc048d3cad016cb8dfb055bb14d86fffa","_id":"is-number@2.1.0","_shasum":"01fcbbb393463a548f2f466cce16dece49db908f","_from":".","_npmVersion":"3.3.6","_nodeVersion":"5.0.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"dist":{"shasum":"01fcbbb393463a548f2f466cce16dece49db908f","tarball":"https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz","integrity":"sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBsAMHxq3xfm/burDf3PmG8CCLKR4UncouEdSDdRwglAAiEAxMTfaixUr2K2XsrRDCg7R6dRYawh8RqjO/VkIJSFNA8="}]},"directories":{}},"3.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"3.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Charlike Mike Reagent","url":"http://www.tunnckocore.tk"},{"name":"Jon Schlinkert","email":"jon.schlinkert@sellside.com","url":"http://twitter.com/jonschlinkert"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"dependencies":{"kind-of":"^3.0.2"},"devDependencies":{"benchmarked":"^0.2.5","chalk":"^1.1.3","gulp-format-md":"^0.1.10","mocha":"^3.0.2"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"related":{"list":["even","is-even","is-odd","is-primitive","kind-of","odd"]},"toc":false,"layout":"default","tasks":["readme"],"plugins":["gulp-format-md"],"lint":{"reflinks":true},"reflinks":["verb","verb-generate-readme"]},"gitHead":"af885e2e890b9ef0875edd2b117305119ee5bdc5","_id":"is-number@3.0.0","_shasum":"24fd6201a4782cf50561c810276afc7d12d71195","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.3.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"maintainers":[{"name":"jonschlinkert","email":"github@sellside.com"},{"name":"doowb","email":"brian.woodward@gmail.com"}],"dist":{"shasum":"24fd6201a4782cf50561c810276afc7d12d71195","tarball":"https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz","integrity":"sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEpkuzJnkIAtuDMAI3VLqzFNwNANap4m9nyeUneW72kRAiEAtsctBWg1OtEaj2FSH+9ViALZU1O0hQFCVzwGMWHfVnk="}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/is-number-3.0.0.tgz_1473555089490_0.21388969756662846"},"directories":{}},"4.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"4.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"tunnckoCore","url":"https://i.am.charlike.online"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"related":{"list":["even","is-even","is-odd","is-primitive","kind-of","odd"]},"toc":false,"layout":"default","tasks":["readme"],"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"0c6b15a88bc10cd47f67a09506399dfc9ddc075d","_id":"is-number@4.0.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==","shasum":"0026e37f5454d73e356dfe6564699867c6a7f0ff","tarball":"https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA4Ju8vfTa5OmCg3qagXNvXHR0wp4GYpv4Jrzzx1Tr6yAiANs8hwximKkGyecUuMhc9/ipdFOP6u5xqFY1kkP37rHQ=="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number-4.0.0.tgz_1508219035603_0.08690439746715128"},"directories":{}},"5.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"5.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"toc":false,"layout":"default","tasks":["readme"],"related":{"list":["isobject","is-plain-object","is-primitive","kind-of"]},"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"7ed43573445149edf10f56967e8d943520ebb1db","_id":"is-number@5.0.0","_npmVersion":"5.6.0","_nodeVersion":"9.1.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-LmVHHP5dTJwrwZg2Jjqp7K5jpvcnYvYD1LMpvGadMsMv5+WXoDSLBQ0+zmuBJmuZGh2J2K845ygj/YukxUnr4A==","shasum":"c393bc471e65de1a10a6abcb20efeb12d2b88166","tarball":"https://registry.npmjs.org/is-number/-/is-number-5.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFRVCaHiES/v9QeFGm0LXGwQmnzQ7rRyYgSkAV0/RfEIAiEAovG90UvuzqTelvVuQdatpyiQ0H43CXLZupcrA2vb2Bs="}]},"maintainers":[{"email":"me@rouvenwessling.de","name":"realityking"},{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number-5.0.0.tgz_1517195201147_0.7769706172402948"},"directories":{}},"6.0.0":{"name":"is-number","description":"Returns true if the value is a number. comprehensive tests.","version":"6.0.0","homepage":"https://github.com/jonschlinkert/is-number","author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"license":"MIT","files":["index.js"],"main":"index.js","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha"},"devDependencies":{"benchmarked":"^2.0.0","chalk":"^2.1.0","gulp-format-md":"^1.0.0","mocha":"^3.0.1"},"keywords":["check","coerce","coercion","integer","is","is-nan","is-num","is-number","istype","kind","math","nan","num","number","numeric","test","type","typeof","value"],"verb":{"toc":false,"layout":"default","tasks":["readme"],"related":{"list":["isobject","is-plain-object","is-primitive","kind-of"]},"plugins":["gulp-format-md"],"lint":{"reflinks":true}},"gitHead":"b0953635829711e7dceec0eaa92bc56521a546eb","_id":"is-number@6.0.0","_npmVersion":"5.8.0","_nodeVersion":"9.9.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==","shasum":"e6d15ad31fc262887cccf217ae5f9316f81b1995","tarball":"https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz","fileCount":4,"unpackedSize":8960,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHw0y05qyjN2G0Uw0DINiC25SvWlVSgd2UD/ddJM8scPAiEArxOqwwCq3PKUhw7VEm21DI141kJs/ktPkaANlO5cGOs="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number_6.0.0_1522515759840_0.005598684369539919"},"_hasShrinkwrap":false},"7.0.0":{"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":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"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}},"gitHead":"98e8ff1da1a89f93d1397a24d7413ed15421c139","_id":"is-number@7.0.0","_npmVersion":"6.1.0","_nodeVersion":"10.0.0","_npmUser":{"name":"jonschlinkert","email":"github@sellside.com"},"dist":{"integrity":"sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==","shasum":"7535345b896734d5f80c4d06c50955527a14f12b","tarball":"https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz","fileCount":4,"unpackedSize":9615,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPOMKCRA9TVsSAnZWagAABmIP/iUfV7gQnAsn2vRNKWIu\nlxkfXFutnV1Bo5P8mlv37Zg+PN5/Ri/RATtKGEosAvHL/HK2HkFH+rLYkupg\nCYaAVXNOJiFN9vK61YYp0TB0PBtGDQ2UwcElxDQ8OP6Djni4fl2fLjVZ+JeN\nPF1bKPE6oMevNg3GtNMrb1QKZNGjplOKFmlmm9fe653LHwIH1zPYy6QQ+cgG\nQ8Czmhdf+NuX8WXqR1h5mHTKCCVAqzcpJ21uX9292aoWlzlijzg9cc8KEPEY\ncbUjJf4NMLs89/8G6tcpDP5qoVjQnWIgfM0mDXt4P7ESdqjusdyNa+3eS/Yi\nsQuevXmth+41kvQaVy7rLbeAssWNbc7IJ+X1qpgnUqTz4rtiAaRnZ6rzAE2s\nrr723lN2H7ALlnDVm5qzXLTTjHwbdYMYuaYHTOMovytYWeRnwhfNCpKeQcEe\nUYR3sm2tEdxsMI5ciu5ULGj/PEKnSOsQcq2y4QjNFz4F5ReXiv+CtphQubAr\nVkKwrjIovN97YXmyrkfJB1zCInCMUz11YgRY0wNaCJPJ4E0V4KdfWgCEyt+F\nqKcdylewrOAma06WozqUXzRH3uNNbMTfsE1nGqbcofJPNBre/VriCwF7zS/H\nLhGfCe6LJuY2Q+2Eel1vtwnY+vAoaWrr7QisjcvywYHvqWlRob2IxC1Ygp3A\nvUY+\r\n=M7jx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGex85Xx5rKhEgNSkg7z5bBu7vbcFbJnWJZbV3f9Td8GAiEA5wzgLXU41sE6ezCKGrmzsyMtm6M+2OhefJJhkzPEAoc="}]},"maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/is-number_7.0.0_1530716938183_0.28831183290614004"},"_hasShrinkwrap":false}},"readme":"# 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)\n\n> Returns true if the value is a finite number.\n\nPlease consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.\n\n## Install\n\nInstall with [npm](https://www.npmjs.com/):\n\n```sh\n$ npm install --save is-number\n```\n\n## Why is this needed?\n\nIn 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:\n\n```js\nconsole.log(+[]); //=> 0\nconsole.log(+''); //=> 0\nconsole.log(+' '); //=> 0\nconsole.log(typeof NaN); //=> 'number'\n```\n\nThis library offers a performant way to smooth out edge cases like these.\n\n## Usage\n\n```js\nconst isNumber = require('is-number');\n```\n\nSee the [tests](./test.js) for more examples.\n\n### true\n\n```js\nisNumber(5e3); // true\nisNumber(0xff); // true\nisNumber(-1.1); // true\nisNumber(0); // true\nisNumber(1); // true\nisNumber(1.1); // true\nisNumber(10); // true\nisNumber(10.10); // true\nisNumber(100); // true\nisNumber('-1.1'); // true\nisNumber('0'); // true\nisNumber('012'); // true\nisNumber('0xff'); // true\nisNumber('1'); // true\nisNumber('1.1'); // true\nisNumber('10'); // true\nisNumber('10.10'); // true\nisNumber('100'); // true\nisNumber('5e3'); // true\nisNumber(parseInt('012')); // true\nisNumber(parseFloat('012')); // true\n```\n\n### False\n\nEverything else is false, as you would expect:\n\n```js\nisNumber(Infinity); // false\nisNumber(NaN); // false\nisNumber(null); // false\nisNumber(undefined); // false\nisNumber(''); // false\nisNumber(' '); // false\nisNumber('foo'); // false\nisNumber([1]); // false\nisNumber([]); // false\nisNumber(function () {}); // false\nisNumber({}); // false\n```\n\n## Release history\n\n### 7.0.0\n\n* Refactor. Now uses `.isFinite` if it exists.\n* 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.\n\n### 6.0.0\n\n* Optimizations, thanks to @benaadams.\n\n### 5.0.0\n\n**Breaking changes**\n\n* removed support for `instanceof Number` and `instanceof String`\n\n## Benchmarks\n\nAs with all benchmarks, take these with a grain of salt. See the [benchmarks](./benchmark/index.js) for more detail.\n\n```\n# all\nv7.0 x 413,222 ops/sec ±2.02% (86 runs sampled)\nv6.0 x 111,061 ops/sec ±1.29% (85 runs sampled)\nparseFloat x 317,596 ops/sec ±1.36% (86 runs sampled)\nfastest is 'v7.0'\n\n# string\nv7.0 x 3,054,496 ops/sec ±1.05% (89 runs sampled)\nv6.0 x 2,957,781 ops/sec ±0.98% (88 runs sampled)\nparseFloat x 3,071,060 ops/sec ±1.13% (88 runs sampled)\nfastest is 'parseFloat,v7.0'\n\n# number\nv7.0 x 3,146,895 ops/sec ±0.89% (89 runs sampled)\nv6.0 x 3,214,038 ops/sec ±1.07% (89 runs sampled)\nparseFloat x 3,077,588 ops/sec ±1.07% (87 runs sampled)\nfastest is 'v6.0'\n```\n\n## About\n\n

\nContributing\n\nPull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).\n\n
\n\n
\nRunning Tests\n\nRunning 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:\n\n```sh\n$ npm install && npm test\n```\n\n
\n\n
\nBuilding docs\n\n_(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.)_\n\nTo generate the readme, run the following command:\n\n```sh\n$ npm install -g verbose/verb#dev verb-generate-readme && verb\n```\n\n
\n\n### Related projects\n\nYou might also be interested in these projects:\n\n* [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.\")\n* [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. \")\n* [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.\")\n* [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.\")\n\n### Contributors\n\n| **Commits** | **Contributor** | \n| --- | --- |\n| 49 | [jonschlinkert](https://github.com/jonschlinkert) |\n| 5 | [charlike-old](https://github.com/charlike-old) |\n| 1 | [benaadams](https://github.com/benaadams) |\n| 1 | [realityking](https://github.com/realityking) |\n\n### Author\n\n**Jon Schlinkert**\n\n* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)\n* [GitHub Profile](https://github.com/jonschlinkert)\n* [Twitter Profile](https://twitter.com/jonschlinkert)\n\n### License\n\nCopyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).\nReleased under the [MIT License](LICENSE).\n\n***\n\n_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 15, 2018._","maintainers":[{"email":"brian.woodward@gmail.com","name":"doowb"},{"email":"github@sellside.com","name":"jonschlinkert"},{"email":"me@rouvenwessling.de","name":"realityking"}],"time":{"modified":"2023-05-26T16:12:33.057Z","created":"2014-09-22T01:58:51.592Z","0.1.0":"2014-09-22T01:58:51.592Z","0.1.1":"2014-09-22T03:37:27.931Z","1.0.0":"2015-01-24T10:16:54.470Z","1.1.0":"2015-01-24T10:33:21.598Z","1.1.1":"2015-03-05T18:37:07.633Z","1.1.2":"2015-03-05T18:57:33.841Z","2.0.0":"2015-05-02T08:11:57.926Z","2.0.1":"2015-05-03T04:27:13.630Z","2.0.2":"2015-05-03T05:59:55.976Z","2.1.0":"2015-11-22T13:56:56.624Z","3.0.0":"2016-09-11T00:51:30.912Z","4.0.0":"2017-10-17T05:43:56.559Z","5.0.0":"2018-01-29T03:06:41.225Z","6.0.0":"2018-03-31T17:02:39.953Z","7.0.0":"2018-07-04T15:08:58.238Z"},"homepage":"https://github.com/jonschlinkert/is-number","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"],"repository":{"type":"git","url":"git+https://github.com/jonschlinkert/is-number.git"},"author":{"name":"Jon Schlinkert","url":"https://github.com/jonschlinkert"},"bugs":{"url":"https://github.com/jonschlinkert/is-number/issues"},"readmeFilename":"README.md","license":"MIT","users":{"jonschlinkert":true,"antanst":true,"rocket0191":true,"papasavva":true,"456wyc":true,"maycon_ribeiro":true,"leix3041":true,"snowdream":true,"fizzvr":true,"jameskrill":true,"rioli":true,"gugadev":true,"fearnbuster":true,"flumpus-dev":true},"contributors":[{"name":"Jon Schlinkert","url":"http://twitter.com/jonschlinkert"},{"name":"Olsten Larck","url":"https://i.am.charlike.online"},{"name":"Rouven Weßling","url":"www.rouvenwessling.de"}]} \ No newline at end of file diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.after.json b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.after.json new file mode 100644 index 00000000000..72926231ba2 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.after.json @@ -0,0 +1,24 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } + }, + "node_modules/is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.before.json b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.before.json new file mode 100644 index 00000000000..5aee81bfda6 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package-lock.before.json @@ -0,0 +1,24 @@ +{ + "name": "fixture", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^4.0.0" + } + }, + "node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json new file mode 100644 index 00000000000..665055ff253 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^6.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json.before b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json.before new file mode 100644 index 00000000000..429b6cf047c --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-leaf/package.json.before @@ -0,0 +1,7 @@ +{ + "name": "fixture", + "version": "1.0.0", + "dependencies": { + "is-number": "^4.0.0" + } +} diff --git a/rewrite-javascript/src/test/resources/npmlock/upgrade-orphans/http/chalk.json b/rewrite-javascript/src/test/resources/npmlock/upgrade-orphans/http/chalk.json new file mode 100644 index 00000000000..b193d465f71 --- /dev/null +++ b/rewrite-javascript/src/test/resources/npmlock/upgrade-orphans/http/chalk.json @@ -0,0 +1 @@ +{"_id":"chalk","_rev":"1239-b742c42277ad0a904287e75461ea13ec","name":"chalk","dist-tags":{"next":"3.0.0-beta.2","latest":"6.0.0"},"versions":{"0.1.0":{"name":"chalk","version":"0.1.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.1.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"69afbee2ffab5e0db239450767a6125cbea50fa2","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.1.0.tgz","integrity":"sha512-E1+My+HBCBHA6fBUZlbPnrOMrGKnc3QAXGEvCk/lpEG/ZKowZFg01dXt6RCYJMvTWYgxHWTyZQ6qkCrVPKJ2YQ==","signatures":[{"sig":"MEQCICcizJ0CViMVIGAdOi/w9z8s5d3Zn23t9fMlbuGpzGENAiB4IAPyJ4DSwN/KaA6WIkJE7cqo3iZiTLD1ClLbpbCEiQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"chalk","_from":".","files":["chalk.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk.git","type":"git"},"_npmVersion":"1.2.32","description":"Terminal string styling done right","directories":{},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"}},"0.1.1":{"name":"chalk","version":"0.1.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.1.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"fe6d90ae2c270424720c87ed92d36490b7d36ea0","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.1.1.tgz","integrity":"sha512-NJbznmWlxmS5Co0rrLJYO0U3QW6IzWw2EuojeOFn4e8nD1CYR5Ie60CEEmHrF8DXtfd83pdF0xYWVCXbRysrDQ==","signatures":[{"sig":"MEYCIQDyRcBiBgR63thSUFHx+SV7hi4FtDRy5WNaeEfCEr6c6wIhAJbSSa3GwYNrT0RVe6AVJcvtXcjsOVg7yTdLVbxlzfK7","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"chalk","_from":".","files":["chalk.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk.git","type":"git"},"_npmVersion":"1.2.32","description":"Terminal string styling done right","directories":{},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"}},"0.2.0":{"name":"chalk","version":"0.2.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.2.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"47270e80edce0e219911af65479d17db525ff5db","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.2.0.tgz","integrity":"sha512-CHq4xplBE+jhsJKGmh8AegFpEsC84kQNPMeL2mjrD5ojPc1LqNV1q5opCBU7BcRxWbpX+S8s+q4LFaqjP1rZmg==","signatures":[{"sig":"MEUCIQDfcM6X1OG63W5oEByNa/SCZJWAU3mNjL4zY35I5yHbGwIgNPIUWRFZl6a3ByWBLR4cXyn2WHnYru0PY39fougSJzQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"chalk","_from":".","files":["chalk.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk.git","type":"git"},"_npmVersion":"1.2.32","description":"Terminal string styling done right","directories":{},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"}},"0.2.1":{"name":"chalk","version":"0.2.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.2.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"7613e1575145b21386483f7f485aa5ffa8cbd10c","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.2.1.tgz","integrity":"sha512-nmVapomwGksziCuynboy7I+dtW4ytIdqXPlrfY/ySx8l8EqFRGHyA04q6NMNpOri8XliGUGwXyfScVl48zFHbw==","signatures":[{"sig":"MEQCIBda89bi2LZLymi7dToSY9rMAFRCXyg6fqyF15yoQO0tAiAT1ZyRicgVCJku8vgl5CUqx27uRUEnRK1GZ2kowTHh4g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"chalk","_from":".","files":["chalk.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk.git","type":"git"},"_npmVersion":"1.3.8","description":"Terminal string styling done right","directories":{},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"}},"0.3.0":{"name":"chalk","version":"0.3.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.3.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"1c98437737f1199ebcc1d4c48fd41b9f9c8e8f23","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.3.0.tgz","integrity":"sha512-OcfgS16PHpCu2Q4TNMtk0aZNx8PyeNiiB+6AgGH91fhT9hJ3v6pIIJ3lxlaOEDHlTm8t3wDe6bDGamvtIokQTg==","signatures":[{"sig":"MEYCIQD/TMCMMPNIkr1dvG6kRR/CWZZJtqKGoMdimY4IY6MEsgIhAJ1HbZkkcygfBmN1N4nqpYpBdAbRlLQOQoHfhOmBxYT1","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"chalk","_from":".","files":["chalk.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk.git","type":"git"},"_npmVersion":"1.3.10","description":"Terminal string styling done right","directories":{},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"}},"0.4.0":{"name":"chalk","version":"0.4.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"author":{"url":"http://sindresorhus.com","name":"Sindre Sorhus","email":"sindresorhus@gmail.com"},"license":"MIT","_id":"chalk@0.4.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"5199a3ddcd0c1efe23bc08c1b027b06176e0c64f","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz","integrity":"sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==","signatures":[{"sig":"MEQCIBe296G5Ckfk2TKZTU3bGX1WzY2zO0oXe5yCT2EecEajAiABeRfWovOVYu9t02fFT3Pnrbreb2qwOUoA6c16yVmoUA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk","type":"git"},"_npmVersion":"1.3.17","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","directories":{},"dependencies":{"has-color":"~0.1.0","strip-ansi":"~0.1.0","ansi-styles":"~1.0.0"},"devDependencies":{"mocha":"~1.x"}},"0.5.0":{"name":"chalk","version":"0.5.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@0.5.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.5.0.tgz","integrity":"sha512-rTCcbF0wrwC+kKzA/3SpBc6PrcOx/+PRQVtS3PEDw5tGzqycpB48dRS8ByxFDd8Ij5E1RtafZ34R1X9VLI/vUQ==","signatures":[{"sig":"MEQCIEGqQOniqI9HsAKeDEvFr1KDB3AZGGcdwYu4q0ylIHtUAiA65kQmXrb1YvhBtaJjhFQBrt7C9MIZfOOBOrg8SOziBA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git://github.com/sindresorhus/chalk","type":"git"},"_npmVersion":"1.4.9","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","directories":{},"dependencies":{"has-ansi":"^0.1.0","strip-ansi":"^0.3.0","ansi-styles":"^1.1.0","supports-color":"^0.2.0","escape-string-regexp":"^1.0.0"},"devDependencies":{"mocha":"*","matcha":"^0.5.0"}},"0.5.1":{"name":"chalk","version":"0.5.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@0.5.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"663b3a648b68b55d04690d49167aa837858f2174","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz","integrity":"sha512-bIKA54hP8iZhyDT81TOsJiQvR1gW+ZYSXFaZUAvoD4wCHdbHY2actmpTE4x344ZlFqHbvoxKOaESULTZN2gstg==","signatures":[{"sig":"MEUCIHm4uVj8/eT3R7g1Q6tzTAMZ2pdqmG9OumNXatGp4ykfAiEAqiq/PLZqnD8UaVvvHh3ElJAhsquDcnDKTEjLo6bZyNY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"663b3a648b68b55d04690d49167aa837858f2174","engines":{"node":">=0.10.0"},"gitHead":"994758f01293f1fdcf63282e9917cb9f2cfbdaac","scripts":{"test":"mocha","bench":"matcha benchmark.js"},"_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"repository":{"url":"git://github.com/sindresorhus/chalk","type":"git"},"_npmVersion":"1.4.14","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","directories":{},"dependencies":{"has-ansi":"^0.1.0","strip-ansi":"^0.3.0","ansi-styles":"^1.1.0","supports-color":"^0.2.0","escape-string-regexp":"^1.0.0"},"devDependencies":{"mocha":"*","matcha":"^0.5.0"}},"1.0.0":{"name":"chalk","version":"1.0.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@1.0.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"dist":{"shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz","integrity":"sha512-1TE3hpADga5iWinlcCpyhC7fTl9uQumLD8i2jJoJeVg7UbveY5jj7F6uCq8w0hQpSeLhaPn5QFe8e56toMVP1A==","signatures":[{"sig":"MEQCIA2fHIK4HaMM5vT8+vgIZDSYl2yR1wBMDpQnyK2mEp73AiBv9R+hCSU6L2lKmjPk37XVGjJaJPMWSPFUT6HNBGXJJg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","engines":{"node":">=0.10.0"},"gitHead":"8864d3563313ed15574a38dd5c9d5966080c46ce","scripts":{"test":"mocha","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"https://github.com/sindresorhus/chalk","type":"git"},"_npmVersion":"2.5.1","description":"Terminal string styling done right. Much color.","directories":{},"_nodeVersion":"0.12.0","dependencies":{"has-ansi":"^1.0.3","strip-ansi":"^2.0.1","ansi-styles":"^2.0.1","supports-color":"^1.3.0","escape-string-regexp":"^1.0.2"},"devDependencies":{"mocha":"*","matcha":"^0.6.0"}},"1.1.0":{"name":"chalk","version":"1.1.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@1.1.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk","bugs":{"url":"https://github.com/chalk/chalk/issues"},"dist":{"shasum":"09b453cec497a75520e4a60ae48214a8700e0921","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz","integrity":"sha512-pn7bzDYUIrL0KRp/KK5B+sej6uYtzQ5hYOdLU+L3MVWHCgoYi4aUYdh2/R2rsdURIoOK/ptZi5FDtLdjvKYQ7g==","signatures":[{"sig":"MEYCIQDvFUAscqbO0W1o8ynaLsS3H/qRFyNIcBpeciwTE0L2eAIhAJLC4kNijQLiP53FxwjKtIk/yb2Mz5bSJkvQcbmO38Lh","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"09b453cec497a75520e4a60ae48214a8700e0921","engines":{"node":">=0.10.0"},"gitHead":"e9bb6e6000b1c5d4508afabfdc85dd70f582f515","scripts":{"test":"mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"repository":{"url":"https://github.com/chalk/chalk","type":"git"},"_npmVersion":"2.10.1","description":"Terminal string styling done right. Much color.","directories":{},"_nodeVersion":"0.12.4","dependencies":{"has-ansi":"^2.0.0","strip-ansi":"^3.0.0","ansi-styles":"^2.1.0","supports-color":"^2.0.0","escape-string-regexp":"^1.0.2"},"devDependencies":{"nyc":"^3.0.0","mocha":"*","matcha":"^0.6.0","semver":"^4.3.3","coveralls":"^2.11.2","resolve-from":"^1.0.0","require-uncached":"^1.0.2"}},"1.1.1":{"name":"chalk","version":"1.1.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@1.1.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"509afb67066e7499f7eb3535c77445772ae2d019","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz","integrity":"sha512-W10W+QfIxJlTm3VRtg8eafwUBkDfUPFvRvPv4jCD9vF4+HzlAyXJ7P3Y5yw/r+gJ1TzFEU6oFqMgp1dIVpYr0A==","signatures":[{"sig":"MEUCIQDJnOp0QV+THZBj97NAJIJ/7FOfH1ApR+V17cduIWef4QIgKx6kVG0zABWS4/A8EyL/AV5PuxB8aCmy9tNSXcFiXa8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"509afb67066e7499f7eb3535c77445772ae2d019","engines":{"node":">=0.10.0"},"gitHead":"8b554e254e89c85c1fd04dcc444beeb15824e1a5","scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"2.13.5","description":"Terminal string styling done right. Much color.","directories":{},"_nodeVersion":"0.12.7","dependencies":{"has-ansi":"^2.0.0","strip-ansi":"^3.0.0","ansi-styles":"^2.1.0","supports-color":"^2.0.0","escape-string-regexp":"^1.0.2"},"devDependencies":{"xo":"*","nyc":"^3.0.0","mocha":"*","matcha":"^0.6.0","semver":"^4.3.3","coveralls":"^2.11.2","resolve-from":"^1.0.0","require-uncached":"^1.0.2"}},"1.1.2":{"name":"chalk","version":"1.1.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@1.1.2","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.2.tgz","integrity":"sha512-QBKX51aavmpKcCkgrJXhjS5b3rCgH2Wn99BYqUV2H1FjTP7Mm4KTcskSxuKrfhQKt69mBn9jH4Kb2xnchvEaOw==","signatures":[{"sig":"MEYCIQDR73JAj03sZJRAoJDQVm+RirI4Iry8ZuCvjsoI7cTA4wIhAOjIHdQPS2bXbYZucSmdnq17cnoYJ4fHFrpbk9slQEst","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","engines":{"node":">=0.10.0"},"gitHead":"a838948dcbf2674dd28adfbb78e791900ae741e9","scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"deprecated":"chalk@1.1.2 introduces breaking changes. Please use 1.1.3 or above.","repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"2.14.2","description":"Terminal string styling done right. Much color.","directories":{},"_nodeVersion":"0.10.32","dependencies":{"ansi-styles":"^2.2.1","supports-color":"^3.1.2","escape-string-regexp":"^1.0.2"},"devDependencies":{"xo":"*","nyc":"^5.2.0","mocha":"*","matcha":"^0.6.0","semver":"^5.1.0","coveralls":"^2.11.2","resolve-from":"^2.0.0","require-uncached":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/chalk-1.1.2.tgz_1459207923607_0.6091341155115515","host":"packages-12-west.internal.npmjs.com"}},"1.1.3":{"name":"chalk","version":"1.1.3","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@1.1.3","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz","integrity":"sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==","signatures":[{"sig":"MEYCIQCYydQMZbUiHhEF1lG6Vvl8dFiZehECOS8naCRKiBaDWAIhAMB+3sTOs5gMFmQyiUE6HzXaIsahGhReBUr4OYaI+iCX","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","files":["index.js"],"_shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","engines":{"node":">=0.10.0"},"gitHead":"0d8d8c204eb87a4038219131ad4d8369c9f59d24","scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"2.14.2","description":"Terminal string styling done right. Much color.","directories":{},"_nodeVersion":"0.10.32","dependencies":{"has-ansi":"^2.0.0","strip-ansi":"^3.0.0","ansi-styles":"^2.2.1","supports-color":"^2.0.0","escape-string-regexp":"^1.0.2"},"devDependencies":{"xo":"*","nyc":"^3.0.0","mocha":"*","matcha":"^0.6.0","semver":"^4.3.3","coveralls":"^2.11.2","resolve-from":"^1.0.0","require-uncached":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/chalk-1.1.3.tgz_1459210604109_0.3892582862172276","host":"packages-12-west.internal.npmjs.com"}},"2.0.0":{"name":"chalk","version":"2.0.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.0.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"c25c5b823fedff921aa5d83da3ecb5392e84e533","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.0.0.tgz","integrity":"sha512-7jy/5E6bVCRhLlvznnsbVPjsARuVC9HDkBjUKVaOmUrhsp6P3ExUUcW09htM7/qieRH+D2lHVpNbuYh7GjVJ0g==","signatures":[{"sig":"MEQCIHTAVf6u8jvZCfxvAN3anX5/E4q4xlYfkCEkZENhrWYbAiBLQg/CjJ1n1peDolmlJB8V892hSsvTW1L1zOl0qA1IHA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js"],"engines":{"node":">=4"},"gitHead":"3fca6150e23439e783409f5c8f948f767c2ddc5a","scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.0.0","description":"Terminal string styling done right. Much color","directories":{},"_nodeVersion":"8.0.0","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","nyc":"^11.0.2","mocha":"*","matcha":"^0.7.0","coveralls":"^2.11.2","import-fresh":"^2.0.0","resolve-from":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.0.0.tgz_1498780161964_0.21432337583974004","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"chalk","version":"2.0.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.0.1","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"dbec49436d2ae15f536114e76d14656cdbc0f44d","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz","integrity":"sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==","signatures":[{"sig":"MEQCICfJZUefrwq1SvzsgOv2Q/7HhKkcNRqOTzI/P/PsGm7dAiAVHrhAfBt0v3Bjqycj4E95pSguOX6OdYQeIElUAHjbvA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js"],"engines":{"node":">=4"},"gitHead":"5827081719944a2f903b52a88baeec1ec8581f82","scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"deprecated":"Please upgrade to Chalk 2.1.0 - template literals in this version (2.0.1) are quite buggy.","repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.0.0","description":"Terminal string styling done right. Much color","directories":{},"_nodeVersion":"8.0.0","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","nyc":"^11.0.2","mocha":"*","matcha":"^0.7.0","coveralls":"^2.11.2","import-fresh":"^2.0.0","resolve-from":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.0.1.tgz_1498793206623_0.8611406192649156","host":"s3://npm-registry-packages"}},"2.1.0":{"name":"chalk","version":"2.1.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.1.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz","integrity":"sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==","signatures":[{"sig":"MEQCIAR2pBNunhcCtIpoVtR8CzUr4fkHHazxHsUmYiEOl3SyAiAj1UgZ9m1qQjHPwS0lWc7+x71FyiJ9BnT8LKzU8hZpaA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js"],"engines":{"node":">=4"},"gitHead":"38f641a222d7ee0e607e4e5209d3931d2af1e409","scripts":{"test":"xo && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.3.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.2.1","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.7.0","matcha":"^0.7.0","coveralls":"^2.11.2","import-fresh":"^2.0.0","resolve-from":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.1.0.tgz_1502078203099_0.6595528507605195","host":"s3://npm-registry-packages"}},"2.2.0":{"name":"chalk","version":"2.2.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.2.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"477b3bf2f9b8fd5ca9e429747e37f724ee7af240","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz","integrity":"sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==","signatures":[{"sig":"MEYCIQCJ26ChsXMgEr8DGfcdGhwoECmCJIQc8C/WtfNNghWXpwIhALxt4sAYIddaWoA+laUzI/bv5TtudGNeOLEa+lB3iTKA","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js","types/index.d.ts"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"d86db88e778fa856f4d6f5f68c588750ca06b822","scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.4.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.7.0","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.8.0","matcha":"^0.7.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.2.0.tgz_1508296541817_0.8590951061341912","host":"s3://npm-registry-packages"}},"2.2.2":{"name":"chalk","version":"2.2.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.2.2","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"4403f5cf18f35c05f51fbdf152bf588f956cf7cb","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz","integrity":"sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==","signatures":[{"sig":"MEYCIQDfa8X3hU20LXJII/tFJYOtrI+If9MXC6lVP2kVo2TeagIhAJTH6/ofItVCqYxnT7cTqmAxRF8XTpQFWlvUr/dLjfi+","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js","types/index.d.ts"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"e1177ec3628f6d0d37489c1e1accd2c389a376a8","scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.3.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.2.1","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.8.0","matcha":"^0.7.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.2.2.tgz_1508815246099_0.3707860491704196","host":"s3://npm-registry-packages"}},"2.3.0":{"name":"chalk","version":"2.3.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.3.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"b5ea48efc9c1793dccc9b4767c93914d3f2d52ba","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz","integrity":"sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==","signatures":[{"sig":"MEYCIQCmt7XnAO8uN79Qxpb8HhB5EzqXR5F9Xz+dizDO68VggQIhAPCzW1TPRUP1vXrzImjrGiRQFFXTq6uWu8l+3dlLRyJm","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"files":["index.js","templates.js","types/index.d.ts"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"14e0aa97727019b22f0a003fdc631aeec5e2e24c","scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.4.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.7.0","dependencies":{"ansi-styles":"^3.1.0","supports-color":"^4.0.0","escape-string-regexp":"^1.0.5"},"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.8.0","matcha":"^0.7.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk-2.3.0.tgz_1508818375657_0.9021007190458477","host":"s3://npm-registry-packages"}},"2.3.1":{"name":"chalk","version":"2.3.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.3.1","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"523fe2678aec7b04e8041909292fe8b17059b796","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz","fileCount":6,"integrity":"sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==","signatures":[{"sig":"MEUCIQDq923pbuma8n5CHp1BmZnEpfSBznm9pjEsnO89V1Fd1QIgPAoDos2IHJA/kzqVf2mD25YwAbgXJ4YOKduTvo92f94=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":24721},"files":["index.js","templates.js","types/index.d.ts"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"ae8a03f2c5c49896adeb3dd4ec5350e4ab9449a2","scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.6.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.9.4","dependencies":{"ansi-styles":"^3.2.0","supports-color":"^5.2.0","escape-string-regexp":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.9.0","matcha":"^0.7.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_2.3.1_1518355108425_0.3816906865374552","host":"s3://npm-registry-packages"}},"2.3.2":{"name":"chalk","version":"2.3.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.3.2","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"]},"dist":{"shasum":"250dc96b07491bfd601e648d66ddf5f60c7a5c65","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz","fileCount":6,"integrity":"sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==","signatures":[{"sig":"MEQCIGrPWo1zy8RefMcSH+1wPT00s3HsqCjGvfnnE3kKN0BMAiA90/5NkYnkzLmda2udxxQfLxRPdxx1Gf9nafuAeaTxrA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":24713},"files":["index.js","templates.js","types/index.d.ts"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"84f27d4bd86f7f482a32652ae536cd996ad204bd","scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.6.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.9.4","dependencies":{"ansi-styles":"^3.2.1","supports-color":"^5.3.0","escape-string-regexp":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.9.0","matcha":"^0.7.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_2.3.2_1520012630405_0.9222977073145247","host":"s3://npm-registry-packages"}},"2.4.0":{"name":"chalk","version":"2.4.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.4.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"dist":{"shasum":"a060a297a6b57e15b61ca63ce84995daa0fe6e52","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz","fileCount":7,"integrity":"sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==","signatures":[{"sig":"MEQCIHWaTr0kn5hhbrdU9rauwwyPdBW6TxZnI4Lc23AJQgTCAiBJcOQo3Y7yHbfSuuL++TjazCour+dgSoT3qw/rRcCHgg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":27005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1Xf3CRA9TVsSAnZWagAA1DcP/2EhxWse6mGwicTqM2U5\nQl2Xol74cFmd6b4nCGZnGycgatfJtyhb1YoH/vL3uNqGFrQGBwAr4GoZxhGd\n7kL0xKWnfhGHFeUe//fSCklj4Aff700RteXornlDFxbK5jVELyYcXfG5xJ5i\ncAIuPb9YYXltdaSfvVcg49qIPcjRfZm5Wz8WxTaUAyD5Ag4lpWKVTgWZsU+c\nEKRQHu+UmpX2OsudafT6GL3ak7GE2+ysH1b0HcYVuf1Wdf39un+E0MXDs58C\nTLCZSASN99/KCEpjh8aa4YdXVU3x0rdf50KdKDBUMF3b6HnSfWqOS+OWZRFZ\nC0jvk58j4vmXCVb2puQI8HIuZXBlNeS59GaN3hB3rz7JMgrQC/LXycOU1x+5\nuKEKupRkkVsSRyAEUdHqx6dwkcm+TVGPnXjUMdYREL9VkyY9eB7lBYTEzH9I\nZN9H3JXrjo/dGVmFL6q+L7lCxLFsl1p+UCMxubUE9XV6C/QN4mQmiwIAwn04\nhJH1RFIFTHszVEUnAJMZ6SqRRJes5iSedAMyiUYi+1S86uQenyUqtIJbHsNO\n7+G3Jnfdw9e1+YMvk53PSJcdtt5ayOx7ezc0HLS5HD9g3bXhMbbxTupHOSAv\nVCiEoaKAmjJK7nbStTqrX3xjz85K+lNHZdKkIzPWX5TkEg8KMSGK3LxfXG8B\n+CuC\r\n=orOi\r\n-----END PGP SIGNATURE-----\r\n"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"af8b3657e96a0a6ca5190fb0d0a1345797148320","scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.6.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.10.0","dependencies":{"ansi-styles":"^3.2.1","supports-color":"^5.3.0","escape-string-regexp":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.9.0","matcha":"^0.7.0","flow-bin":"^0.68.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_2.4.0_1523939317754_0.3039215958746819","host":"s3://npm-registry-packages"}},"2.4.1":{"name":"chalk","version":"2.4.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.4.1","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"dist":{"shasum":"18c49ab16a037b6eb0152cc83e3471338215b66e","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz","fileCount":7,"integrity":"sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==","signatures":[{"sig":"MEUCIQCTy37ycwX7bqoO0WDu7AVubgfxDHR/7neyxoLzwx8dIwIgJxP4QEC0TbUnC9iBA3w36fy7kAAd1tHPSQZtkZ1yOrA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":26917,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4WCICRA9TVsSAnZWagAAhgwP/2M/ItinhR06BFhLMh91\nK/ru5t71NzSzoEvI2nh4W57Wk9cU1NOYi1cI17nUvICHCL4Vq9mjvU0hajTw\ncAYtM0Lwl+G4Hk4JtuiZITYj93QY3yLSJ8zkj95JznFbH0Zd9KkZrkoGukcG\nFY9at0cfNyhBmwi5sEDAFktcw7wThQ6Wy3iIttQ0N1M6Lf1XILg9Xyq6Id/W\nlz3TbkCt6AZCS1icmDPIiLdVQuD9SfpusIDsHm5/6FJPShwmQjUlM6Kdy7lx\n6M8uhcIknpxjfPTA6/aSBC4qgXnDhuPPi9xF657/81Mswz4Tb71KOf6UqLPi\n3zk1D5PF71ujWs3wmPll9TAVGnWuNzE+X/7GVIB4qCrib3SgvRzMhL0Wo95v\nzxTpNoD23hKYwofUyV3cTFh47YwkVoPtOStRAgdE87rx+v3VjbWSThQJc3V8\nHOsIeTjpQMwAr/d2DnasHKlps/q+gnGKqhBhcf11tAKn9C7PsAQ2l6+E4Erc\nfPKqDRC6TVG7ABdwOtyNonHhrJ2JLgYj8d4mHdtsMTtFsUTOQR/+Rx0V8HJS\n9gBLmPr3yc/yEedYW68wP5tPK2SfvFTzgMBw5v0+tgIxOjUunGxDUV4a1Bpp\npCBLN7iS77FLMiMonfcD2z/SsoB+Hb+7q5eT/gua3BIUNNZEdmgw9queXw+q\n7DFE\r\n=LSlF\r\n-----END PGP SIGNATURE-----\r\n"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"48ba5b0b9beadcabd9fc406ac4d9337d8fa6b36d","scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"5.6.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.11.1","dependencies":{"ansi-styles":"^3.2.1","supports-color":"^5.3.0","escape-string-regexp":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.9.0","matcha":"^0.7.0","flow-bin":"^0.68.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_2.4.1_1524719751701_0.7780175911150953","host":"s3://npm-registry-packages"}},"2.4.2":{"name":"chalk","version":"2.4.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@2.4.2","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"dist":{"shasum":"cd42541677a54333cf541a49108c1432b44c9424","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz","fileCount":7,"integrity":"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==","signatures":[{"sig":"MEUCIHxDV26xkYTdx1T+EBh6zvEaa602qK7hNWXvOTB1yr5UAiEAqSxYcAo+BSotxMY2GjH1e25JFKt2I+5D19gPFGbdghE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":26924,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMNEwCRA9TVsSAnZWagAAmpUQAJgCZygaBX9qniyJ7YVF\nOXq9BNycBSnHyRd5YnaoO6HB7ejh/M4CYYGPqdSQ0OXEk1teNm7iPhGhocbW\n0eEcg0gsnVTgkUKx5p3o841VKydwy72FDgO9WJjKm2QC/mwuYHB9kI7zkq3h\nkakWBNGlKxbKNYX+7x04BXx1H8Fn1CSE//133uQnUWzM6NSXrUwpiZTzwtXi\nOybESujfKq6x6DxlYsTTScThCUodQQTslxIrdeS8PZxQL1RqCwnJSMHi81nI\nPR5BNVbAEYOsZuw88mNEtc6sHellN3ZFVlZwFDu4ZDskgoMiXZVv7Qp6AXbN\nCdsz1ej/OBFdwUfjS17igoHY3sO3+7o3IuFFaCXM4lkSE2zu79M2A7H0GL0R\nUcyfM1OC/nRcLgeEytIDBSOAgeN4tstswdyagFQ36jymeKUyz+q50ziBchey\nZnxPMGYDMKTx+me3TGpf3SbjiSstyZm8GLWPhRLbkjIDajFcFnq2HZXUu/LR\npdFJIWqnJihr9dxxiPSxddqZspb/Jo2mD2+ILNxROZB5+nzmlLnV/PsnnbxM\nPRN0iYDQt6NtXce/GOFMasLwtwidfHx8B4ybmObU3btbmg7V7Og++xpVg+h1\nQfACtop8sZyVN3l65vhonCmioqpSLQPeEkMvwGN6/7wi01BRi5VI4DdEtIet\nHcNL\r\n=DerQ\r\n-----END PGP SIGNATURE-----\r\n"},"types":"types/index.d.ts","engines":{"node":">=4"},"gitHead":"9776a2ae5b5b1712ccf16416b55f47e575a81fb9","scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.5.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"10.13.0","dependencies":{"ansi-styles":"^3.2.1","supports-color":"^5.3.0","escape-string-regexp":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"xo":"*","ava":"*","nyc":"^11.0.2","execa":"^0.9.0","matcha":"^0.7.0","flow-bin":"^0.68.0","coveralls":"^3.0.0","typescript":"^2.5.3","import-fresh":"^2.0.0","resolve-from":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_2.4.2_1546703152138_0.5501232329596948","host":"s3://npm-registry-packages"}},"3.0.0-beta.1":{"name":"chalk","version":"3.0.0-beta.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@3.0.0-beta.1","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off"}},"dist":{"shasum":"328a0eccc051d6e50787fe112cbcf85b5d5e4d88","tarball":"https://registry.npmjs.org/chalk/-/chalk-3.0.0-beta.1.tgz","fileCount":7,"integrity":"sha512-f32K9VcIM5XJjpPHkqbrg+xN4vQVzEFNmPTgn1Ai3RBbtWT6ggFkUwZmB3/JTk0tdtjH1sl7fepaB9Vj8uVdUw==","signatures":[{"sig":"MEYCIQCe0bs1bAdkWtb7IlPzwUC1aavccTqLOMjSpRDMQWZFjwIhAONAABWrbNk+e31MGrLVolFCW6IA03RVeQP3vX11l1fh","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":31421,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdjZk5CRA9TVsSAnZWagAAzZ8P/iVhUy5WekDoOrbrump/\nw638F5EWWFLQNYd9SZOdZ0P7eDFJn9vfYwPitgL9jYJZ1T8fMveKbYLsJt6h\nLiNEk9to5mMgfINlj/+vOk83qEZ2yfM46jL+xTfyBLIpnKozlLkUjlm0cPXi\n6yOW26zdmyke1tp/gZafNSaJ/vJbxpjJyciccrvmfe2DWVyzwCcjP7nxpx8/\nUHdjSGvz8ul9PMwA1WieSHE/btPTqaPAPPiVtiOZWyDLhDI50+VXW7iQnvVM\nlMr1OiGjdQ2GKAxJHomvb+bjoWjWxKz3kUnk801quxABfgDHAk+Y3GIvMxLU\nVGQqiNvqYkMcqiF211xkXyFw71tiHyPqQ8pDkp4iYns4LIScr+ppoHPmJv9x\nALKBarLK5IQI1Fjw2sK5t9oOqNQ9HDZLDwGI/DTVOzUCzEMa67euv53IPRl3\nVbR8HHDDTareIWu1zpaHeOfxSoiRpx9TdV0thwWCzSuhANhUws4ebWh+NZG0\npY6Zt0lmSC+Cr3W/Oj41NgJ5MIk6uywZMjYa5wMS22qEzdhWCIDwckeuAsdz\nDi2h+9fcIHOkXxPWKn7UI91B5FCbEadThU9ASjZWSEv+BmtZ605wHRxk36Cm\noFe5WoIbblSjTpWU8ECtpyLm7o1j0aZj7nTgd0DV8ab30CzepNoECebX8AOq\nJ//W\r\n=/gvL\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=8"},"gitHead":"48905d08052aad4c8ba53bbd9fbcd8a9faf4f6e5","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.11.3","description":"Terminal string styling done right","directories":{},"_nodeVersion":"8.16.1","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"readmeFilename":"readme.md","devDependencies":{"xo":"^0.25.3","ava":"^2.4.0","nyc":"^14.1.1","tsd":"^0.7.4","execa":"^2.0.3","matcha":"^0.7.0","coveralls":"^3.0.5","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_3.0.0-beta.1_1569560889303_0.3449501496211118","host":"s3://npm-registry-packages"}},"3.0.0-beta.2":{"name":"chalk","version":"3.0.0-beta.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@3.0.0-beta.2","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off"}},"dist":{"shasum":"d6a422d12828314a6f2ecad6863c68b706598a22","tarball":"https://registry.npmjs.org/chalk/-/chalk-3.0.0-beta.2.tgz","fileCount":7,"integrity":"sha512-NKGY083nqioebgPmjRTGY/bRq34dgkXkmHmWgwDXbPs0YEkN7ZTcimhnv1KnHGW80QPta1QZiJDbQv7s+e+uaQ==","signatures":[{"sig":"MEYCIQCR8QG2c2hRIQDlCKH8KjjOFNGvWAEqtmoIHPcJ0BWY/AIhANBUmWME4/25NdWUmjZrye5lgor0aOJPV3z/HEVysw6z","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":31889,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdnFe/CRA9TVsSAnZWagAAN/YP/0i73lzDmsyO/x2VPyvz\nlL0W6F4HdeK3W/Mr7BNf3M06KVjax+BhLTq/KyAhyZlfCAI412HeZCdb34Aq\nXXucOoN5l7o6oJrs+KXN2GlxzHZT3HJjrU653bAuaw/FN0apVM/cLCLA30gq\nZZSM9cxJKy8LDZsszGT88iQtcUI/sp1yvkooKKV4A9XyjQaC05xTVBAbNan5\nYWQfgFKdr2Wo3A5KPND0hf9247GQzg8Lu8fE0EOtRhng+ZxUExp0aApaevl+\nZj+265abk5RMmOUa+VMln91NixSnE98PRguTZcVF+m4HuGyx3fR5jiJx5XU8\nlWvaA01CSHTVh2aVvDHa16/Cbcqzrl24xV7MSVRzUEAY5OudV/+JMvIFWo54\nIFnQqBYFbao9GoHQRqrFLqi5szR/yBYPayFGBcG3L3O6Tngz1N+OtnD+mGNC\nu7ZRt+zr8w0ooPIqKO97PBsgF7u495pvdKx2L5exw77kbltwTEiad2KmOTf2\nQDy1UN+KTUGzeArUa5tdqd3xl6r3V9WqEHsul065u2o4cqPAMXqvR1Xa8lv7\nxGbF1M/lKwGQihn37tHbXPkS/t1ghr+OS0kNaUgN8E1j/7//xx+j2bt3MAi2\nxmZbnCL0EufwXl85FJQ/Y0QFWFl/6LgJbvsmCD8ZqoP+Y8zljZDsKHjvtewU\nnRyz\r\n=5dvj\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=8"},"gitHead":"4de1841129cf3d0a1db7a5d6638402b7828e1731","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.11.3","description":"Terminal string styling done right","directories":{},"_nodeVersion":"10.16.3","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"readmeFilename":"readme.md","devDependencies":{"xo":"^0.25.3","ava":"^2.4.0","nyc":"^14.1.1","tsd":"^0.7.4","execa":"^2.0.3","matcha":"^0.7.0","coveralls":"^3.0.5","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_3.0.0-beta.2_1570527167016_0.8251191799502275","host":"s3://npm-registry-packages"}},"3.0.0":{"name":"chalk","version":"3.0.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@3.0.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off"}},"dist":{"shasum":"3f73c2bf526591f574cc492c51e2456349f844e4","tarball":"https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz","fileCount":7,"integrity":"sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==","signatures":[{"sig":"MEUCIHFevK5+lXJPZaAa9WD2j7ykLEswtElzlNvuddi6ulb+AiEAuQyuRFvzORZkufOCblOvMRtG0vc69A7rodPmDWZlp18=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":32729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxmO9CRA9TVsSAnZWagAAQlUP/0PNLoVFZvoOYYt8XPh9\n6mDNBG9olRXfrrR33bcNZdkpKfil6MU7uMkLOME+L9U6h1iqMVUK/CWKfqwS\nUPH/zKprPc2xOgDVKiEgAPm+OWCxcZrGBGUJPiP2TVlo5UshIA6DheD8TSgQ\nGBW2JrOo+IXuHkza1+rPMzfrBpvulp0gthN9JjJYQNZ66SuB1wyFPMLh1b9A\nq/Q5Kg5acnnNAE5xFogzw2gAaf5qee3v3Ozda96VFG8oeCvDXYre6oC0OUzV\ng/ODyHikvvtZx6TU5hosOSRTawXjq1lGgLL2xzWt7w8oRziTBb2NKf/irsMd\nuWel64/sBbQF9C1C1/z/MkYRS2OVQWOo/qZ/BdIvfCTniaq6sekNn6rIXJj8\nPRXmBsJXdxD6mhPKxa2YEUWHFigyI+DyNRi3EkUpCqp2ZmfkD0srhakUf97z\nB4kr+0MvNpBhWt8y7Yjz1jQC9EM73yQ1POjspYj+Fh6mr7kgkfo/AFGh4AHI\nSXlXgE0b8WUn6hl3/icMZHk2xwYyIVImklNkKfI4IhxodkjL11ji+Nn5yUkI\nf9RqxQajpLAwLyWeAT2RCSTLvxfjwKnU+bWyFWHqyGQb4aS4TLSz0wmR8raS\nroGj3AXz4oUTazsBy+kGNwzOZs3tOV/Uv30MFpnHpFpOQhW1Mvp/RiQkd4O3\nxEsU\r\n=jRi9\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=8"},"gitHead":"20002d8bd1dfd6f68bfa8bdacba520ff6027a450","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.13.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"10.17.0","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"devDependencies":{"xo":"^0.25.3","ava":"^2.4.0","nyc":"^14.1.1","tsd":"^0.7.4","execa":"^3.2.0","matcha":"^0.7.0","coveralls":"^3.0.7","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_3.0.0_1573282748902_0.03099002657701666","host":"s3://npm-registry-packages"}},"4.0.0":{"name":"chalk","version":"4.0.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@4.0.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"no-redeclare":"off","unicorn/better-regex":"off","unicorn/string-content":"off","unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off","@typescript-eslint/member-ordering":"off"}},"dist":{"shasum":"6e98081ed2d17faab615eb52ac66ec1fe6209e72","tarball":"https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz","fileCount":7,"integrity":"sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==","signatures":[{"sig":"MEUCIQD7qR9gpQpWRXV3jyQzkkap03iawVdpCjW7KHMqHUCSMAIgF1VFxJCJMi2OPph8OaYzcwNwHHTXEDg3BzcAqM0J3c0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":33203,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJehaBSCRA9TVsSAnZWagAAOr4QAJcb6PYIe6jxjYoonKMe\nsF+1AbJDL8JbXYEJME2KzFD1SXQEUIlUBM8C+hqfu0b2TxXs96rMzI+ueLx4\nvWIdw5d6By+eLQr2pfKgr4YrrPa0vniUd26/7pdbPTJbXpF/u0/BNI0TD30D\nSHBMuFbvVVUV0QfrjajTJXnA6LsD7LOcp9RlL8zyZRDYrstGJShO0yYUt6vp\n7+cTVX3oYkXFpfd2xBqRyeljFO5S4D9dhkGvq6vdVt9VUMXhmUzEJwtzpDpj\nBqfDfRBudePuthM+nNlNd9DIfCY+HopadNAKsRKv0fobzACNE2xedBUHWfvB\nAxVOBupA23Xok0z7dgXBKllLptQlI5mQ3e1cqQO9hUB22iRSUrSM4eEz6lrB\nzCbyzr+7WoxSPRWaoIu52/zPanuGAwc2Omk7+BHwEX0j7wiyHpxPWSkbZiw6\ngeiro1ZDzbWYCd2lOe2ZGRRQdIHCADozHz6IHorbHp9k4R5cHtmryiwmE59B\nZ4JYtRjn6uiWbr+RPVdSS9RySu95eApfTNO148IIek+E1lNLJ3VTobUmDWyY\nDW6HDIA1Iplbm54dSGgC5fwDOhZAnvrMOfOS6MMygblIuHP4Cm16woIUwWFi\nE4ErSEGMZZg2N0fkGP3oEgOjbnzXiSrYBPXZncfI+nnTtHf82kJ4D2Oc8nPp\nVbza\r\n=EnFl\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=10"},"funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"31fa94208034cb7581a81b06045ff2cf51057b40","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.13.4","description":"Terminal string styling done right","directories":{},"_nodeVersion":"10.19.0","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"devDependencies":{"xo":"^0.28.2","ava":"^2.4.0","nyc":"^15.0.0","tsd":"^0.7.4","execa":"^4.0.0","matcha":"^0.7.0","coveralls":"^3.0.7","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_4.0.0_1585815633587_0.14399738942582263","host":"s3://npm-registry-packages"}},"4.1.0":{"name":"chalk","version":"4.1.0","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@4.1.0","maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"no-redeclare":"off","unicorn/better-regex":"off","unicorn/string-content":"off","unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off","@typescript-eslint/member-ordering":"off"}},"dist":{"shasum":"4e14870a618d9e2edd97dd8345fd9d9dc315646a","tarball":"https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz","fileCount":7,"integrity":"sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==","signatures":[{"sig":"MEUCIQDngUfyzfUivBEHqCcMvyhegi4ut++J5IACRwl3gHTy2wIgbyjwcUbiRPFMf5J95/s1JR7DUuPwMqrOHpFuzTrnmZg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":33631,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3z2uCRA9TVsSAnZWagAA0WAQAI74Vzh0XPfSSmh2CcWS\n+aaiM3I/TWlkYavizTfItEhGfuzf+Fi0RAzdW9SXjxYq9kZe1W+9zG+QJQ3S\nR5icdbgu3lXwAfesJUcX5EplLoSKEJkpTMLtOcff0lu4ug0+dYm5XHbCfign\n8e7vVdU50GPMM8mg20Hyl0SIuawkUngnlIeCiY36NjdysJtMa8X2QeMHRNat\nSg/aK3+SepkJyxAQSXqiI9QemV4PMI42L7pCb19bu79eBUYwaoKml4qKneX2\nH18ViBB6wKhxfNwX1K7M2PHxqd5e2t44hqliAgzXzz/bNIaU3qomm2OJYGKS\nZujI7mx3DEKzsYd7glloIBQKWWet22mc0eQSjH7q25w6tjPZpk68Ggs4xxIm\nRgJaAjhFURC916d4o/EhQYXTv+0WnS+TRwcJOBDpsrfZ1IuqErC2ZT+QnMya\nzEMemmRWMUFhdQcQYUQT8jDHuSpqxj9d6DUBBGJrM29W1CH3j0xt6DN2EwOx\nUj3HGHKTc652yrvP4JKSj8XAPUn7mHW1kEOT9ypk+sBISI3u5EYMdPr4xRKp\ngx2Ci/q9lI+IQWT1Rf2EBzluwjA3/6fz0IoVAkelxKRiQsVSsdGVXuGB/QdU\nBChW4WzwPn9FbBiuLb+9SYY9lKjHmNbn0nUklvZVrpiUpWAEePZVp97ohqRy\nrq+U\r\n=5TmM\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=10"},"funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"4c3df8847256f9f2471f0af74100b21afc12949f","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"6.14.5","description":"Terminal string styling done right","directories":{},"_nodeVersion":"14.4.0","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"devDependencies":{"xo":"^0.28.2","ava":"^2.4.0","nyc":"^15.0.0","tsd":"^0.7.4","execa":"^4.0.0","matcha":"^0.7.0","coveralls":"^3.0.7","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_4.1.0_1591688622018_0.2681914768782716","host":"s3://npm-registry-packages"}},"4.1.1":{"name":"chalk","version":"4.1.1","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@4.1.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"i.am.qix@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"no-redeclare":"off","unicorn/better-regex":"off","unicorn/string-content":"off","unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off","@typescript-eslint/member-ordering":"off"}},"dist":{"shasum":"c80b3fab28bf6371e6863325eee67e618b77e6ad","tarball":"https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz","fileCount":7,"integrity":"sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==","signatures":[{"sig":"MEQCIFRLSrIoAV5Vuz5b8oIdXGeN7vlNJCSxq1vXEDPOGrdxAiAGLyD2ukbgFSt3og6x5DALaTSFTGCTd2ZCTZIqPX/CBw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":34823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgf+g6CRA9TVsSAnZWagAAYJ4P/3Tow5x9NagQZ4wlfmp+\nAx2ZtnEj/nASDGzd0E66OdyF69kS658zaMCBK96P/qXRYbCDJm77wq4W3Iui\nnaC6X1ZLcsbY9ME+EKHVCVXHiCjXC7EsPskkHrSUUYvwEiSK6wOH2ljfogNr\nLXQFbMT0x5cRpZZcherkrDWgJCFnD8L6+a9aDkfS/ZQZSBN0MHGZmi1AYl3B\nh/iKYq+ZhI1qUJaDhf005Oj0Vtegjozr3C+senyN4QWpUijoTF7MgJwiF/8w\nvb8e8Lzf0KlfdSvxtXeZ38m3J+y3+cphcBmkoagxsMtrtjzbFCUFIjHS6b1r\nldlAmH/xe5oemntzjX/7mXzhK6yMA515vAhKswcJ267oJ5tsnfa90bo2wh11\nBdAAr3RjWgNUb/OV1aIlFFvTCwc7O5yYKfkY7KXnL/NUGq0gpIJ1lEdTMgPL\nNaQXm41q0UEmVV9bi/BQKIUpPblVMYSJShcbjxhiZ9Yzc2vkVbzY73UXoEwE\nn+JIKCZPbC1RJQ/E8IjEtROoUFJ7MmhPm/dqMuw+/9JITGh7c4HYh1u0xqzI\nHp4l+Fc39tIje76zkT/QzvW9R3M83xOWxTTHARTJKtC6wqDytuYO8liIOEIi\nbcZd+j6YwHU8C071Dvncg2wELx7VmQefvxyWcjnuOCLyuHFOXJAsy79z3Cc4\n1lSw\r\n=t7Q/\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=10"},"funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"89e9e3a5b0601f4eda4c3a92acd887ec836d0175","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"7.5.4","description":"Terminal string styling done right","directories":{},"_nodeVersion":"12.22.1","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"devDependencies":{"xo":"^0.28.2","ava":"^2.4.0","nyc":"^15.0.0","tsd":"^0.7.4","execa":"^4.0.0","matcha":"^0.7.0","coveralls":"^3.0.7","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_4.1.1_1618995257952_0.8528874341897312","host":"s3://npm-registry-packages"}},"4.1.2":{"name":"chalk","version":"4.1.2","keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@4.1.2","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"xo":{"rules":{"no-redeclare":"off","unicorn/better-regex":"off","unicorn/string-content":"off","unicorn/prefer-includes":"off","unicorn/prefer-string-slice":"off","@typescript-eslint/member-ordering":"off"}},"dist":{"shasum":"aac4e2b7734a740867aeb16bf02aad556a1e7a01","tarball":"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz","fileCount":7,"integrity":"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==","signatures":[{"sig":"MEYCIQD4dG0uJ9LWDhLIbBJazgFGOYD+6u8gUvOP/yfEluvstAIhAK7GZOqN8KY0Alry2lZ2MBIvWjuEGISyqHydp9oFrw22","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":35047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhA+psCRA9TVsSAnZWagAAaj8QAIsfB8+2kMsY5OUrDEqr\nqbznQ57bFD3ArrUSvhg+03aVEQV8fwgQHZtDC4KUSFuZGw/1l+3A+GFxvK68\nMM9SOD7jMNy1BUfzrfi0M2TR+V4pNjqJl+/ePQlgQ1SYzCZ+JpMUXdwkiV6r\nYzXuyObH6lJHPvdch+ynLSIYsQHHCDEe1qKEsdZXJzEAOc51a17ymlt+HdGg\nYZKENPA80H6h1bxOwf74i6uUNOYRLucAjDDuZX+cBxzILh9HOzl1MLRSgEJR\nD8Yl212H5+02bZb2Mhlrl+iFcfaPwz/CWWFxTW3dFoaAEVpiK+g06vlVKR+4\nIagsh89hAyWLl4mc661vycKi+WdhVQ275bzjtnzmti4E2CKVevksJS6aJKKo\nrtgAVlI0XEWDfduEEH3Bh/MfazmRl2BlKtKQoWmQjnj8ydydEchk2nN0N8cd\nnshOuqhOVtRoCROOUBIZHP84cy7teK0HDNKypv1Lu/43F3pZl12fJNPuo+zA\nGSjCke6YI6GFn0NkZ403iMQnOb8bF/nyQwVNUf/0DXEP3wNJbGyXyrY3HLeY\nleZa/LuXwt/4dXs5+g8RlaMjcqIukABwEwpsqX8G/ASaW9Do6VuwRqD7fva+\nXQCIebFDLUTbtAbI4L0qIqIDPCxvXR67m/j0fzHvzjGDwQzOlL2Og10rI0ZT\nmil5\r\n=FyBn\r\n-----END PGP SIGNATURE-----\r\n"},"main":"source","engines":{"node":">=10"},"funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"95d74cbe8d3df3674dec1445a4608d3288d8b73c","scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"7.5.4","description":"Terminal string styling done right","directories":{},"_nodeVersion":"12.22.1","dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"_hasShrinkwrap":false,"devDependencies":{"xo":"^0.28.2","ava":"^2.4.0","nyc":"^15.0.0","tsd":"^0.7.4","execa":"^4.0.0","matcha":"^0.7.0","coveralls":"^3.0.7","import-fresh":"^3.1.0","resolve-from":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chalk_4.1.2_1627646572658_0.5829286157088185","host":"s3://npm-registry-packages"}},"5.0.0":{"name":"chalk","version":"5.0.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.0.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off"}},"dist":{"shasum":"bd96c6bb8e02b96e08c0c3ee2a9d90e050c7b832","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.0.0.tgz","fileCount":12,"integrity":"sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==","signatures":[{"sig":"MEMCHwQWn9IdUcKlXMudz/Dn2ckiNTICSI/byCzWG3AhrfECIAiIfvI5iXGb5Ps8mCJMHTu07kPNDH3RrsZMoyxnI6ge","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":41306,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhoK+PCRA9TVsSAnZWagAAX+wP/jaVhQWZpfCaDjmJsHuN\n5JQ1XlOLFdbzRfyvuZ2XAn96myIf/1UAa96Pi9gKXjVV1cnRdFW9TPgBMIzt\n42mqC2T8/qJe0a2VFIvlRlSFBMyThbyr3WnDCHvrgjfy8pp6EN10uHwSqnWn\nYL5NemSFQSc2EZ1LxulrJC8bzj3CzcB6yJXDMKUE3BfSFL0r5YxG2FLjktDw\nlL9hm/JxylEPgUIrzKNabO0W77Lcvg2nwJzxRZpDCkLC6NSLx3UV8nDyzoXT\nlvBiR1pxzjWrWbOPvTGO1+5q1HdVTOGqLWA/XjSBBpHZ7SQDgkh9f8pwP823\nep7Q3/2j5BvgleeVzOPQqwGXOq7qbAcBFibHTLd2Zi0xXBFMHtIVaw8odDVV\nAsWqTV4qAgRrefe8Q7wIzUrO42Z5ndRfqHSI6t9bJ4AeH/ZL3vrNNmTFIoLx\nJdWEu1WXSnkrFdCWkxHIjU0wyVJAIAOtK/vQw7LPmOQhEeHLLos/t7fBP9tC\nMi5UoMNZYYE41d5MENeySPAHXZ+ZVIROdAqN7mCCwfAg8lygiNfbNLiPeo9o\nld5H9hYFw4eW31fwvlX8Q6MclVR5k9755fpZUHcyDqgN6hgLJU4j0PHSvnhI\nFrB0wwi7SNJ4DiqIlKtpeNaRSwy1cnaiML3wFeeYKf0zZEAp26bf4CNbZ9XX\ndcEG\r\n=qfhV\r\n-----END PGP SIGNATURE-----\r\n"},"type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"4d5c4795ad24c326ae16bfe0c39c826c732716a9","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.1.0","description":"Terminal string styling done right","directories":{},"_nodeVersion":"12.22.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.47.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.0.0_1637920655740_0.2838492953241636","host":"s3://npm-registry-packages"}},"5.0.1":{"name":"chalk","version":"5.0.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.0.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off"}},"dist":{"shasum":"ca57d71e82bb534a296df63bbacc4a1c22b2a4b6","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz","fileCount":12,"integrity":"sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==","signatures":[{"sig":"MEUCIF8zpu4flQt9Ck8M+VS0lz3b8mdY12JcKsCNaVK+2pY1AiEA4+L33unqlFikjPh1wCQQcPQ5jOpz9l5PGjjp1ERb/GA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":41336,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJ6QUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoR4hAAkZ1Pzo7shU7iLgAUqhpUI79vsAQoqkKYBv9iC+Z4ogWUlcd0\r\nRmauMjugcrKH6fsokqp9jDuJLiZSAbj7nwbmWDoBR9XRrxedjsB2H0eANVlC\r\nTAecFxGdN4gxEBzE6yVOfJelpNuw2qWstXKwOZmLwZkTlqE9LETYWO7xmzfs\r\nUW42alsTOP78ZYRnUWwkeZr3Z8yt7thGUwIi9q+QFsDIt0VwE86uTLeLvv+6\r\npNI04MyKzNkKRG+PF8uW+O+j5PYIr9BPYY++g+f+rayFdwSYcoQjutF0BHdj\r\nG+7DGTrk+dhzCJ5xLSZY0rljcgyY9/KMSj+3rO7fUJalPIpqbwLClmMtfJQU\r\n2MmdM+dJfsXAfoZA5rMxP3GoOC8LC6RaScliVivockrCSJgd9Tp9KzRt+66I\r\nqNiuztSypB5SRB7TC41S8jvIHDw5PNNnNP5C7E/uBjU35yc6aX/2pyxUeXYm\r\nAOPLmVWqBcroBiE4zi4OmG1fB2Izw9DJsK31i2U98lkMLfkVaUa4tIBgVwbU\r\nkB62F3BA86yYuWucYeZL3hp9H1TG5+WBhs9+lHrb0+mH3b6ab2lZu/uCWvH6\r\nSedXquHHQxyM9JcuxDrDtmELqR87B+h0iAKzBf7KYtmyrqrxpHE0FiteQsV9\r\nUJbfD3SPAaX/IBAryNeP4Q4e/oSQDy3YUuI=\r\n=ZFqY\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"bccde97f8a1bb125d4fe99e8fd355182101ff4f2","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.3.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"16.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.47.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.0.1_1646765076079_0.31760153530326884","host":"s3://npm-registry-packages"}},"5.1.0":{"name":"chalk","version":"5.1.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.1.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"c4b4a62bfb6df0eeeb5dbc52e6a9ecaff14b9976","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.1.0.tgz","fileCount":12,"integrity":"sha512-56zD4khRTBoIyzUYAFgDDaPhUMN/fC/rySe6aZGqbj/VWiU2eI3l6ZLOtYGFZAV5v02mwPjtpzlrOveJiz5eZQ==","signatures":[{"sig":"MEYCIQCGiB2UgkPRG76rTZOqtyvgHW3GZdkr1l1grc4mtEcDuQIhAJuhTuvzptwKcBUWBFc4+2YHWu3vqzlDzAAfqkac2pZ1","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":41604,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjPZi8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoY0xAAiHomYe49a9lY0i07r0BEJZGVmegNRGYPJAekN+UaRE/UOx67\r\n6EzdIa7v74VYkhVD4rHBg/O7Uqe+O0U517do414JWVWVXbkB/t5RGjaGtH1s\r\n8OQ85DCyTmIhD15M107/v3qSKWLMhE8lca1KnFYKtCrGFfmEsib8hAFsqS2F\r\nWnrEM152LuQeXnUoUwCaI5yUefG0uLe/yuKhtyWcKToxjmK6HH4ORlG+1o+K\r\nsyXX6Lfv3m40LAIWayP8KE49RjZ1kM0sFK+hasPg8hoxMQgSyM2URnjcUPVN\r\n9wi8ReRUHuaWyuPEPWfRRnYpK8IQnTo24eFaSz4Jz5Z/yVLDYhmOuvzeqXbm\r\nkv74Tnn4HlD7iju3erQQjolvl5D+mKh9ObGjl92nekeyg8G/A/w2EfMpd8FR\r\nJfFBr9Ty+vtNEYbl5iKgzjrl5uLEHKmOGfXXogLsahWB0EXuX2AV8dB5OMlX\r\ngmr68f1jvWYZmxiaKHkXVsLAW/TXl1zWOotSdeYDVDpZQ3SOKtZCez+QKnBQ\r\n1GFqIj/nBmkSGtP++w9Hk9PGAXM7cW/7pLgwT8qGLEeT2SrwnEEAUkImPNJe\r\nnLHSyaS7l7nA267jR5XQQ2SP0wR1alYrE4MKL0nw5wHau8bxLMb1ZFjxE58V\r\n/LYxUMGQDJqfgNtyYmtq8CycQRUv3kbxsHg=\r\n=0Hlp\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"92c55db46f2396c18764e55e6a52dcb49884a42b","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.3.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"14.19.3","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.52.4","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.1.0_1664981180277_0.8837577780411197","host":"s3://npm-registry-packages"}},"5.1.1":{"name":"chalk","version":"5.1.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.1.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"546fb2b8fc5b7dad0991ef81b2a98b265fa71e02","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.1.1.tgz","fileCount":12,"integrity":"sha512-OItMegkSDU3P7OJRWBbNRsQsL8SzgwlIGXSZRVfHCLBYrDgzYDuozwDMwvEDpiZdjr50tdOTbTzuubirtEozsg==","signatures":[{"sig":"MEYCIQCe9oT/CKTmjgzKIXm3S+DVkuwywIySphHQrSYz9xWtGAIhAJNOTCunCt5qIDhrg5pWHvdPHorZeO13auuylbrUjTq/","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":43787,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjRoroACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmotkg//SSk78lf5lQWol2k17UO4dnj+LpYx4gNYLk8uptAPbsRLyhx2\r\nhkmiejrW9Komrzx1FO58JwocXNS5Q2I3mUqG3WisGokfvTWI6kDVlx9l4M0a\r\n0lPo/ENgk9lPN1WUMVx60zCneP/NDxG/sJerE8cM/UnWdc/YHKDiHQEU/hzX\r\nkGAn5juElGo0ae4PAL1M15UsMg3Mk4lyhTRsoztWxYfAI1pNIAxI6ovTaVWg\r\nG/dT6b59DsG6U8dM94cwGxFGtOsnzaBfgupH5Y1T1GvwVQCgeFiLlWWXLAqc\r\nsqP67fUDJtMY1qAJCKhFm80g4eCr6NOvfZ8yovn87Hw8RRmglyOrA46MpQ70\r\nYdJbJBruOToWfR9C9VpcO7BzcPJP79ynfyX70ULe1uP6MZ6R4nJr5FfKanm6\r\ndde4ZTNvLr7ZDWhbW9n4Fr7cVMsT9Jr3f1R/YJLqBNpp0cQBP7UeeJfi+yRj\r\nAsoD1oaDgdDIjcjRBUVAKirU4EwNZ/tk7ejQg710KBK2ccgsiav5rm69TeDd\r\nlCLJdiE856wWK6ZRqY/aXdydoglVJb/L8rG0UK20gaEw4U/BGkLoyvWke/PG\r\nz8VUy2ih3MlSRNVBgXW5U15jT8ku5pnf0jT2yiNT9ke+Vk79Ke7TCPqUj+AU\r\n8htjOcAsRtRTJnQa15nytGTSRtQmQzGqVzg=\r\n=Tswy\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"1b4cd21fb15ca441ab8ff1fc4ce9fcd1365e4b7d","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.3.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"16.15.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.52.4","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.1.1_1665567464573_0.20876003648435004","host":"s3://npm-registry-packages"}},"5.1.2":{"name":"chalk","version":"5.1.2","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.1.2","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"d957f370038b75ac572471e83be4c5ca9f8e8c45","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz","fileCount":12,"integrity":"sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==","signatures":[{"sig":"MEUCIHW+BiaXhxpezvF8SWNxOCnLYZEqgpN7iUr+4sfRrJ1NAiEA45MmChdnALfbsbbqaI0RqSrU6koyuZjSI/FwkJrgCf4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":43787,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjRuv3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpXDg//SHD6IFmJB0Dq/i5hFI0gxlnD9aTFqVEQAatIyxOJvXvEyS7M\r\n+JD3/dOU44ePZ4zH7aYT0YrUnY1oHpijO1elbyL4mhgLxauHuNpYmvgH7dyE\r\nuSKSbvCmvtB/lzeTZR5VDDvq/CYRZ4CTL3N9oZmRMV4b3yw6JGZVa7iTUYvS\r\nz5WdJ89aGNmtH8wvmR1HOfDQOeBEV438VpGhBp2lKy6WYYJVEJgddR/FutMd\r\nwJ4Ptm810A5bNMlhfCQRmjYwEgEz9EipavaM+sS6RWKxLGps+tvTRz1Ukgt5\r\n4yRaEjDpYywtB7ujl/dA2mXKjnJo92uLmirmQkSJHHjSJ8r+M8lx9y4CYdo7\r\nlpzHovkYnDacd3F9rKMZoFZZR7a/VWGCBQQM1P7xabPqCJV88Pyqv1jsjSrE\r\ne/mNaEqSUFomZG//23pavE3UAe2aCfX9V3aZay2rYDdeAmLebCAhxaNqUscL\r\nok0aOwSJG2c0c2RxceQl/7o27CY/5F5iJqg6Dcvk5MbuF0z5GIoMoIRYx4Rs\r\nouwEKeu+7ei4Du7qs55GsjQuSUdR52L5s/UtT1u/RUEvPgoonP33LSr7UxZD\r\nOuN8BdmCdD9MMfiZjf/RUJFrApOa4nCyWB4p9wwKTQc2DZ4TErJJIWwQxyz9\r\nKAkARhOYA8iaWDtpBRlVbeEI/xnbezSuqrA=\r\n=ibOO\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"158bf4429ee5c40fd23d45b7d43e5cbbbdf6795e","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.3.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"16.16.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.52.4","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.1.2_1665592311613_0.6166299016608878","host":"s3://npm-registry-packages"}},"5.2.0":{"name":"chalk","version":"5.2.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.2.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"249623b7d66869c673699fb66d65723e54dfcfb3","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz","fileCount":12,"integrity":"sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==","signatures":[{"sig":"MEQCIGpkIV4DWbErlKu9VI8Xrd6zVKzVBcJP1P4uiwhcauWeAiBCaqZ8GWGM91SUt7da69Vy7lSbP1Qsfns18NVexta3Jw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":43568,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkjEDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpV7g//SkAHVpwaXi9OSemLPPViDVvDgWITSR6UOiBP2kt/IAYeuRw+\r\nBJPNm3iIrJPK55H5xFW8hOTasUdt6pltGY6lBLkNYytOGRKx6Hj4+6gMUbvI\r\nHhrRUb3IJyGAkxQeQ1yqSpjGpubi5T0Xe7q5WFgEm+0cibDPqOBBAl2/Y2mL\r\npHW5cL2zyzTo76TW6m33PjA51ima7eSlXx76ZBYE74NZ69mS30mkxGx7/KW4\r\nN83QnYpIvZi7cfFqcMQQhnD5LK9vm1bE9wbdVvwj3r6tFt+W97egZ3qiBU4g\r\nownwJUfj7tSP0Vi0XQeLhImIh9efdxqvRK5HJjaEWDQhnyAZIw9S22aesGD/\r\nwjL6ehZRawG7TAHvMh4KC/8Yv4Wubx5dJgvGuwOjgv1+45bt+r7xfKPvnBBb\r\nFt+s8YfMvGMv685020Ht9TGmH3DwypB5RltnZoOnmvBpWRfP93uTkLZiweek\r\nbRfzqfjK1kj8V4qqphCfJYU71d9s1q7A5fnRob+MTAJ1opRyK2v30du2D/P0\r\n3IBJ6fynWJUAMHyWg7BZRDfsNWN/pYkW1UP1fMy8V93dXBa2WGuMuVwpRBxK\r\nIzrXhc52uxi1jIZDaZ2RbhcdIxtWLy+5ikYx34nqdMFquh0WWkhXsus1t3A4\r\ndI5gxKg37xdA8NYh9kwQGmZ6HsjrmqMbKUs=\r\n=tvom\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"a370f468a43999e4397094ff5c3d17aadcc4860e","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"8.19.2","description":"Terminal string styling done right","directories":{},"_nodeVersion":"14.21.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.53.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.2.0_1670525187006_0.6054411598751666","host":"s3://npm-registry-packages"}},"5.3.0":{"name":"chalk","version":"5.3.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.3.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"josh@junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"67c20a7ebef70e7f3970a01f90fa210cb6860385","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz","fileCount":12,"integrity":"sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==","signatures":[{"sig":"MEQCIC7jtsJDO883o5OSOE4ygbH48k0Q4SciRc0MhlEjWvJRAiAi1pflMpbvv+4KrVGVN3ZhppLjF45dpLmLJ3dk1VtZug==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":43736},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"72c742d4716b1f94bb24bbda86d96fbb247ca646","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"9.2.0","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"16.20.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.53.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.3.0_1688036291769_0.9519443644747436","host":"s3://npm-registry-packages"}},"5.4.0":{"name":"chalk","version":"5.4.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.4.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"npm@josh.junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"846fdb5d5d939d6fa3d565cd5545697b6f8b6923","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz","fileCount":12,"integrity":"sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==","signatures":[{"sig":"MEQCIF9O9rt/0qVcL415fsimTeAtarR3ClkFa2x24fPx4VzsAiAyfeEfT32AN36Dl+1Wt4T8dyAGqZc0ktD3+hgIiSNnGQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":44129},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"83acfcf8cb17437b63beceb027180399da74f0a7","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"10.9.0","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"23.3.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.57.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.4.0_1734544841544_0.4959266765700201","host":"s3://npm-registry-packages-npm-production"}},"5.4.1":{"name":"chalk","version":"5.4.1","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.4.1","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"npm@josh.junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"1b48bf0963ec158dce2aacf69c093ae2dd2092d8","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz","fileCount":12,"integrity":"sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==","signatures":[{"sig":"MEYCIQCZ5wDikSytgziyeCEmOhw4VJznYEkpJZXRQgJr4o+SUQIhAK3MBAa2qCkGdIpM+MMML0rPG+R12h6M+pqFXKxYO9Yq","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":44242},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"5dbc1e2633f3874f43c144fa4919934bc934c495","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"10.9.0","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"23.3.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.57.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.4.1_1734800692821_0.33369100320867306","host":"s3://npm-registry-packages-npm-production"}},"5.5.0":{"name":"chalk","version":"5.5.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.5.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"npm@josh.junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"67ada1df5ca809dc84c9b819d76418ddcf128428","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz","fileCount":12,"integrity":"sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==","signatures":[{"sig":"MEUCIQDd95By+Xq8YfsvakJXy/bRWZbeZk5y8OoE79Gc2gfr+AIgX7a/na4DrAktKiWQtokee89nf4/BiwRsGmwhYirwauM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44295},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"67db246ae0a2bbcc57c190d641c5d767e5275160","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"20.19.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.57.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.5.0_1754263329622_0.07389803706521159","host":"s3://npm-registry-packages-npm-production"}},"5.6.0":{"name":"chalk","version":"5.6.0","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.6.0","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"qix","email":"npm@josh.junon.me"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"a1a8d294ea3526dbb77660f12649a08490e33ab8","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz","fileCount":12,"integrity":"sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==","signatures":[{"sig":"MEYCIQDltNNES9F6J7ZCIOUmCIhmzarhpwV/RreL30sKz1JmrAIhALm8Tqs3WI9NV4zlCvcssrH4iNus8SHGfj5uM87gYKNd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44342},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"5c91505e184aff4609c0a7fb235770c2f71db4a3","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"20.19.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.57.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.6.0_1755415667378_0.8747575983878675","host":"s3://npm-registry-packages-npm-production"}},"5.6.2":{"name":"chalk","version":"5.6.2","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"license":"MIT","_id":"chalk@5.6.2","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"homepage":"https://github.com/chalk/chalk#readme","bugs":{"url":"https://github.com/chalk/chalk/issues"},"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}},"dist":{"shasum":"b1238b6e23ea337af71c7f8a295db5af0c158aea","tarball":"https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz","fileCount":12,"integrity":"sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==","signatures":[{"sig":"MEUCIAK8R5sdT/x7G+um1BI7SoV0pjX9rmfetVilv4nFhgVMAiEA0zkx6dRcCky2Exe5uLha3/Hnv9JISu7kVVBBFUeZ/RQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44342},"main":"./source/index.js","type":"module","types":"./source/index.d.ts","engines":{"node":"^12.17.0 || ^14.13 || >=16.0.0"},"exports":"./source/index.js","funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"51557784b829c87ff8d138206598764f2eb957b1","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"scripts":{"test":"xo && c8 ava && tsd","bench":"matcha benchmark.js"},"_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal string styling done right","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.10.0","xo":"^0.57.0","ava":"^3.15.0","tsd":"^0.19.0","execa":"^6.0.0","matcha":"^0.7.0","log-update":"^5.0.0","yoctodelay":"^2.0.0","@types/node":"^16.11.10","color-convert":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/chalk_5.6.2_1757342874299_0.9496636300891743","host":"s3://npm-registry-packages-npm-production"}},"6.0.0":{"c8":{"exclude":["source/vendor"],"reporter":["text","lcov"]},"xo":[{"ignores":["source/vendor"]},{"rules":{"no-warning-comments":"off","unicorn/prefer-string-slice":"off","unicorn/expiring-todo-comments":"off","@typescript-eslint/consistent-type-exports":"off","@typescript-eslint/consistent-type-imports":"off","@typescript-eslint/consistent-type-definitions":"off"}}],"_id":"chalk@6.0.0","bugs":{"url":"https://github.com/chalk/chalk/issues"},"dist":{"shasum":"a3bae843bc8454f41ef66ef3fd584dcf34dd805d","tarball":"https://registry.npmjs.org/chalk/-/chalk-6.0.0.tgz","fileCount":12,"integrity":"sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==","signatures":[{"sig":"MEYCIQDkRybaXiWbWA2HNC5DeMLw9jJZD4MXs56nLrqen4Y1kAIhALHJlK4u37pCSgdxBJGY6O4edIq8ihjLF8Syt6UkcXlo","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICO3Obg06YF3rR7AWElxEX/VCksltxq9xZiaac2uUMuhAiEAhANwq2jUyqF/BlXwL2vwnx72HVIxIB16E/Voq7HvzA0="}],"unpackedSize":56029},"name":"chalk","type":"module","engines":{"node":">=22"},"exports":{"types":"./source/index.d.ts","default":"./source/index.js"},"funding":"https://github.com/chalk/chalk?sponsor=1","gitHead":"661317e6f91fe7c90306c2c48ea9354562ee9146","imports":{"#ansi-styles":"./source/vendor/ansi-styles/index.js","#supports-color":{"node":"./source/vendor/supports-color/index.js","default":"./source/vendor/supports-color/browser.js"}},"license":"MIT","scripts":{"test":"xo && c8 ava && tsc --noEmit --types node source/index.d.ts","bench":"matcha benchmark.js"},"version":"6.0.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"homepage":"https://github.com/chalk/chalk#readme","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"_npmVersion":"12.0.1","description":"Terminal string styling done right","directories":{},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.23.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^12.0.0","xo":"^4.0.0","ava":"^8.0.1","execa":"^10.0.0","matcha":"^0.7.0","log-update":"^8.0.0","typescript":"^6.0.3","yoctodelay":"^2.0.0","@types/node":"^26.1.1","ansi-styles":"^6.2.3","color-convert":"^3.1.3"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chalk_6.0.0_1785077467188_0.7480010571173716"}}},"time":{"created":"2013-08-03T00:21:56.318Z","modified":"2026-07-26T14:51:07.471Z","0.1.0":"2013-08-03T00:21:59.499Z","0.1.1":"2013-08-03T01:38:53.881Z","0.2.0":"2013-08-03T16:48:31.308Z","0.2.1":"2013-08-29T14:15:49.234Z","0.3.0":"2013-10-19T15:58:20.344Z","0.4.0":"2013-12-13T19:30:32.742Z","0.5.0":"2014-07-04T21:23:48.003Z","0.5.1":"2014-07-09T20:24:36.498Z","1.0.0":"2015-02-23T07:41:35.421Z","1.1.0":"2015-07-01T13:32:13.906Z","1.1.1":"2015-08-19T20:10:58.495Z","1.1.2":"2016-03-28T23:32:04.003Z","1.1.3":"2016-03-29T00:16:44.512Z","2.0.0":"2017-06-29T23:49:22.932Z","2.0.1":"2017-06-30T03:26:46.721Z","2.1.0":"2017-08-07T03:56:43.217Z","2.2.0":"2017-10-18T03:15:41.898Z","2.2.2":"2017-10-24T03:20:46.238Z","2.3.0":"2017-10-24T04:12:55.953Z","2.3.1":"2018-02-11T13:18:28.596Z","2.3.2":"2018-03-02T17:43:52.786Z","2.4.0":"2018-04-17T04:28:37.857Z","2.4.1":"2018-04-26T05:15:51.877Z","2.4.2":"2019-01-05T15:45:52.349Z","3.0.0-beta.1":"2019-09-27T05:08:09.440Z","3.0.0-beta.2":"2019-10-08T09:32:47.141Z","3.0.0":"2019-11-09T06:59:09.065Z","4.0.0":"2020-04-02T08:20:33.785Z","4.1.0":"2020-06-09T07:43:42.525Z","4.1.1":"2021-04-21T08:54:18.124Z","4.1.2":"2021-07-30T12:02:52.839Z","5.0.0":"2021-11-26T09:57:35.917Z","5.0.1":"2022-03-08T18:44:36.269Z","5.1.0":"2022-10-05T14:46:20.465Z","5.1.1":"2022-10-12T09:37:44.826Z","5.1.2":"2022-10-12T16:31:51.839Z","5.2.0":"2022-12-08T18:46:27.169Z","5.3.0":"2023-06-29T10:58:11.887Z","5.4.0":"2024-12-18T18:00:41.792Z","5.4.1":"2024-12-21T17:04:53.006Z","5.5.0":"2025-08-03T23:22:09.818Z","5.6.0":"2025-08-17T07:27:47.572Z","5.6.1":"2025-09-08T13:13:05.239Z","5.6.2":"2025-09-08T14:47:54.486Z","6.0.0":"2026-07-26T14:51:07.269Z"},"bugs":{"url":"https://github.com/chalk/chalk/issues"},"license":"MIT","homepage":"https://github.com/chalk/chalk#readme","keywords":["color","colour","colors","terminal","console","cli","string","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"repository":{"url":"git+https://github.com/chalk/chalk.git","type":"git"},"description":"Terminal string styling done right","maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"readme":"

\n\t
\n\t
\n\t\"Chalk\"\n\t
\n\t
\n\t
\n

\n\n> Terminal string styling done right\n\n[![Coverage Status](https://codecov.io/gh/chalk/chalk/branch/main/graph/badge.svg)](https://codecov.io/gh/chalk/chalk)\n[![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents)\n[![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk)\n\n![](media/screenshot.png)\n\n## Info\n\n- [Why not switch to a smaller coloring package?](https://github.com/chalk/chalk?tab=readme-ov-file#why-not-switch-to-a-smaller-coloring-package)\n- See [yoctocolors](https://github.com/sindresorhus/yoctocolors) for a smaller alternative\n\n## Highlights\n\n- Expressive API\n- Highly performant\n- No dependencies\n- Ability to nest styles\n- [256/Truecolor color support](#256-and-truecolor-color-support)\n- Auto-detects color support\n- Doesn't extend `String.prototype`\n- Clean and focused\n- Actively maintained\n- [Used by ~115,000 packages](https://www.npmjs.com/browse/depended/chalk) as of July 4, 2024\n\n## Install\n\n```sh\nnpm install chalk\n```\n\n**IMPORTANT:** Chalk 5 is ESM. If you want to use Chalk with TypeScript or a build tool, you will probably want to use Chalk 4 for now. [Read more.](https://github.com/chalk/chalk/releases/tag/v5.0.0)\n\n## Usage\n\n```js\nimport chalk from 'chalk';\n\nconsole.log(chalk.blue('Hello world!'));\n```\n\nChalk comes with an easy to use composable API where you just chain and nest the styles you want.\n\n```js\nimport chalk from 'chalk';\n\nconst log = console.log;\n\n// Combine styled and normal strings\nlog(chalk.blue('Hello') + ' World' + chalk.red('!'));\n\n// Compose multiple styles using the chainable API\nlog(chalk.blue.bgRed.bold('Hello world!'));\n\n// Pass in multiple arguments\nlog(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));\n\n// Nest styles\nlog(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));\n\n// Nest styles of the same type even (color, underline, background)\nlog(chalk.green(\n\t'I am a green line ' +\n\tchalk.blue.underline.bold('with a blue substring') +\n\t' that becomes green again!'\n));\n\n// ES2015 template literal\nlog(`\nCPU: ${chalk.red('90%')}\nRAM: ${chalk.green('40%')}\nDISK: ${chalk.yellow('70%')}\n`);\n\n// Use RGB colors in terminal emulators that support it.\nlog(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));\nlog(chalk.hex('#DEADED').bold('Bold gray!'));\n```\n\nEasily define your own themes:\n\n```js\nimport chalk from 'chalk';\n\nconst error = chalk.bold.red;\nconst warning = chalk.hex('#FFA500'); // Orange color\n\nconsole.log(error('Error!'));\nconsole.log(warning('Warning!'));\n```\n\nTake advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):\n\n```js\nimport chalk from 'chalk';\n\nconst name = 'Sindre';\nconsole.log(chalk.green('Hello %s'), name);\n//=> 'Hello Sindre'\n```\n\n## API\n\n### chalk.`