Compare commits
30 Commits
v1.5.6
...
v1.0.0-dev.7
| Author | SHA1 | Date | |
|---|---|---|---|
| 66df4488c0 | |||
| a3470a3b7a | |||
| a320b6cd16 | |||
| 392d395215 | |||
| 784e516eea | |||
| 2649a3372d | |||
| 28226e8379 | |||
| 947aad0768 | |||
| c11c9348ec | |||
| 1d12504743 | |||
| dc1fae0651 | |||
| 2e1f11c5fe | |||
| c1c7f72da6 | |||
| d63ef2e517 | |||
| dbb62d6790 | |||
| d1a1e5778e | |||
| 6a88d5a0bf | |||
| 9401058586 | |||
| c3337194b7 | |||
| c58f08cc0c | |||
| 8b04c78736 | |||
| cca440f827 | |||
| dfa07ca02c | |||
| 3856ae5eac | |||
| b4d4d3d6d8 | |||
| 321f705db3 | |||
| 54cce55baf | |||
| 1816687ec7 | |||
| c0d61e733d | |||
| 90d717d73f |
@@ -0,0 +1,20 @@
|
|||||||
|
FROM alpine:3.22
|
||||||
|
|
||||||
|
RUN apk update && apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
bash \
|
||||||
|
openjdk21-jdk \
|
||||||
|
maven \
|
||||||
|
git \
|
||||||
|
ca-certificates \
|
||||||
|
pnpm
|
||||||
|
|
||||||
|
# git trust all directories
|
||||||
|
RUN git config --global --add safe.directory '*'
|
||||||
|
|
||||||
|
# Install quarkus
|
||||||
|
ENV JBANG_DIR="/root/.jbang"
|
||||||
|
ENV PATH="${JBANG_DIR}/bin:${PATH}"
|
||||||
|
|
||||||
|
RUN curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/
|
||||||
|
RUN curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio
|
||||||
@@ -1,33 +1,24 @@
|
|||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
// README at: https://github.com/devcontainers/templates/tree/main/src/alpine
|
// README at: https://github.com/devcontainers/templates/tree/main/src/alpine
|
||||||
{
|
{
|
||||||
"name": "Alpine",
|
"dockerComposeFile": "docker-compose.main.yaml",
|
||||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
"mounts": [
|
||||||
"image": "mcr.microsoft.com/devcontainers/base:alpine-3.22",
|
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
|
||||||
"features": {
|
],
|
||||||
"ghcr.io/muhmdraouf/devcontainers-features/alpine-apk:0": {
|
"remoteUser": "root",
|
||||||
"packages": "pnpm",
|
"service": "devcontainer",
|
||||||
"upgradePackages": true
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
}
|
|
||||||
},
|
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"Oracle.oracle-java",
|
"redhat.vscode-quarkus",
|
||||||
"redhat.vscode-quarkus"
|
"vscjava.vscode-java-pack",
|
||||||
|
"redhat.vscode-xml",
|
||||||
|
"esbenp.prettier-vscode"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"containerEnv": {
|
||||||
|
"TESTCONTAINERS_RYUK_DISABLED": "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
|
||||||
// "forwardPorts": [],
|
|
||||||
|
|
||||||
// Use 'postCreateCommand' to run commands after the container is created.
|
|
||||||
// "postCreateCommand": "uname -a",
|
|
||||||
|
|
||||||
// Configure tool-specific properties.
|
|
||||||
// "customizations": {},
|
|
||||||
|
|
||||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
|
||||||
// "remoteUser": "root"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
services:
|
||||||
|
kafka:
|
||||||
|
image: apache/kafka:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
environment:
|
||||||
|
KAFKA_NODE_ID: 1
|
||||||
|
KAFKA_PROCESS_ROLES: broker,controller
|
||||||
|
KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
|
||||||
|
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
|
||||||
|
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
|
||||||
|
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093
|
||||||
|
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
|
||||||
|
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
|
||||||
|
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||||
|
|
||||||
|
kafdrop:
|
||||||
|
image: obsidiandynamics/kafdrop:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- kafka
|
||||||
|
network_mode: host
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
command: sh -c "sleep 5 && exec ./start-app"
|
||||||
|
environment:
|
||||||
|
KAFKA_BROKERCONNECT: "localhost:9092"
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
include:
|
||||||
|
- ./docker-compose.kafka.yaml
|
||||||
|
- ./docker-compose.postgres.yaml
|
||||||
|
|
||||||
|
services:
|
||||||
|
devcontainer:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ../..:/workspaces:cached
|
||||||
|
network_mode: host
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
command: sleep infinity
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_PASSWORD=password
|
||||||
|
network_mode: host
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
name: Release package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
distribution: "temurin"
|
||||||
|
java-version: "25"
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: git.demonkernel.io.vn
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
|
|
||||||
|
- uses: pnpm/action-setup@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
run_install: false
|
||||||
|
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Cache Maven packages
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
name: Setup pnpm cache
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/package.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
|
- name: Run Semantic Release
|
||||||
|
env:
|
||||||
|
GITEA_USER: ${{ github.actor }}
|
||||||
|
GITEA_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm i
|
||||||
|
pnpm format
|
||||||
|
pnpm release
|
||||||
|
|
||||||
|
- name: Commit & Push Changes
|
||||||
|
env:
|
||||||
|
MY_PAT_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$(git status --porcelain)" ]; then
|
||||||
|
git config --global user.name "gitea-actions"
|
||||||
|
git config --global user.email "actions-user@noreply.git.demonkernel.io.vn"
|
||||||
|
|
||||||
|
git remote set-url origin https://x-access-token:${MY_PAT_TOKEN}@git.demonkernel.io.vn/${{ github.repository }}.git
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "chore: release [ci skip]"
|
||||||
|
|
||||||
|
git push origin HEAD:${{ github.ref_name }}
|
||||||
|
fi
|
||||||
|
|||||||
@@ -43,3 +43,6 @@ nb-configuration.xml
|
|||||||
/.quarkus/cli/plugins/
|
/.quarkus/cli/plugins/
|
||||||
# TLS Certificates
|
# TLS Certificates
|
||||||
.certs/
|
.certs/
|
||||||
|
|
||||||
|
# NodeJS
|
||||||
|
/node_modules
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
wrapperVersion=3.3.4
|
||||||
|
distributionType=only-script
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
|
||||||
|
distributionSha256Sum=305773a68d6ddfd413df58c82b3f8050e89778e777f3a745c8e5b8cbea4018ef
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
var baseHasIn = require('./_baseHasIn'),
|
||||||
|
hasPath = require('./_hasPath');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `path` is a direct or inherited property of `object`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 4.0.0
|
||||||
|
* @category Object
|
||||||
|
* @param {Object} object The object to query.
|
||||||
|
* @param {Array|string} path The path to check.
|
||||||
|
* @returns {boolean} Returns `true` if `path` exists, else `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var object = _.create({ 'a': _.create({ 'b': 2 }) });
|
||||||
|
*
|
||||||
|
* _.hasIn(object, 'a');
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.hasIn(object, 'a.b');
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.hasIn(object, ['a', 'b']);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.hasIn(object, 'b');
|
||||||
|
* // => false
|
||||||
|
*/
|
||||||
|
function hasIn(object, path) {
|
||||||
|
return object != null && hasPath(object, path, baseHasIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = hasIn;
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Pierre Vanduynslager
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
var convert = require('./convert');
|
||||||
|
module.exports = convert(require('../function'));
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag.
|
||||||
|
|
||||||
|
@param flag - CLI flag to look for. The `--` prefix is optional.
|
||||||
|
@param argv - CLI arguments. Default: `process.argv`.
|
||||||
|
@returns Whether the flag exists.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
// $ ts-node foo.ts -f --unicorn --foo=bar -- --rainbow
|
||||||
|
|
||||||
|
// foo.ts
|
||||||
|
import hasFlag = require('has-flag');
|
||||||
|
|
||||||
|
hasFlag('unicorn');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('--unicorn');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('f');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('-f');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('foo=bar');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('foo');
|
||||||
|
//=> false
|
||||||
|
|
||||||
|
hasFlag('rainbow');
|
||||||
|
//=> false
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
declare function hasFlag(flag: string, argv?: string[]): boolean;
|
||||||
|
|
||||||
|
export = hasFlag;
|
||||||
+176
@@ -0,0 +1,176 @@
|
|||||||
|
declare class CancelErrorClass extends Error {
|
||||||
|
readonly name: 'CancelError';
|
||||||
|
readonly isCanceled: true;
|
||||||
|
|
||||||
|
constructor(reason?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace PCancelable {
|
||||||
|
/**
|
||||||
|
Accepts a function that is called when the promise is canceled.
|
||||||
|
|
||||||
|
You're not required to call this function. You can call this function multiple times to add multiple cancel handlers.
|
||||||
|
*/
|
||||||
|
interface OnCancelFunction {
|
||||||
|
(cancelHandler: () => void): void;
|
||||||
|
shouldReject: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CancelError = CancelErrorClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class PCancelable<ValueType> extends Promise<ValueType> {
|
||||||
|
/**
|
||||||
|
Convenience method to make your promise-returning or async function cancelable.
|
||||||
|
|
||||||
|
@param fn - A promise-returning function. The function you specify will have `onCancel` appended to its parameters.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import PCancelable = require('p-cancelable');
|
||||||
|
|
||||||
|
const fn = PCancelable.fn((input, onCancel) => {
|
||||||
|
const job = new Job();
|
||||||
|
|
||||||
|
onCancel(() => {
|
||||||
|
job.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
return job.start(); //=> Promise
|
||||||
|
});
|
||||||
|
|
||||||
|
const cancelablePromise = fn('input'); //=> PCancelable
|
||||||
|
|
||||||
|
// …
|
||||||
|
|
||||||
|
cancelablePromise.cancel();
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
static fn<ReturnType>(
|
||||||
|
userFn: (onCancel: PCancelable.OnCancelFunction) => PromiseLike<ReturnType>
|
||||||
|
): () => PCancelable<ReturnType>;
|
||||||
|
static fn<Agument1Type, ReturnType>(
|
||||||
|
userFn: (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => PromiseLike<ReturnType>
|
||||||
|
): (argument1: Agument1Type) => PCancelable<ReturnType>;
|
||||||
|
static fn<Agument1Type, Agument2Type, ReturnType>(
|
||||||
|
userFn: (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => PromiseLike<ReturnType>
|
||||||
|
): (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type
|
||||||
|
) => PCancelable<ReturnType>;
|
||||||
|
static fn<Agument1Type, Agument2Type, Agument3Type, ReturnType>(
|
||||||
|
userFn: (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => PromiseLike<ReturnType>
|
||||||
|
): (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type
|
||||||
|
) => PCancelable<ReturnType>;
|
||||||
|
static fn<Agument1Type, Agument2Type, Agument3Type, Agument4Type, ReturnType>(
|
||||||
|
userFn: (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type,
|
||||||
|
argument4: Agument4Type,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => PromiseLike<ReturnType>
|
||||||
|
): (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type,
|
||||||
|
argument4: Agument4Type
|
||||||
|
) => PCancelable<ReturnType>;
|
||||||
|
static fn<
|
||||||
|
Agument1Type,
|
||||||
|
Agument2Type,
|
||||||
|
Agument3Type,
|
||||||
|
Agument4Type,
|
||||||
|
Agument5Type,
|
||||||
|
ReturnType
|
||||||
|
>(
|
||||||
|
userFn: (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type,
|
||||||
|
argument4: Agument4Type,
|
||||||
|
argument5: Agument5Type,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => PromiseLike<ReturnType>
|
||||||
|
): (
|
||||||
|
argument1: Agument1Type,
|
||||||
|
argument2: Agument2Type,
|
||||||
|
argument3: Agument3Type,
|
||||||
|
argument4: Agument4Type,
|
||||||
|
argument5: Agument5Type
|
||||||
|
) => PCancelable<ReturnType>;
|
||||||
|
static fn<ReturnType>(
|
||||||
|
userFn: (...arguments: unknown[]) => PromiseLike<ReturnType>
|
||||||
|
): (...arguments: unknown[]) => PCancelable<ReturnType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a promise that can be canceled.
|
||||||
|
|
||||||
|
Can be constructed in the same was as a [`Promise` constructor](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise), but with an appended `onCancel` parameter in `executor`. `PCancelable` is a subclass of `Promise`.
|
||||||
|
|
||||||
|
Cancelling will reject the promise with `CancelError`. To avoid that, set `onCancel.shouldReject` to `false`.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import PCancelable = require('p-cancelable');
|
||||||
|
|
||||||
|
const cancelablePromise = new PCancelable((resolve, reject, onCancel) => {
|
||||||
|
const job = new Job();
|
||||||
|
|
||||||
|
onCancel.shouldReject = false;
|
||||||
|
onCancel(() => {
|
||||||
|
job.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
job.on('finish', resolve);
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelablePromise.cancel(); // Doesn't throw an error
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
executor: (
|
||||||
|
resolve: (value?: ValueType | PromiseLike<ValueType>) => void,
|
||||||
|
reject: (reason?: unknown) => void,
|
||||||
|
onCancel: PCancelable.OnCancelFunction
|
||||||
|
) => void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether the promise is canceled.
|
||||||
|
*/
|
||||||
|
readonly isCanceled: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Cancel the promise and optionally provide a reason.
|
||||||
|
|
||||||
|
The cancellation is synchronous. Calling it after the promise has settled or multiple times does nothing.
|
||||||
|
|
||||||
|
@param reason - The cancellation reason to reject the promise with.
|
||||||
|
*/
|
||||||
|
cancel: (reason?: string) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Rejection reason when `.cancel()` is called.
|
||||||
|
|
||||||
|
It includes a `.isCanceled` property for convenience.
|
||||||
|
*/
|
||||||
|
static CancelError: typeof CancelErrorClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = PCancelable;
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('defaultsAll', require('../defaults'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
export interface TimeEndFunction {
|
||||||
|
/**
|
||||||
|
@returns Elapsed milliseconds.
|
||||||
|
*/
|
||||||
|
(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@returns Elapsed milliseconds rounded.
|
||||||
|
*/
|
||||||
|
rounded(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@returns Elapsed seconds.
|
||||||
|
*/
|
||||||
|
seconds(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@returns Elapsed nanoseconds.
|
||||||
|
*/
|
||||||
|
nanoseconds(): bigint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simplified high resolution timing.
|
||||||
|
|
||||||
|
@returns A function that returns the time difference.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import timeSpan from 'time-span';
|
||||||
|
|
||||||
|
const end = timeSpan();
|
||||||
|
|
||||||
|
timeConsumingFn();
|
||||||
|
|
||||||
|
console.log(end());
|
||||||
|
//=> 1745.3186
|
||||||
|
|
||||||
|
console.log(end.rounded());
|
||||||
|
//=> 1745
|
||||||
|
|
||||||
|
console.log(end.seconds());
|
||||||
|
//=> 1.7453186
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
export default function timeSpan(): TimeEndFunction;
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const u = require('universalify').fromCallback
|
||||||
|
const jsonFile = require('./jsonfile')
|
||||||
|
|
||||||
|
jsonFile.outputJson = u(require('./output-json'))
|
||||||
|
jsonFile.outputJsonSync = require('./output-json-sync')
|
||||||
|
// aliases
|
||||||
|
jsonFile.outputJSON = jsonFile.outputJson
|
||||||
|
jsonFile.outputJSONSync = jsonFile.outputJsonSync
|
||||||
|
jsonFile.writeJSON = jsonFile.writeJson
|
||||||
|
jsonFile.writeJSONSync = jsonFile.writeJsonSync
|
||||||
|
jsonFile.readJSON = jsonFile.readJson
|
||||||
|
jsonFile.readJSONSync = jsonFile.readJsonSync
|
||||||
|
|
||||||
|
module.exports = jsonFile
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
var apply = require('./_apply'),
|
||||||
|
arrayPush = require('./_arrayPush'),
|
||||||
|
baseRest = require('./_baseRest'),
|
||||||
|
castSlice = require('./_castSlice'),
|
||||||
|
toInteger = require('./toInteger');
|
||||||
|
|
||||||
|
/** Error message constants. */
|
||||||
|
var FUNC_ERROR_TEXT = 'Expected a function';
|
||||||
|
|
||||||
|
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||||||
|
var nativeMax = Math.max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function that invokes `func` with the `this` binding of the
|
||||||
|
* create function and an array of arguments much like
|
||||||
|
* [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
|
||||||
|
*
|
||||||
|
* **Note:** This method is based on the
|
||||||
|
* [spread operator](https://mdn.io/spread_operator).
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 3.2.0
|
||||||
|
* @category Function
|
||||||
|
* @param {Function} func The function to spread arguments over.
|
||||||
|
* @param {number} [start=0] The start position of the spread.
|
||||||
|
* @returns {Function} Returns the new function.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var say = _.spread(function(who, what) {
|
||||||
|
* return who + ' says ' + what;
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* say(['fred', 'hello']);
|
||||||
|
* // => 'fred says hello'
|
||||||
|
*
|
||||||
|
* var numbers = Promise.all([
|
||||||
|
* Promise.resolve(40),
|
||||||
|
* Promise.resolve(36)
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* numbers.then(_.spread(function(x, y) {
|
||||||
|
* return x + y;
|
||||||
|
* }));
|
||||||
|
* // => a Promise of 76
|
||||||
|
*/
|
||||||
|
function spread(func, start) {
|
||||||
|
if (typeof func != 'function') {
|
||||||
|
throw new TypeError(FUNC_ERROR_TEXT);
|
||||||
|
}
|
||||||
|
start = start == null ? 0 : nativeMax(toInteger(start), 0);
|
||||||
|
return baseRest(function(args) {
|
||||||
|
var array = args[start],
|
||||||
|
otherArgs = castSlice(args, 0, start);
|
||||||
|
|
||||||
|
if (array) {
|
||||||
|
arrayPush(otherArgs, array);
|
||||||
|
}
|
||||||
|
return apply(func, this, otherArgs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = spread;
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Checks if `value` is `null` or `undefined`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 4.0.0
|
||||||
|
* @category Lang
|
||||||
|
* @param {*} value The value to check.
|
||||||
|
* @returns {boolean} Returns `true` if `value` is nullish, else `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.isNil(null);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isNil(void 0);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isNil(NaN);
|
||||||
|
* // => false
|
||||||
|
*/
|
||||||
|
function isNil(value) {
|
||||||
|
return value == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default isNil;
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
type Pathname = string
|
||||||
|
|
||||||
|
interface TestResult {
|
||||||
|
ignored: boolean
|
||||||
|
unignored: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Ignore {
|
||||||
|
/**
|
||||||
|
* Adds one or several rules to the current manager.
|
||||||
|
* @param {string[]} patterns
|
||||||
|
* @returns IgnoreBase
|
||||||
|
*/
|
||||||
|
add(patterns: string | Ignore | readonly (string | Ignore)[]): this
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the given array of pathnames, and returns the filtered array.
|
||||||
|
* NOTICE that each path here should be a relative path to the root of your repository.
|
||||||
|
* @param paths the array of paths to be filtered.
|
||||||
|
* @returns The filtered array of paths
|
||||||
|
*/
|
||||||
|
filter(pathnames: readonly Pathname[]): Pathname[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a filter function which could filter
|
||||||
|
* an array of paths with Array.prototype.filter.
|
||||||
|
*/
|
||||||
|
createFilter(): (pathname: Pathname) => boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Boolean whether pathname should be ignored.
|
||||||
|
* @param {string} pathname a path to check
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
ignores(pathname: Pathname): boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether pathname should be ignored or unignored
|
||||||
|
* @param {string} pathname a path to check
|
||||||
|
* @returns TestResult
|
||||||
|
*/
|
||||||
|
test(pathname: Pathname): TestResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
ignorecase?: boolean
|
||||||
|
// For compatibility
|
||||||
|
ignoreCase?: boolean
|
||||||
|
allowRelativePaths?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new ignore manager.
|
||||||
|
*/
|
||||||
|
declare function ignore(options?: Options): Ignore
|
||||||
|
|
||||||
|
declare namespace ignore {
|
||||||
|
export function isPathValid (pathname: string): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ignore
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
IR_Black style (c) Vasily Mikhailitchenko <vaskas@programica.ru>
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 0.5em;
|
||||||
|
background: #000;
|
||||||
|
color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-quote,
|
||||||
|
.hljs-meta {
|
||||||
|
color: #7c7c7c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-tag,
|
||||||
|
.hljs-name {
|
||||||
|
color: #96cbfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-attribute,
|
||||||
|
.hljs-selector-id {
|
||||||
|
color: #ffffb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo,
|
||||||
|
.hljs-addition {
|
||||||
|
color: #a8ff60;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-subst {
|
||||||
|
color: #daefa3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-regexp,
|
||||||
|
.hljs-link {
|
||||||
|
color: #e9c062;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-doctag {
|
||||||
|
color: #ffffb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-literal {
|
||||||
|
color: #c6c5fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-deletion {
|
||||||
|
color:#ff73fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-emphasis {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const which = require('../lib')
|
||||||
|
const argv = process.argv.slice(2)
|
||||||
|
|
||||||
|
const usage = (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`which: ${err}`)
|
||||||
|
}
|
||||||
|
console.error('usage: which [-as] program ...')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argv.length) {
|
||||||
|
return usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
let dashdash = false
|
||||||
|
const [commands, flags] = argv.reduce((acc, arg) => {
|
||||||
|
if (dashdash || arg === '--') {
|
||||||
|
dashdash = true
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!/^-/.test(arg)) {
|
||||||
|
acc[0].push(arg)
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const flag of arg.slice(1).split('')) {
|
||||||
|
if (flag === 's') {
|
||||||
|
acc[1].silent = true
|
||||||
|
} else if (flag === 'a') {
|
||||||
|
acc[1].all = true
|
||||||
|
} else {
|
||||||
|
usage(`illegal option -- ${flag}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, [[], {}])
|
||||||
|
|
||||||
|
for (const command of commands) {
|
||||||
|
try {
|
||||||
|
const res = which.sync(command, { all: flags.all })
|
||||||
|
if (!flags.silent) {
|
||||||
|
console.log([].concat(res).join('\n'))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
process.exitCode = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
Description: Srcery dark color scheme for highlight.js
|
||||||
|
Author: Chen Bin <chen.bin@gmail.com>
|
||||||
|
Website: https://srcery-colors.github.io/
|
||||||
|
Date: 2020-04-06
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 0.5em;
|
||||||
|
background: #1C1B19;
|
||||||
|
color: #FCE8C3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-strong,
|
||||||
|
.hljs-emphasis {
|
||||||
|
color: #918175;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-quote,
|
||||||
|
.hljs-link,
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-regexp,
|
||||||
|
.hljs-literal {
|
||||||
|
color: #FF5C8F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-code,
|
||||||
|
.hljs-selector-class {
|
||||||
|
color: #68A8E4
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-emphasis {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-attribute,
|
||||||
|
.hljs-variable {
|
||||||
|
color: #EF2F27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-name,
|
||||||
|
.hljs-title {
|
||||||
|
color: #FBB829;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-params {
|
||||||
|
color: #0AAEB3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string {
|
||||||
|
color: #98BC37;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-subst,
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-builtin-name,
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-selector-id,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo,
|
||||||
|
.hljs-template-tag,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-addition {
|
||||||
|
color: #C07ABE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-deletion,
|
||||||
|
.hljs-meta {
|
||||||
|
color: #918175;
|
||||||
|
}
|
||||||
+228
@@ -0,0 +1,228 @@
|
|||||||
|
// pkg/dist-src/index.js
|
||||||
|
import BottleneckLight from "bottleneck/light.js";
|
||||||
|
|
||||||
|
// pkg/dist-src/version.js
|
||||||
|
var VERSION = "0.0.0-development";
|
||||||
|
|
||||||
|
// pkg/dist-src/wrap-request.js
|
||||||
|
var noop = () => Promise.resolve();
|
||||||
|
function wrapRequest(state, request, options) {
|
||||||
|
return state.retryLimiter.schedule(doRequest, state, request, options);
|
||||||
|
}
|
||||||
|
async function doRequest(state, request, options) {
|
||||||
|
const { pathname } = new URL(options.url, "http://github.test");
|
||||||
|
const isAuth = isAuthRequest(options.method, pathname);
|
||||||
|
const isWrite = !isAuth && options.method !== "GET" && options.method !== "HEAD";
|
||||||
|
const isSearch = options.method === "GET" && pathname.startsWith("/search/");
|
||||||
|
const isGraphQL = pathname.startsWith("/graphql");
|
||||||
|
const retryCount = ~~request.retryCount;
|
||||||
|
const jobOptions = retryCount > 0 ? { priority: 0, weight: 0 } : {};
|
||||||
|
if (state.clustering) {
|
||||||
|
jobOptions.expiration = 1e3 * 60;
|
||||||
|
}
|
||||||
|
if (isWrite || isGraphQL) {
|
||||||
|
await state.write.key(state.id).schedule(jobOptions, noop);
|
||||||
|
}
|
||||||
|
if (isWrite && state.triggersNotification(pathname)) {
|
||||||
|
await state.notifications.key(state.id).schedule(jobOptions, noop);
|
||||||
|
}
|
||||||
|
if (isSearch) {
|
||||||
|
await state.search.key(state.id).schedule(jobOptions, noop);
|
||||||
|
}
|
||||||
|
const req = (isAuth ? state.auth : state.global).key(state.id).schedule(jobOptions, request, options);
|
||||||
|
if (isGraphQL) {
|
||||||
|
const res = await req;
|
||||||
|
if (res.data.errors != null && res.data.errors.some((error) => error.type === "RATE_LIMITED")) {
|
||||||
|
const error = Object.assign(new Error("GraphQL Rate Limit Exceeded"), {
|
||||||
|
response: res,
|
||||||
|
data: res.data
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
function isAuthRequest(method, pathname) {
|
||||||
|
return method === "PATCH" && // https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-a-scoped-access-token
|
||||||
|
/^\/applications\/[^/]+\/token\/scoped$/.test(pathname) || method === "POST" && // https://docs.github.com/en/rest/apps/oauth-applications?apiVersion=2022-11-28#reset-a-token
|
||||||
|
(/^\/applications\/[^/]+\/token$/.test(pathname) || // https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app
|
||||||
|
/^\/app\/installations\/[^/]+\/access_tokens$/.test(pathname) || // https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
|
||||||
|
pathname === "/login/oauth/access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkg/dist-src/generated/triggers-notification-paths.js
|
||||||
|
var triggers_notification_paths_default = [
|
||||||
|
"/orgs/{org}/invitations",
|
||||||
|
"/orgs/{org}/invitations/{invitation_id}",
|
||||||
|
"/orgs/{org}/teams/{team_slug}/discussions",
|
||||||
|
"/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments",
|
||||||
|
"/repos/{owner}/{repo}/collaborators/{username}",
|
||||||
|
"/repos/{owner}/{repo}/commits/{commit_sha}/comments",
|
||||||
|
"/repos/{owner}/{repo}/issues",
|
||||||
|
"/repos/{owner}/{repo}/issues/{issue_number}/comments",
|
||||||
|
"/repos/{owner}/{repo}/issues/{issue_number}/sub_issue",
|
||||||
|
"/repos/{owner}/{repo}/issues/{issue_number}/sub_issues/priority",
|
||||||
|
"/repos/{owner}/{repo}/pulls",
|
||||||
|
"/repos/{owner}/{repo}/pulls/{pull_number}/comments",
|
||||||
|
"/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies",
|
||||||
|
"/repos/{owner}/{repo}/pulls/{pull_number}/merge",
|
||||||
|
"/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers",
|
||||||
|
"/repos/{owner}/{repo}/pulls/{pull_number}/reviews",
|
||||||
|
"/repos/{owner}/{repo}/releases",
|
||||||
|
"/teams/{team_id}/discussions",
|
||||||
|
"/teams/{team_id}/discussions/{discussion_number}/comments"
|
||||||
|
];
|
||||||
|
|
||||||
|
// pkg/dist-src/route-matcher.js
|
||||||
|
function routeMatcher(paths) {
|
||||||
|
const regexes = paths.map(
|
||||||
|
(path) => path.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
||||||
|
);
|
||||||
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
||||||
|
return new RegExp(regex2, "i");
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkg/dist-src/index.js
|
||||||
|
var regex = routeMatcher(triggers_notification_paths_default);
|
||||||
|
var triggersNotification = regex.test.bind(regex);
|
||||||
|
var groups = {};
|
||||||
|
var createGroups = function(Bottleneck, common) {
|
||||||
|
groups.global = new Bottleneck.Group({
|
||||||
|
id: "octokit-global",
|
||||||
|
maxConcurrent: 10,
|
||||||
|
...common
|
||||||
|
});
|
||||||
|
groups.auth = new Bottleneck.Group({
|
||||||
|
id: "octokit-auth",
|
||||||
|
maxConcurrent: 1,
|
||||||
|
...common
|
||||||
|
});
|
||||||
|
groups.search = new Bottleneck.Group({
|
||||||
|
id: "octokit-search",
|
||||||
|
maxConcurrent: 1,
|
||||||
|
minTime: 2e3,
|
||||||
|
...common
|
||||||
|
});
|
||||||
|
groups.write = new Bottleneck.Group({
|
||||||
|
id: "octokit-write",
|
||||||
|
maxConcurrent: 1,
|
||||||
|
minTime: 1e3,
|
||||||
|
...common
|
||||||
|
});
|
||||||
|
groups.notifications = new Bottleneck.Group({
|
||||||
|
id: "octokit-notifications",
|
||||||
|
maxConcurrent: 1,
|
||||||
|
minTime: 3e3,
|
||||||
|
...common
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function throttling(octokit, octokitOptions) {
|
||||||
|
const {
|
||||||
|
enabled = true,
|
||||||
|
Bottleneck = BottleneckLight,
|
||||||
|
id = "no-id",
|
||||||
|
timeout = 1e3 * 60 * 2,
|
||||||
|
// Redis TTL: 2 minutes
|
||||||
|
connection
|
||||||
|
} = octokitOptions.throttle || {};
|
||||||
|
if (!enabled) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const common = { timeout };
|
||||||
|
if (typeof connection !== "undefined") {
|
||||||
|
common.connection = connection;
|
||||||
|
}
|
||||||
|
if (groups.global == null) {
|
||||||
|
createGroups(Bottleneck, common);
|
||||||
|
}
|
||||||
|
const state = Object.assign(
|
||||||
|
{
|
||||||
|
clustering: connection != null,
|
||||||
|
triggersNotification,
|
||||||
|
fallbackSecondaryRateRetryAfter: 60,
|
||||||
|
retryAfterBaseValue: 1e3,
|
||||||
|
retryLimiter: new Bottleneck(),
|
||||||
|
id,
|
||||||
|
...groups
|
||||||
|
},
|
||||||
|
octokitOptions.throttle
|
||||||
|
);
|
||||||
|
if (typeof state.onSecondaryRateLimit !== "function" || typeof state.onRateLimit !== "function") {
|
||||||
|
throw new Error(`octokit/plugin-throttling error:
|
||||||
|
You must pass the onSecondaryRateLimit and onRateLimit error handlers.
|
||||||
|
See https://octokit.github.io/rest.js/#throttling
|
||||||
|
|
||||||
|
const octokit = new Octokit({
|
||||||
|
throttle: {
|
||||||
|
onSecondaryRateLimit: (retryAfter, options) => {/* ... */},
|
||||||
|
onRateLimit: (retryAfter, options) => {/* ... */}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
const events = {};
|
||||||
|
const emitter = new Bottleneck.Events(events);
|
||||||
|
events.on("secondary-limit", state.onSecondaryRateLimit);
|
||||||
|
events.on("rate-limit", state.onRateLimit);
|
||||||
|
events.on(
|
||||||
|
"error",
|
||||||
|
(e) => octokit.log.warn("Error in throttling-plugin limit handler", e)
|
||||||
|
);
|
||||||
|
state.retryLimiter.on("failed", async function(error, info) {
|
||||||
|
const [state2, request, options] = info.args;
|
||||||
|
const { pathname } = new URL(options.url, "http://github.test");
|
||||||
|
const shouldRetryGraphQL = pathname.startsWith("/graphql") && error.status !== 401;
|
||||||
|
if (!(shouldRetryGraphQL || error.status === 403 || error.status === 429)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const retryCount = ~~request.retryCount;
|
||||||
|
request.retryCount = retryCount;
|
||||||
|
options.request.retryCount = retryCount;
|
||||||
|
const { wantRetry, retryAfter = 0 } = await (async function() {
|
||||||
|
if (/\bsecondary rate\b/i.test(error.message)) {
|
||||||
|
const retryAfter2 = Number(error.response.headers["retry-after"]) || state2.fallbackSecondaryRateRetryAfter;
|
||||||
|
const wantRetry2 = await emitter.trigger(
|
||||||
|
"secondary-limit",
|
||||||
|
retryAfter2,
|
||||||
|
options,
|
||||||
|
octokit,
|
||||||
|
retryCount
|
||||||
|
);
|
||||||
|
return { wantRetry: wantRetry2, retryAfter: retryAfter2 };
|
||||||
|
}
|
||||||
|
if (error.response.headers != null && error.response.headers["x-ratelimit-remaining"] === "0" || (error.response.data?.errors ?? []).some(
|
||||||
|
(error2) => error2.type === "RATE_LIMITED"
|
||||||
|
)) {
|
||||||
|
const rateLimitReset = new Date(
|
||||||
|
~~error.response.headers["x-ratelimit-reset"] * 1e3
|
||||||
|
).getTime();
|
||||||
|
const retryAfter2 = Math.max(
|
||||||
|
// Add one second so we retry _after_ the reset time
|
||||||
|
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#exceeding-the-rate-limit
|
||||||
|
Math.ceil((rateLimitReset - Date.now()) / 1e3) + 1,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const wantRetry2 = await emitter.trigger(
|
||||||
|
"rate-limit",
|
||||||
|
retryAfter2,
|
||||||
|
options,
|
||||||
|
octokit,
|
||||||
|
retryCount
|
||||||
|
);
|
||||||
|
return { wantRetry: wantRetry2, retryAfter: retryAfter2 };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
})();
|
||||||
|
if (wantRetry) {
|
||||||
|
request.retryCount++;
|
||||||
|
return retryAfter * state2.retryAfterBaseValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
octokit.hook.wrap("request", wrapRequest.bind(null, state));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
throttling.VERSION = VERSION;
|
||||||
|
throttling.triggersNotification = triggersNotification;
|
||||||
|
export {
|
||||||
|
throttling
|
||||||
|
};
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
import type {_DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
|
||||||
|
import type {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep.d.ts';
|
||||||
|
import type {ApplyDefaultOptions} from './internal/index.d.ts';
|
||||||
|
import type {WordsOptions} from './words.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert object properties to kebab case recursively.
|
||||||
|
|
||||||
|
This can be useful when, for example, converting some API types from a different style.
|
||||||
|
|
||||||
|
@see {@link KebabCase}
|
||||||
|
@see {@link KebabCasedProperties}
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {KebabCasedPropertiesDeep} from 'type-fest';
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
userId: number;
|
||||||
|
userName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserWithFriends = {
|
||||||
|
userInfo: User;
|
||||||
|
userFriends: User[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const result: KebabCasedPropertiesDeep<UserWithFriends> = {
|
||||||
|
'user-info': {
|
||||||
|
'user-id': 1,
|
||||||
|
'user-name': 'Tom',
|
||||||
|
},
|
||||||
|
'user-friends': [
|
||||||
|
{
|
||||||
|
'user-id': 2,
|
||||||
|
'user-name': 'Jerry',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'user-id': 3,
|
||||||
|
'user-name': 'Spike',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitOnNumbers: KebabCasedPropertiesDeep<{line1: {line2: [{line3: string}]}}, {splitOnNumbers: true}> = {
|
||||||
|
'line-1': {
|
||||||
|
'line-2': [
|
||||||
|
{
|
||||||
|
'line-3': 'string',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@category Change case
|
||||||
|
@category Template literal
|
||||||
|
@category Object
|
||||||
|
*/
|
||||||
|
export type KebabCasedPropertiesDeep<
|
||||||
|
Value,
|
||||||
|
Options extends WordsOptions = {},
|
||||||
|
> = DelimiterCasedPropertiesDeep<Value, '-', ApplyDefaultOptions<WordsOptions, _DefaultDelimiterCaseOptions, Options>>;
|
||||||
|
|
||||||
|
export {};
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "@nodelib/fs.stat",
|
||||||
|
"version": "2.0.5",
|
||||||
|
"description": "Get the status of a file with some features",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.stat",
|
||||||
|
"keywords": [
|
||||||
|
"NodeLib",
|
||||||
|
"fs",
|
||||||
|
"FileSystem",
|
||||||
|
"file system",
|
||||||
|
"stat"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"out/**",
|
||||||
|
"!out/**/*.map",
|
||||||
|
"!out/**/*.spec.*"
|
||||||
|
],
|
||||||
|
"main": "out/index.js",
|
||||||
|
"typings": "out/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf {tsconfig.tsbuildinfo,out}",
|
||||||
|
"lint": "eslint \"src/**/*.ts\" --cache",
|
||||||
|
"compile": "tsc -b .",
|
||||||
|
"compile:watch": "tsc -p . --watch --sourceMap",
|
||||||
|
"test": "mocha \"out/**/*.spec.js\" -s 0",
|
||||||
|
"build": "npm run clean && npm run compile && npm run lint && npm test",
|
||||||
|
"watch": "npm run clean && npm run compile:watch"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nodelib/fs.macchiato": "1.0.4"
|
||||||
|
},
|
||||||
|
"gitHead": "d6a7960d5281d3dd5f8e2efba49bb552d090f562"
|
||||||
|
}
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
# Connecting through a proxy
|
||||||
|
|
||||||
|
Connecting through a proxy is possible by:
|
||||||
|
|
||||||
|
- Using [ProxyAgent](/docs/docs/api/ProxyAgent.md).
|
||||||
|
- Configuring `Client` or `Pool` constructor.
|
||||||
|
|
||||||
|
The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url
|
||||||
|
should be added to every request call in the `path`.
|
||||||
|
For instance, if you need to send a request to the `/hello` route of your upstream server,
|
||||||
|
the `path` should be `path: 'http://upstream.server:port/hello?foo=bar'`.
|
||||||
|
|
||||||
|
If you proxy requires basic authentication, you can send it via the `proxy-authorization` header.
|
||||||
|
|
||||||
|
### Connect without authentication
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Client } from 'undici'
|
||||||
|
import { createServer } from 'http'
|
||||||
|
import { createProxy } from 'proxy'
|
||||||
|
|
||||||
|
const server = await buildServer()
|
||||||
|
const proxyServer = await buildProxy()
|
||||||
|
|
||||||
|
const serverUrl = `http://localhost:${server.address().port}`
|
||||||
|
const proxyUrl = `http://localhost:${proxyServer.address().port}`
|
||||||
|
|
||||||
|
server.on('request', (req, res) => {
|
||||||
|
console.log(req.url) // '/hello?foo=bar'
|
||||||
|
res.setHeader('content-type', 'application/json')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
})
|
||||||
|
|
||||||
|
const client = new Client(proxyUrl)
|
||||||
|
|
||||||
|
const response = await client.request({
|
||||||
|
method: 'GET',
|
||||||
|
path: serverUrl + '/hello?foo=bar'
|
||||||
|
})
|
||||||
|
|
||||||
|
response.body.setEncoding('utf8')
|
||||||
|
let data = ''
|
||||||
|
for await (const chunk of response.body) {
|
||||||
|
data += chunk
|
||||||
|
}
|
||||||
|
console.log(response.statusCode) // 200
|
||||||
|
console.log(JSON.parse(data)) // { hello: 'world' }
|
||||||
|
|
||||||
|
server.close()
|
||||||
|
proxyServer.close()
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
function buildServer () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const server = createServer()
|
||||||
|
server.listen(0, () => resolve(server))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildProxy () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const server = createProxy(createServer())
|
||||||
|
server.listen(0, () => resolve(server))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connect with authentication
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Client } from 'undici'
|
||||||
|
import { createServer } from 'http'
|
||||||
|
import { createProxy } from 'proxy'
|
||||||
|
|
||||||
|
const server = await buildServer()
|
||||||
|
const proxyServer = await buildProxy()
|
||||||
|
|
||||||
|
const serverUrl = `http://localhost:${server.address().port}`
|
||||||
|
const proxyUrl = `http://localhost:${proxyServer.address().port}`
|
||||||
|
|
||||||
|
proxyServer.authenticate = function (req) {
|
||||||
|
return req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`
|
||||||
|
}
|
||||||
|
|
||||||
|
server.on('request', (req, res) => {
|
||||||
|
console.log(req.url) // '/hello?foo=bar'
|
||||||
|
res.setHeader('content-type', 'application/json')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
})
|
||||||
|
|
||||||
|
const client = new Client(proxyUrl)
|
||||||
|
|
||||||
|
const response = await client.request({
|
||||||
|
method: 'GET',
|
||||||
|
path: serverUrl + '/hello?foo=bar',
|
||||||
|
headers: {
|
||||||
|
'proxy-authorization': `Basic ${Buffer.from('user:pass').toString('base64')}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
response.body.setEncoding('utf8')
|
||||||
|
let data = ''
|
||||||
|
for await (const chunk of response.body) {
|
||||||
|
data += chunk
|
||||||
|
}
|
||||||
|
console.log(response.statusCode) // 200
|
||||||
|
console.log(JSON.parse(data)) // { hello: 'world' }
|
||||||
|
|
||||||
|
server.close()
|
||||||
|
proxyServer.close()
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
function buildServer () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const server = createServer()
|
||||||
|
server.listen(0, () => resolve(server))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildProxy () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const server = createProxy(createServer())
|
||||||
|
server.listen(0, () => resolve(server))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
return not (redis.call('exists', settings_key) == 1)
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
var defer = require('./defer.js');
|
||||||
|
|
||||||
|
// API
|
||||||
|
module.exports = async;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs provided callback asynchronously
|
||||||
|
* even if callback itself is not
|
||||||
|
*
|
||||||
|
* @param {function} callback - callback to invoke
|
||||||
|
* @returns {function} - augmented callback
|
||||||
|
*/
|
||||||
|
function async(callback)
|
||||||
|
{
|
||||||
|
var isAsync = false;
|
||||||
|
|
||||||
|
// check if async happened
|
||||||
|
defer(function() { isAsync = true; });
|
||||||
|
|
||||||
|
return function async_callback(err, result)
|
||||||
|
{
|
||||||
|
if (isAsync)
|
||||||
|
{
|
||||||
|
callback(err, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defer(function nextTick_callback()
|
||||||
|
{
|
||||||
|
callback(err, result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Language: RenderMan RSL
|
||||||
|
Author: Konstantin Evdokimenko <qewerty@gmail.com>
|
||||||
|
Contributors: Shuen-Huei Guan <drake.guan@gmail.com>
|
||||||
|
Website: https://renderman.pixar.com/resources/RenderMan_20/shadingLanguage.html
|
||||||
|
Category: graphics
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rsl(hljs) {
|
||||||
|
return {
|
||||||
|
name: 'RenderMan RSL',
|
||||||
|
keywords: {
|
||||||
|
keyword:
|
||||||
|
'float color point normal vector matrix while for if do return else break extern continue',
|
||||||
|
built_in:
|
||||||
|
'abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise ' +
|
||||||
|
'clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp ' +
|
||||||
|
'faceforward filterstep floor format fresnel incident length lightsource log match ' +
|
||||||
|
'max min mod noise normalize ntransform opposite option phong pnoise pow printf ' +
|
||||||
|
'ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp ' +
|
||||||
|
'setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan ' +
|
||||||
|
'texture textureinfo trace transform vtransform xcomp ycomp zcomp'
|
||||||
|
},
|
||||||
|
illegal: '</',
|
||||||
|
contains: [
|
||||||
|
hljs.C_LINE_COMMENT_MODE,
|
||||||
|
hljs.C_BLOCK_COMMENT_MODE,
|
||||||
|
hljs.QUOTE_STRING_MODE,
|
||||||
|
hljs.APOS_STRING_MODE,
|
||||||
|
hljs.C_NUMBER_MODE,
|
||||||
|
{
|
||||||
|
className: 'meta',
|
||||||
|
begin: '#',
|
||||||
|
end: '$'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'class',
|
||||||
|
beginKeywords: 'surface displacement light volume imager',
|
||||||
|
end: '\\('
|
||||||
|
},
|
||||||
|
{
|
||||||
|
beginKeywords: 'illuminate illuminance gather',
|
||||||
|
end: '\\('
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = rsl;
|
||||||
+258
@@ -0,0 +1,258 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
* @returns {RegExp}
|
||||||
|
* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {RegExp | string } re
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function source(re) {
|
||||||
|
if (!re) return null;
|
||||||
|
if (typeof re === "string") return re;
|
||||||
|
|
||||||
|
return re.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {...(RegExp | string) } args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function concat(...args) {
|
||||||
|
const joined = args.map((x) => source(x)).join("");
|
||||||
|
return joined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Language: Markdown
|
||||||
|
Requires: xml.js
|
||||||
|
Author: John Crepezzi <john.crepezzi@gmail.com>
|
||||||
|
Website: https://daringfireball.net/projects/markdown/
|
||||||
|
Category: common, markup
|
||||||
|
*/
|
||||||
|
|
||||||
|
function markdown(hljs) {
|
||||||
|
const INLINE_HTML = {
|
||||||
|
begin: /<\/?[A-Za-z_]/,
|
||||||
|
end: '>',
|
||||||
|
subLanguage: 'xml',
|
||||||
|
relevance: 0
|
||||||
|
};
|
||||||
|
const HORIZONTAL_RULE = {
|
||||||
|
begin: '^[-\\*]{3,}',
|
||||||
|
end: '$'
|
||||||
|
};
|
||||||
|
const CODE = {
|
||||||
|
className: 'code',
|
||||||
|
variants: [
|
||||||
|
// TODO: fix to allow these to work with sublanguage also
|
||||||
|
{
|
||||||
|
begin: '(`{3,})[^`](.|\\n)*?\\1`*[ ]*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '(~{3,})[^~](.|\\n)*?\\1~*[ ]*'
|
||||||
|
},
|
||||||
|
// needed to allow markdown as a sublanguage to work
|
||||||
|
{
|
||||||
|
begin: '```',
|
||||||
|
end: '```+[ ]*$'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '~~~',
|
||||||
|
end: '~~~+[ ]*$'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '`.+?`'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '(?=^( {4}|\\t))',
|
||||||
|
// use contains to gobble up multiple lines to allow the block to be whatever size
|
||||||
|
// but only have a single open/close tag vs one per line
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
begin: '^( {4}|\\t)',
|
||||||
|
end: '(\\n)$'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
relevance: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const LIST = {
|
||||||
|
className: 'bullet',
|
||||||
|
begin: '^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)',
|
||||||
|
end: '\\s+',
|
||||||
|
excludeEnd: true
|
||||||
|
};
|
||||||
|
const LINK_REFERENCE = {
|
||||||
|
begin: /^\[[^\n]+\]:/,
|
||||||
|
returnBegin: true,
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: 'symbol',
|
||||||
|
begin: /\[/,
|
||||||
|
end: /\]/,
|
||||||
|
excludeBegin: true,
|
||||||
|
excludeEnd: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'link',
|
||||||
|
begin: /:\s*/,
|
||||||
|
end: /$/,
|
||||||
|
excludeBegin: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const URL_SCHEME = /[A-Za-z][A-Za-z0-9+.-]*/;
|
||||||
|
const LINK = {
|
||||||
|
variants: [
|
||||||
|
// too much like nested array access in so many languages
|
||||||
|
// to have any real relevance
|
||||||
|
{
|
||||||
|
begin: /\[.+?\]\[.*?\]/,
|
||||||
|
relevance: 0
|
||||||
|
},
|
||||||
|
// popular internet URLs
|
||||||
|
{
|
||||||
|
begin: /\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,
|
||||||
|
relevance: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: concat(/\[.+?\]\(/, URL_SCHEME, /:\/\/.*?\)/),
|
||||||
|
relevance: 2
|
||||||
|
},
|
||||||
|
// relative urls
|
||||||
|
{
|
||||||
|
begin: /\[.+?\]\([./?&#].*?\)/,
|
||||||
|
relevance: 1
|
||||||
|
},
|
||||||
|
// whatever else, lower relevance (might not be a link at all)
|
||||||
|
{
|
||||||
|
begin: /\[.+?\]\(.*?\)/,
|
||||||
|
relevance: 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returnBegin: true,
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
relevance: 0,
|
||||||
|
begin: '\\[',
|
||||||
|
end: '\\]',
|
||||||
|
excludeBegin: true,
|
||||||
|
returnEnd: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'link',
|
||||||
|
relevance: 0,
|
||||||
|
begin: '\\]\\(',
|
||||||
|
end: '\\)',
|
||||||
|
excludeBegin: true,
|
||||||
|
excludeEnd: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'symbol',
|
||||||
|
relevance: 0,
|
||||||
|
begin: '\\]\\[',
|
||||||
|
end: '\\]',
|
||||||
|
excludeBegin: true,
|
||||||
|
excludeEnd: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const BOLD = {
|
||||||
|
className: 'strong',
|
||||||
|
contains: [], // defined later
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
begin: /_{2}/,
|
||||||
|
end: /_{2}/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: /\*{2}/,
|
||||||
|
end: /\*{2}/
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const ITALIC = {
|
||||||
|
className: 'emphasis',
|
||||||
|
contains: [], // defined later
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
begin: /\*(?!\*)/,
|
||||||
|
end: /\*/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: /_(?!_)/,
|
||||||
|
end: /_/,
|
||||||
|
relevance: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
BOLD.contains.push(ITALIC);
|
||||||
|
ITALIC.contains.push(BOLD);
|
||||||
|
|
||||||
|
let CONTAINABLE = [
|
||||||
|
INLINE_HTML,
|
||||||
|
LINK
|
||||||
|
];
|
||||||
|
|
||||||
|
BOLD.contains = BOLD.contains.concat(CONTAINABLE);
|
||||||
|
ITALIC.contains = ITALIC.contains.concat(CONTAINABLE);
|
||||||
|
|
||||||
|
CONTAINABLE = CONTAINABLE.concat(BOLD, ITALIC);
|
||||||
|
|
||||||
|
const HEADER = {
|
||||||
|
className: 'section',
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
begin: '^#{1,6}',
|
||||||
|
end: '$',
|
||||||
|
contains: CONTAINABLE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '(?=^.+?\\n[=-]{2,}$)',
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
begin: '^[=-]*$'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
begin: '^',
|
||||||
|
end: "\\n",
|
||||||
|
contains: CONTAINABLE
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const BLOCKQUOTE = {
|
||||||
|
className: 'quote',
|
||||||
|
begin: '^>\\s+',
|
||||||
|
contains: CONTAINABLE,
|
||||||
|
end: '$'
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'Markdown',
|
||||||
|
aliases: [
|
||||||
|
'md',
|
||||||
|
'mkdown',
|
||||||
|
'mkd'
|
||||||
|
],
|
||||||
|
contains: [
|
||||||
|
HEADER,
|
||||||
|
INLINE_HTML,
|
||||||
|
LIST,
|
||||||
|
BOLD,
|
||||||
|
ITALIC,
|
||||||
|
BLOCKQUOTE,
|
||||||
|
CODE,
|
||||||
|
HORIZONTAL_RULE,
|
||||||
|
LINK,
|
||||||
|
LINK_REFERENCE
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = markdown;
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
// tar -x
|
||||||
|
import * as fsm from '@isaacs/fs-minipass';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import { filesFilter } from './list.js';
|
||||||
|
import { makeCommand } from './make-command.js';
|
||||||
|
import { Unpack, UnpackSync } from './unpack.js';
|
||||||
|
const extractFileSync = (opt) => {
|
||||||
|
const u = new UnpackSync(opt);
|
||||||
|
const file = opt.file;
|
||||||
|
const stat = fs.statSync(file);
|
||||||
|
// This trades a zero-byte read() syscall for a stat
|
||||||
|
// However, it will usually result in less memory allocation
|
||||||
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
||||||
|
const stream = new fsm.ReadStreamSync(file, {
|
||||||
|
readSize: readSize,
|
||||||
|
size: stat.size,
|
||||||
|
});
|
||||||
|
stream.pipe(u);
|
||||||
|
};
|
||||||
|
const extractFile = (opt, _) => {
|
||||||
|
const u = new Unpack(opt);
|
||||||
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
||||||
|
const file = opt.file;
|
||||||
|
const p = new Promise((resolve, reject) => {
|
||||||
|
u.on('error', reject);
|
||||||
|
u.on('close', resolve);
|
||||||
|
// This trades a zero-byte read() syscall for a stat
|
||||||
|
// However, it will usually result in less memory allocation
|
||||||
|
fs.stat(file, (er, stat) => {
|
||||||
|
if (er) {
|
||||||
|
reject(er);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const stream = new fsm.ReadStream(file, {
|
||||||
|
readSize: readSize,
|
||||||
|
size: stat.size,
|
||||||
|
});
|
||||||
|
stream.on('error', reject);
|
||||||
|
stream.pipe(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
export const extract = makeCommand(extractFileSync, extractFile, opt => new UnpackSync(opt), opt => new Unpack(opt), (opt, files) => {
|
||||||
|
if (files?.length)
|
||||||
|
filesFilter(opt, files);
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=extract.js.map
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
import type { ResponseHeaders } from "@octokit/types";
|
||||||
|
import type { GraphQlEndpointOptions, GraphQlQueryResponse } from "./types.js";
|
||||||
|
type ServerResponseData<T> = Required<GraphQlQueryResponse<T>>;
|
||||||
|
export declare class GraphqlResponseError<ResponseData> extends Error {
|
||||||
|
readonly request: GraphQlEndpointOptions;
|
||||||
|
readonly headers: ResponseHeaders;
|
||||||
|
readonly response: ServerResponseData<ResponseData>;
|
||||||
|
name: string;
|
||||||
|
readonly errors: GraphQlQueryResponse<never>["errors"];
|
||||||
|
readonly data: ResponseData;
|
||||||
|
constructor(request: GraphQlEndpointOptions, headers: ResponseHeaders, response: ServerResponseData<ResponseData>);
|
||||||
|
}
|
||||||
|
export {};
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
import type {Whitespace} from './internal/index.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove spaces from the left side.
|
||||||
|
*/
|
||||||
|
type TrimLeft<V extends string> = V extends `${Whitespace}${infer R}` ? TrimLeft<R> : V;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove spaces from the right side.
|
||||||
|
*/
|
||||||
|
type TrimRight<V extends string> = V extends `${infer R}${Whitespace}` ? TrimRight<R> : V;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove leading and trailing spaces from a string.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {Trim} from 'type-fest';
|
||||||
|
|
||||||
|
type Example = Trim<' foo '>;
|
||||||
|
//=> 'foo'
|
||||||
|
```
|
||||||
|
|
||||||
|
@category String
|
||||||
|
@category Template literal
|
||||||
|
*/
|
||||||
|
export type Trim<V extends string> = TrimLeft<TrimRight<V>>;
|
||||||
|
|
||||||
|
export {};
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports["default"] = void 0;
|
||||||
|
var _node = _interopRequireDefault(require("./node"));
|
||||||
|
var _types = require("./types");
|
||||||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||||||
|
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
|
||||||
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
||||||
|
var Nesting = /*#__PURE__*/function (_Node) {
|
||||||
|
_inheritsLoose(Nesting, _Node);
|
||||||
|
function Nesting(opts) {
|
||||||
|
var _this;
|
||||||
|
_this = _Node.call(this, opts) || this;
|
||||||
|
_this.type = _types.NESTING;
|
||||||
|
_this.value = '&';
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return Nesting;
|
||||||
|
}(_node["default"]);
|
||||||
|
exports["default"] = Nesting;
|
||||||
|
module.exports = exports.default;
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
# combined-stream
|
||||||
|
|
||||||
|
A stream that emits multiple other streams one after another.
|
||||||
|
|
||||||
|
**NB** Currently `combined-stream` works with streams version 1 only. There is ongoing effort to switch this library to streams version 2. Any help is welcome. :) Meanwhile you can explore other libraries that provide streams2 support with more or less compatibility with `combined-stream`.
|
||||||
|
|
||||||
|
- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module.
|
||||||
|
|
||||||
|
- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
npm install combined-stream
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Here is a simple example that shows how you can use combined-stream to combine
|
||||||
|
two files into one:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var CombinedStream = require('combined-stream');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var combinedStream = CombinedStream.create();
|
||||||
|
combinedStream.append(fs.createReadStream('file1.txt'));
|
||||||
|
combinedStream.append(fs.createReadStream('file2.txt'));
|
||||||
|
|
||||||
|
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||||
|
```
|
||||||
|
|
||||||
|
While the example above works great, it will pause all source streams until
|
||||||
|
they are needed. If you don't want that to happen, you can set `pauseStreams`
|
||||||
|
to `false`:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var CombinedStream = require('combined-stream');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var combinedStream = CombinedStream.create({pauseStreams: false});
|
||||||
|
combinedStream.append(fs.createReadStream('file1.txt'));
|
||||||
|
combinedStream.append(fs.createReadStream('file2.txt'));
|
||||||
|
|
||||||
|
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||||
|
```
|
||||||
|
|
||||||
|
However, what if you don't have all the source streams yet, or you don't want
|
||||||
|
to allocate the resources (file descriptors, memory, etc.) for them right away?
|
||||||
|
Well, in that case you can simply provide a callback that supplies the stream
|
||||||
|
by calling a `next()` function:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var CombinedStream = require('combined-stream');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var combinedStream = CombinedStream.create();
|
||||||
|
combinedStream.append(function(next) {
|
||||||
|
next(fs.createReadStream('file1.txt'));
|
||||||
|
});
|
||||||
|
combinedStream.append(function(next) {
|
||||||
|
next(fs.createReadStream('file2.txt'));
|
||||||
|
});
|
||||||
|
|
||||||
|
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### CombinedStream.create([options])
|
||||||
|
|
||||||
|
Returns a new combined stream object. Available options are:
|
||||||
|
|
||||||
|
* `maxDataSize`
|
||||||
|
* `pauseStreams`
|
||||||
|
|
||||||
|
The effect of those options is described below.
|
||||||
|
|
||||||
|
### combinedStream.pauseStreams = `true`
|
||||||
|
|
||||||
|
Whether to apply back pressure to the underlaying streams. If set to `false`,
|
||||||
|
the underlaying streams will never be paused. If set to `true`, the
|
||||||
|
underlaying streams will be paused right after being appended, as well as when
|
||||||
|
`delayedStream.pipe()` wants to throttle.
|
||||||
|
|
||||||
|
### combinedStream.maxDataSize = `2 * 1024 * 1024`
|
||||||
|
|
||||||
|
The maximum amount of bytes (or characters) to buffer for all source streams.
|
||||||
|
If this value is exceeded, `combinedStream` emits an `'error'` event.
|
||||||
|
|
||||||
|
### combinedStream.dataSize = `0`
|
||||||
|
|
||||||
|
The amount of bytes (or characters) currently buffered by `combinedStream`.
|
||||||
|
|
||||||
|
### combinedStream.append(stream)
|
||||||
|
|
||||||
|
Appends the given `stream` to the combinedStream object. If `pauseStreams` is
|
||||||
|
set to `true, this stream will also be paused right away.
|
||||||
|
|
||||||
|
`streams` can also be a function that takes one parameter called `next`. `next`
|
||||||
|
is a function that must be invoked in order to provide the `next` stream, see
|
||||||
|
example above.
|
||||||
|
|
||||||
|
Regardless of how the `stream` is appended, combined-stream always attaches an
|
||||||
|
`'error'` listener to it, so you don't have to do that manually.
|
||||||
|
|
||||||
|
Special case: `stream` can also be a String or Buffer.
|
||||||
|
|
||||||
|
### combinedStream.write(data)
|
||||||
|
|
||||||
|
You should not call this, `combinedStream` takes care of piping the appended
|
||||||
|
streams into itself for you.
|
||||||
|
|
||||||
|
### combinedStream.resume()
|
||||||
|
|
||||||
|
Causes `combinedStream` to start drain the streams it manages. The function is
|
||||||
|
idempotent, and also emits a `'resume'` event each time which usually goes to
|
||||||
|
the stream that is currently being drained.
|
||||||
|
|
||||||
|
### combinedStream.pause();
|
||||||
|
|
||||||
|
If `combinedStream.pauseStreams` is set to `false`, this does nothing.
|
||||||
|
Otherwise a `'pause'` event is emitted, this goes to the stream that is
|
||||||
|
currently being drained, so you can use it to apply back pressure.
|
||||||
|
|
||||||
|
### combinedStream.end();
|
||||||
|
|
||||||
|
Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
|
||||||
|
all streams from the queue.
|
||||||
|
|
||||||
|
### combinedStream.destroy();
|
||||||
|
|
||||||
|
Same as `combinedStream.end()`, except it emits a `'close'` event instead of
|
||||||
|
`'end'`.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
combined-stream is licensed under the MIT license.
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
# Class: RetryAgent
|
||||||
|
|
||||||
|
Extends: `undici.Dispatcher`
|
||||||
|
|
||||||
|
A `undici.Dispatcher` that allows to automatically retry a request.
|
||||||
|
Wraps a `undici.RetryHandler`.
|
||||||
|
|
||||||
|
## `new RetryAgent(dispatcher, [options])`
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
* **dispatcher** `undici.Dispatcher` (required) - the dispatcher to wrap
|
||||||
|
* **options** `RetryHandlerOptions` (optional) - the options
|
||||||
|
|
||||||
|
Returns: `ProxyAgent`
|
||||||
|
|
||||||
|
### Parameter: `RetryHandlerOptions`
|
||||||
|
|
||||||
|
- **retry** `(err: Error, context: RetryContext, callback: (err?: Error | null) => void) => void` (optional) - Function to be called after every retry. It should pass error if no more retries should be performed.
|
||||||
|
- **maxRetries** `number` (optional) - Maximum number of retries. Default: `5`
|
||||||
|
- **maxTimeout** `number` (optional) - Maximum number of milliseconds to wait before retrying. Default: `30000` (30 seconds)
|
||||||
|
- **minTimeout** `number` (optional) - Minimum number of milliseconds to wait before retrying. Default: `500` (half a second)
|
||||||
|
- **timeoutFactor** `number` (optional) - Factor to multiply the timeout by for each retry attempt. Default: `2`
|
||||||
|
- **retryAfter** `boolean` (optional) - It enables automatic retry after the `Retry-After` header is received. Default: `true`
|
||||||
|
-
|
||||||
|
- **methods** `string[]` (optional) - Array of HTTP methods to retry. Default: `['GET', 'PUT', 'HEAD', 'OPTIONS', 'DELETE']`
|
||||||
|
- **statusCodes** `number[]` (optional) - Array of HTTP status codes to retry. Default: `[429, 500, 502, 503, 504]`
|
||||||
|
- **errorCodes** `string[]` (optional) - Array of Error codes to retry. Default: `['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN','ENETUNREACH', 'EHOSTDOWN', 'UND_ERR_SOCKET']`
|
||||||
|
|
||||||
|
**`RetryContext`**
|
||||||
|
|
||||||
|
- `state`: `RetryState` - Current retry state. It can be mutated.
|
||||||
|
- `opts`: `Dispatch.DispatchOptions & RetryOptions` - Options passed to the retry handler.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Agent, RetryAgent } from 'undici'
|
||||||
|
|
||||||
|
const agent = new RetryAgent(new Agent())
|
||||||
|
|
||||||
|
const res = await agent.request('http://example.com')
|
||||||
|
console.log(res.statuCode)
|
||||||
|
console.log(await res.body.text())
|
||||||
|
```
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
import type {DelimiterCasedProperties} from './delimiter-cased-properties';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert object properties to snake case but not recursively.
|
||||||
|
|
||||||
|
This can be useful when, for example, converting some API types from a different style.
|
||||||
|
|
||||||
|
@see SnakeCase
|
||||||
|
@see SnakeCasedPropertiesDeep
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {SnakeCasedProperties} from 'type-fest';
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
userId: number;
|
||||||
|
userName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: SnakeCasedProperties<User> = {
|
||||||
|
user_id: 1,
|
||||||
|
user_name: 'Tom',
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@category Change case
|
||||||
|
@category Template literal
|
||||||
|
@category Object
|
||||||
|
*/
|
||||||
|
export type SnakeCasedProperties<Value> = DelimiterCasedProperties<Value, '_'>;
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
# has-flag [](https://travis-ci.org/sindresorhus/has-flag)
|
||||||
|
|
||||||
|
> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
|
||||||
|
|
||||||
|
Correctly stops looking after an `--` argument terminator.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<b>
|
||||||
|
<a href="https://tidelift.com/subscription/pkg/npm-has-flag?utm_source=npm-has-flag&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
|
||||||
|
</b>
|
||||||
|
<br>
|
||||||
|
<sub>
|
||||||
|
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||||
|
</sub>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install has-flag
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
// foo.js
|
||||||
|
const hasFlag = require('has-flag');
|
||||||
|
|
||||||
|
hasFlag('unicorn');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('--unicorn');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('f');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('-f');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('foo=bar');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
hasFlag('foo');
|
||||||
|
//=> false
|
||||||
|
|
||||||
|
hasFlag('rainbow');
|
||||||
|
//=> false
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ node foo.js -f --unicorn --foo=bar -- --rainbow
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### hasFlag(flag, [argv])
|
||||||
|
|
||||||
|
Returns a boolean for whether the flag exists.
|
||||||
|
|
||||||
|
#### flag
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
CLI flag to look for. The `--` prefix is optional.
|
||||||
|
|
||||||
|
#### argv
|
||||||
|
|
||||||
|
Type: `string[]`<br>
|
||||||
|
Default: `process.argv`
|
||||||
|
|
||||||
|
CLI arguments.
|
||||||
|
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) Robert Kowalski and Isaac Z. Schlueter ("Authors")
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
The BSD License
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
import castPath from './_castPath.js';
|
||||||
|
import isFunction from './isFunction.js';
|
||||||
|
import toKey from './_toKey.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is like `_.get` except that if the resolved value is a
|
||||||
|
* function it's invoked with the `this` binding of its parent object and
|
||||||
|
* its result is returned.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @since 0.1.0
|
||||||
|
* @memberOf _
|
||||||
|
* @category Object
|
||||||
|
* @param {Object} object The object to query.
|
||||||
|
* @param {Array|string} path The path of the property to resolve.
|
||||||
|
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
|
||||||
|
* @returns {*} Returns the resolved value.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
|
||||||
|
*
|
||||||
|
* _.result(object, 'a[0].b.c1');
|
||||||
|
* // => 3
|
||||||
|
*
|
||||||
|
* _.result(object, 'a[0].b.c2');
|
||||||
|
* // => 4
|
||||||
|
*
|
||||||
|
* _.result(object, 'a[0].b.c3', 'default');
|
||||||
|
* // => 'default'
|
||||||
|
*
|
||||||
|
* _.result(object, 'a[0].b.c3', _.constant('default'));
|
||||||
|
* // => 'default'
|
||||||
|
*/
|
||||||
|
function result(object, path, defaultValue) {
|
||||||
|
path = castPath(path, object);
|
||||||
|
|
||||||
|
var index = -1,
|
||||||
|
length = path.length;
|
||||||
|
|
||||||
|
// Ensure the loop is entered when path is empty.
|
||||||
|
if (!length) {
|
||||||
|
length = 1;
|
||||||
|
object = undefined;
|
||||||
|
}
|
||||||
|
while (++index < length) {
|
||||||
|
var value = object == null ? undefined : object[toKey(path[index])];
|
||||||
|
if (value === undefined) {
|
||||||
|
index = length;
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
object = isFunction(value) ? value.call(object) : value;
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default result;
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import http = require('http');
|
||||||
|
import https = require('https');
|
||||||
|
import stream = require('stream');
|
||||||
|
import { Merge } from 'type-fest';
|
||||||
|
import { Defaults, NormalizedOptions, RequestFunction, URLOrOptions, requestSymbol } from './types';
|
||||||
|
export declare const preNormalizeArguments: (options: Merge<https.RequestOptions, Merge<import("./types").GotOptions, import("./utils/options-to-url").URLOptions>>, defaults?: NormalizedOptions | undefined) => NormalizedOptions;
|
||||||
|
export declare const mergeOptions: (...sources: Merge<https.RequestOptions, Merge<import("./types").GotOptions, import("./utils/options-to-url").URLOptions>>[]) => NormalizedOptions;
|
||||||
|
export declare const normalizeArguments: (url: URLOrOptions, options?: Merge<https.RequestOptions, Merge<import("./types").GotOptions, import("./utils/options-to-url").URLOptions>> | undefined, defaults?: Defaults | undefined) => NormalizedOptions;
|
||||||
|
export declare type NormalizedRequestArguments = Merge<https.RequestOptions, {
|
||||||
|
body?: stream.Readable;
|
||||||
|
[requestSymbol]: RequestFunction;
|
||||||
|
url: Pick<NormalizedOptions, 'url'>;
|
||||||
|
}>;
|
||||||
|
export declare const normalizeRequestArguments: (options: NormalizedOptions) => Promise<Merge<https.RequestOptions, {
|
||||||
|
body?: stream.Readable | undefined;
|
||||||
|
url: Pick<NormalizedOptions, "url">;
|
||||||
|
[requestSymbol]: typeof http.request;
|
||||||
|
}>>;
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
import { castArray, identity, isNil, isPlainObject, isString, omit } from "lodash-es";
|
||||||
|
import AggregateError from "aggregate-error";
|
||||||
|
import getError from "../get-error.js";
|
||||||
|
import PLUGINS_DEFINITIONS from "../definitions/plugins.js";
|
||||||
|
import { loadPlugin, parseConfig, validatePlugin, validateStep } from "./utils.js";
|
||||||
|
import pipeline from "./pipeline.js";
|
||||||
|
import normalize from "./normalize.js";
|
||||||
|
|
||||||
|
export default async (context, pluginsPath) => {
|
||||||
|
let { options, logger } = context;
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
const plugins = options.plugins
|
||||||
|
? await castArray(options.plugins).reduce(async (eventualPluginsList, plugin) => {
|
||||||
|
const pluginsList = await eventualPluginsList;
|
||||||
|
if (validatePlugin(plugin)) {
|
||||||
|
const [name, config] = parseConfig(plugin);
|
||||||
|
plugin = isString(name) ? await loadPlugin(context, name, pluginsPath) : name;
|
||||||
|
|
||||||
|
if (isPlainObject(plugin)) {
|
||||||
|
Object.entries(plugin).forEach(([type, func]) => {
|
||||||
|
if (PLUGINS_DEFINITIONS[type]) {
|
||||||
|
Reflect.defineProperty(func, "pluginName", {
|
||||||
|
value: isPlainObject(name) ? "Inline plugin" : name,
|
||||||
|
writable: false,
|
||||||
|
enumerable: true,
|
||||||
|
});
|
||||||
|
pluginsList[type] = [...(pluginsList[type] || []), [func, config]];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
errors.push(getError("EPLUGINSCONF", { plugin }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors.push(getError("EPLUGINSCONF", { plugin }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pluginsList;
|
||||||
|
}, {})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
throw new AggregateError(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = { ...plugins, ...options };
|
||||||
|
|
||||||
|
const pluginsConfig = await Object.entries(PLUGINS_DEFINITIONS).reduce(
|
||||||
|
async (
|
||||||
|
eventualPluginsConfigAccumulator,
|
||||||
|
[type, { required, default: def, pipelineConfig, postprocess = identity, preprocess = identity }]
|
||||||
|
) => {
|
||||||
|
let pluginOptions;
|
||||||
|
const pluginsConfigAccumulator = await eventualPluginsConfigAccumulator;
|
||||||
|
|
||||||
|
if (isNil(options[type]) && def) {
|
||||||
|
pluginOptions = def;
|
||||||
|
} else {
|
||||||
|
// If an object is passed and the path is missing, merge it with step options
|
||||||
|
if (isPlainObject(options[type]) && !options[type].path) {
|
||||||
|
options[type] = castArray(plugins[type]).map((plugin) =>
|
||||||
|
plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateStep({ required }, options[type])) {
|
||||||
|
errors.push(getError("EPLUGINCONF", { type, required, pluginConf: options[type] }));
|
||||||
|
return pluginsConfigAccumulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginOptions = options[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
const steps = await Promise.all(
|
||||||
|
castArray(pluginOptions).map(async (pluginOpt) =>
|
||||||
|
normalize(
|
||||||
|
{ ...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), "plugins") },
|
||||||
|
type,
|
||||||
|
pluginOpt,
|
||||||
|
pluginsPath
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
pluginsConfigAccumulator[type] = async (input) =>
|
||||||
|
postprocess(
|
||||||
|
await pipeline(
|
||||||
|
steps,
|
||||||
|
pipelineConfig && pipelineConfig(pluginsConfigAccumulator, logger)
|
||||||
|
)(await preprocess(input)),
|
||||||
|
input
|
||||||
|
);
|
||||||
|
|
||||||
|
return pluginsConfigAccumulator;
|
||||||
|
},
|
||||||
|
plugins
|
||||||
|
);
|
||||||
|
if (errors.length > 0) {
|
||||||
|
throw new AggregateError(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pluginsConfig;
|
||||||
|
};
|
||||||
+304
@@ -0,0 +1,304 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const log = require('./log')
|
||||||
|
const semver = require('semver')
|
||||||
|
const { execFile } = require('./util')
|
||||||
|
const win = process.platform === 'win32'
|
||||||
|
|
||||||
|
function getOsUserInfo () {
|
||||||
|
try {
|
||||||
|
return require('os').userInfo().username
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemDrive = process.env.SystemDrive || 'C:'
|
||||||
|
const username = process.env.USERNAME || process.env.USER || getOsUserInfo()
|
||||||
|
const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local`
|
||||||
|
const foundLocalAppData = process.env.LOCALAPPDATA || username
|
||||||
|
const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${systemDrive}\\Program Files`
|
||||||
|
const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)`
|
||||||
|
|
||||||
|
const winDefaultLocationsArray = []
|
||||||
|
for (const majorMinor of ['311', '310', '39', '38']) {
|
||||||
|
if (foundLocalAppData) {
|
||||||
|
winDefaultLocationsArray.push(
|
||||||
|
`${localAppData}\\Programs\\Python\\Python${majorMinor}\\python.exe`,
|
||||||
|
`${programFiles}\\Python${majorMinor}\\python.exe`,
|
||||||
|
`${localAppData}\\Programs\\Python\\Python${majorMinor}-32\\python.exe`,
|
||||||
|
`${programFiles}\\Python${majorMinor}-32\\python.exe`,
|
||||||
|
`${programFilesX86}\\Python${majorMinor}-32\\python.exe`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
winDefaultLocationsArray.push(
|
||||||
|
`${programFiles}\\Python${majorMinor}\\python.exe`,
|
||||||
|
`${programFiles}\\Python${majorMinor}-32\\python.exe`,
|
||||||
|
`${programFilesX86}\\Python${majorMinor}-32\\python.exe`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PythonFinder {
|
||||||
|
static findPython = (...args) => new PythonFinder(...args).findPython()
|
||||||
|
|
||||||
|
log = log.withPrefix('find Python')
|
||||||
|
argsExecutable = ['-c', 'import sys; sys.stdout.buffer.write(sys.executable.encode(\'utf-8\'));']
|
||||||
|
argsVersion = ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);']
|
||||||
|
semverRange = '>=3.6.0'
|
||||||
|
|
||||||
|
// These can be overridden for testing:
|
||||||
|
execFile = execFile
|
||||||
|
env = process.env
|
||||||
|
win = win
|
||||||
|
pyLauncher = 'py.exe'
|
||||||
|
winDefaultLocations = winDefaultLocationsArray
|
||||||
|
|
||||||
|
constructor (configPython) {
|
||||||
|
this.configPython = configPython
|
||||||
|
this.errorLog = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logs a message at verbose level, but also saves it to be displayed later
|
||||||
|
// at error level if an error occurs. This should help diagnose the problem.
|
||||||
|
addLog (message) {
|
||||||
|
this.log.verbose(message)
|
||||||
|
this.errorLog.push(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find Python by trying a sequence of possibilities.
|
||||||
|
// Ignore errors, keep trying until Python is found.
|
||||||
|
async findPython () {
|
||||||
|
const SKIP = 0
|
||||||
|
const FAIL = 1
|
||||||
|
const toCheck = (() => {
|
||||||
|
if (this.env.NODE_GYP_FORCE_PYTHON) {
|
||||||
|
return [{
|
||||||
|
before: () => {
|
||||||
|
this.addLog(
|
||||||
|
'checking Python explicitly set from NODE_GYP_FORCE_PYTHON')
|
||||||
|
this.addLog('- process.env.NODE_GYP_FORCE_PYTHON is ' +
|
||||||
|
`"${this.env.NODE_GYP_FORCE_PYTHON}"`)
|
||||||
|
},
|
||||||
|
check: () => this.checkCommand(this.env.NODE_GYP_FORCE_PYTHON)
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
const checks = [
|
||||||
|
{
|
||||||
|
before: () => {
|
||||||
|
if (!this.configPython) {
|
||||||
|
this.addLog('--python was not set on the command line')
|
||||||
|
return SKIP
|
||||||
|
}
|
||||||
|
this.addLog(`--python=${this.configPython} was set on the command line`)
|
||||||
|
},
|
||||||
|
check: () => this.checkCommand(this.configPython)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
before: () => {
|
||||||
|
if (!this.env.PYTHON) {
|
||||||
|
this.addLog('Python is not set from environment variable ' +
|
||||||
|
'PYTHON')
|
||||||
|
return SKIP
|
||||||
|
}
|
||||||
|
this.addLog('checking Python explicitly set from environment ' +
|
||||||
|
'variable PYTHON')
|
||||||
|
this.addLog(`- process.env.PYTHON is "${this.env.PYTHON}"`)
|
||||||
|
},
|
||||||
|
check: () => this.checkCommand(this.env.PYTHON)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (this.win) {
|
||||||
|
checks.push({
|
||||||
|
before: () => {
|
||||||
|
this.addLog(
|
||||||
|
'checking if the py launcher can be used to find Python 3')
|
||||||
|
},
|
||||||
|
check: () => this.checkPyLauncher()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
checks.push(...[
|
||||||
|
{
|
||||||
|
before: () => { this.addLog('checking if "python3" can be used') },
|
||||||
|
check: () => this.checkCommand('python3')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
before: () => { this.addLog('checking if "python" can be used') },
|
||||||
|
check: () => this.checkCommand('python')
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
if (this.win) {
|
||||||
|
for (let i = 0; i < this.winDefaultLocations.length; ++i) {
|
||||||
|
const location = this.winDefaultLocations[i]
|
||||||
|
checks.push({
|
||||||
|
before: () => this.addLog(`checking if Python is ${location}`),
|
||||||
|
check: () => this.checkExecPath(location)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return checks
|
||||||
|
})()
|
||||||
|
|
||||||
|
for (const check of toCheck) {
|
||||||
|
const before = check.before()
|
||||||
|
if (before === SKIP) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (before === FAIL) {
|
||||||
|
return this.fail()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return await check.check()
|
||||||
|
} catch (err) {
|
||||||
|
this.log.silly('runChecks: err = %j', (err && err.stack) || err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if command is a valid Python to use.
|
||||||
|
// Will exit the Python finder on success.
|
||||||
|
// If on Windows, run in a CMD shell to support BAT/CMD launchers.
|
||||||
|
async checkCommand (command) {
|
||||||
|
let exec = command
|
||||||
|
let args = this.argsExecutable
|
||||||
|
let shell = false
|
||||||
|
if (this.win) {
|
||||||
|
// Arguments have to be manually quoted
|
||||||
|
exec = `"${exec}"`
|
||||||
|
args = args.map(a => `"${a}"`)
|
||||||
|
shell = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.verbose(`- executing "${command}" to get executable path`)
|
||||||
|
// Possible outcomes:
|
||||||
|
// - Error: not in PATH, not executable or execution fails
|
||||||
|
// - Gibberish: the next command to check version will fail
|
||||||
|
// - Absolute path to executable
|
||||||
|
try {
|
||||||
|
const execPath = await this.run(exec, args, shell)
|
||||||
|
this.addLog(`- executable path is "${execPath}"`)
|
||||||
|
return this.checkExecPath(execPath)
|
||||||
|
} catch (err) {
|
||||||
|
this.addLog(`- "${command}" is not in PATH or produced an error`)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the py launcher can find a valid Python to use.
|
||||||
|
// Will exit the Python finder on success.
|
||||||
|
// Distributions of Python on Windows by default install with the "py.exe"
|
||||||
|
// Python launcher which is more likely to exist than the Python executable
|
||||||
|
// being in the $PATH.
|
||||||
|
// Because the Python launcher supports Python 2 and Python 3, we should
|
||||||
|
// explicitly request a Python 3 version. This is done by supplying "-3" as
|
||||||
|
// the first command line argument. Since "py.exe -3" would be an invalid
|
||||||
|
// executable for "execFile", we have to use the launcher to figure out
|
||||||
|
// where the actual "python.exe" executable is located.
|
||||||
|
async checkPyLauncher () {
|
||||||
|
this.log.verbose(`- executing "${this.pyLauncher}" to get Python 3 executable path`)
|
||||||
|
// Possible outcomes: same as checkCommand
|
||||||
|
try {
|
||||||
|
const execPath = await this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false)
|
||||||
|
this.addLog(`- executable path is "${execPath}"`)
|
||||||
|
return this.checkExecPath(execPath)
|
||||||
|
} catch (err) {
|
||||||
|
this.addLog(`- "${this.pyLauncher}" is not in PATH or produced an error`)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a Python executable is the correct version to use.
|
||||||
|
// Will exit the Python finder on success.
|
||||||
|
async checkExecPath (execPath) {
|
||||||
|
this.log.verbose(`- executing "${execPath}" to get version`)
|
||||||
|
// Possible outcomes:
|
||||||
|
// - Error: executable can not be run (likely meaning the command wasn't
|
||||||
|
// a Python executable and the previous command produced gibberish)
|
||||||
|
// - Gibberish: somehow the last command produced an executable path,
|
||||||
|
// this will fail when verifying the version
|
||||||
|
// - Version of the Python executable
|
||||||
|
try {
|
||||||
|
const version = await this.run(execPath, this.argsVersion, false)
|
||||||
|
this.addLog(`- version is "${version}"`)
|
||||||
|
|
||||||
|
const range = new semver.Range(this.semverRange)
|
||||||
|
let valid = false
|
||||||
|
try {
|
||||||
|
valid = range.test(version)
|
||||||
|
} catch (err) {
|
||||||
|
this.log.silly('range.test() threw:\n%s', err.stack)
|
||||||
|
this.addLog(`- "${execPath}" does not have a valid version`)
|
||||||
|
this.addLog('- is it a Python executable?')
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
this.addLog(`- version is ${version} - should be ${this.semverRange}`)
|
||||||
|
this.addLog('- THIS VERSION OF PYTHON IS NOT SUPPORTED')
|
||||||
|
throw new Error(`Found unsupported Python version ${version}`)
|
||||||
|
}
|
||||||
|
return this.succeed(execPath, version)
|
||||||
|
} catch (err) {
|
||||||
|
this.addLog(`- "${execPath}" could not be run`)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run an executable or shell command, trimming the output.
|
||||||
|
async run (exec, args, shell) {
|
||||||
|
const env = Object.assign({}, this.env)
|
||||||
|
env.TERM = 'dumb'
|
||||||
|
const opts = { env, shell }
|
||||||
|
|
||||||
|
this.log.silly('execFile: exec = %j', exec)
|
||||||
|
this.log.silly('execFile: args = %j', args)
|
||||||
|
this.log.silly('execFile: opts = %j', opts)
|
||||||
|
try {
|
||||||
|
const [err, stdout, stderr] = await this.execFile(exec, args, opts)
|
||||||
|
this.log.silly('execFile result: err = %j', (err && err.stack) || err)
|
||||||
|
this.log.silly('execFile result: stdout = %j', stdout)
|
||||||
|
this.log.silly('execFile result: stderr = %j', stderr)
|
||||||
|
return stdout.trim()
|
||||||
|
} catch (err) {
|
||||||
|
this.log.silly('execFile: threw:\n%s', err.stack)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
succeed (execPath, version) {
|
||||||
|
this.log.info(`using Python version ${version} found at "${execPath}"`)
|
||||||
|
return execPath
|
||||||
|
}
|
||||||
|
|
||||||
|
fail () {
|
||||||
|
const errorLog = this.errorLog.join('\n')
|
||||||
|
|
||||||
|
const pathExample = this.win
|
||||||
|
? 'C:\\Path\\To\\python.exe'
|
||||||
|
: '/path/to/pythonexecutable'
|
||||||
|
// For Windows 80 col console, use up to the column before the one marked
|
||||||
|
// with X (total 79 chars including logger prefix, 58 chars usable here):
|
||||||
|
// X
|
||||||
|
const info = [
|
||||||
|
'**********************************************************',
|
||||||
|
'You need to install the latest version of Python.',
|
||||||
|
'Node-gyp should be able to find and use Python. If not,',
|
||||||
|
'you can try one of the following options:',
|
||||||
|
`- Use the switch --python="${pathExample}"`,
|
||||||
|
' (accepted by both node-gyp and npm)',
|
||||||
|
'- Set the environment variable PYTHON',
|
||||||
|
'For more information consult the documentation at:',
|
||||||
|
'https://github.com/nodejs/node-gyp#installation',
|
||||||
|
'**********************************************************'
|
||||||
|
].join('\n')
|
||||||
|
|
||||||
|
this.log.error(`\n${errorLog}\n\n${info}\n`)
|
||||||
|
throw new Error('Could not find any Python installation to use')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = PythonFinder
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('isSymbol', require('../isSymbol'), require('./_falseOptions'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
export {};
|
||||||
|
|
||||||
|
import { webcrypto } from "crypto";
|
||||||
|
|
||||||
|
type _Crypto = typeof globalThis extends { onmessage: any } ? {} : webcrypto.Crypto;
|
||||||
|
type _CryptoKey = typeof globalThis extends { onmessage: any } ? {} : webcrypto.CryptoKey;
|
||||||
|
type _SubtleCrypto = typeof globalThis extends { onmessage: any } ? {} : webcrypto.SubtleCrypto;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Crypto extends _Crypto {}
|
||||||
|
var Crypto: typeof globalThis extends { onmessage: any; Crypto: infer T } ? T : {
|
||||||
|
prototype: webcrypto.Crypto;
|
||||||
|
new(): webcrypto.Crypto;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface CryptoKey extends _CryptoKey {}
|
||||||
|
var CryptoKey: typeof globalThis extends { onmessage: any; CryptoKey: infer T } ? T : {
|
||||||
|
prototype: webcrypto.CryptoKey;
|
||||||
|
new(): webcrypto.CryptoKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SubtleCrypto extends _SubtleCrypto {}
|
||||||
|
var SubtleCrypto: typeof globalThis extends { onmessage: any; SubtleCrypto: infer T } ? T : {
|
||||||
|
prototype: webcrypto.SubtleCrypto;
|
||||||
|
new(): webcrypto.SubtleCrypto;
|
||||||
|
supports(
|
||||||
|
operation: string,
|
||||||
|
algorithm: webcrypto.AlgorithmIdentifier,
|
||||||
|
length?: number,
|
||||||
|
): boolean;
|
||||||
|
supports(
|
||||||
|
operation: string,
|
||||||
|
algorithm: webcrypto.AlgorithmIdentifier,
|
||||||
|
additionalAlgorithm: webcrypto.AlgorithmIdentifier,
|
||||||
|
): boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
var crypto: typeof globalThis extends { onmessage: any; crypto: infer T } ? T : webcrypto.Crypto;
|
||||||
|
}
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
.TH "NPM-DOCTOR" "1" "March 2026" "NPM@11.12.0" ""
|
||||||
|
.SH "NAME"
|
||||||
|
\fBnpm-doctor\fR - Check the health of your npm environment
|
||||||
|
.SS "Synopsis"
|
||||||
|
.P
|
||||||
|
.RS 2
|
||||||
|
.nf
|
||||||
|
npm doctor \[lB]connection\[rB] \[lB]registry\[rB] \[lB]versions\[rB] \[lB]environment\[rB] \[lB]permissions\[rB] \[lB]cache\[rB]
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
.P
|
||||||
|
Note: This command is unaware of workspaces.
|
||||||
|
.SS "Description"
|
||||||
|
.P
|
||||||
|
\fBnpm doctor\fR runs a set of checks to ensure that your npm installation has what it needs to manage your JavaScript packages. npm is mostly a standalone tool, but it does have some basic requirements that must be met:
|
||||||
|
.RS 0
|
||||||
|
.IP \(bu 4
|
||||||
|
Node.js and git must be executable by npm.
|
||||||
|
.IP \(bu 4
|
||||||
|
The primary npm registry, \fBregistry.npmjs.com\fR, or another service that uses the registry API, is available.
|
||||||
|
.IP \(bu 4
|
||||||
|
The directories that npm uses, \fBnode_modules\fR (both locally and globally), exist and can be written by the current user.
|
||||||
|
.IP \(bu 4
|
||||||
|
The npm cache exists, and the package tarballs within it aren't corrupt.
|
||||||
|
.RE 0
|
||||||
|
|
||||||
|
.P
|
||||||
|
Without all of these working properly, npm may not work properly. Many issues are often attributable to things that are outside npm's code base, so \fBnpm doctor\fR confirms that the npm installation is in a good state.
|
||||||
|
.P
|
||||||
|
Also, in addition to this, there are also very many issue reports due to using old versions of npm. Since npm is constantly improving, running \fBnpm@latest\fR is better than an old version.
|
||||||
|
.P
|
||||||
|
\fBnpm doctor\fR verifies the following items in your environment, and if there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments.
|
||||||
|
.SS "\fBConnecting to the registry\fR"
|
||||||
|
.P
|
||||||
|
By default, npm installs from the primary npm registry, \fBregistry.npmjs.org\fR. \fBnpm doctor\fR hits a special connection testing endpoint within the registry. This can also be checked with \fBnpm ping\fR. If this check fails, you may be using a proxy that needs to be configured, or may need to talk to your IT staff to get access over HTTPS to \fBregistry.npmjs.org\fR.
|
||||||
|
.P
|
||||||
|
This check is done against whichever registry you've configured (you can see what that is by running \fBnpm config get registry\fR), and if you're using a private registry that doesn't support the \fB/whoami\fR endpoint supported by the primary registry, this check may fail.
|
||||||
|
.SS "\fBChecking npm version\fR"
|
||||||
|
.P
|
||||||
|
While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run \fBnpm@latest\fR if they can. As the CLI is maintained by a small team of contributors, there are only resources for a single line of development, so npm's own long-term support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm.
|
||||||
|
.SS "\fBChecking node version\fR"
|
||||||
|
.P
|
||||||
|
For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new ECMAscript features or bleeding-edge changes to Node's standard library may be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS.
|
||||||
|
.SS "\fBChecking configured npm registry\fR"
|
||||||
|
.P
|
||||||
|
You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow questions in an effort to troubleshoot problems you may be having. Sometimes, this may entail changing the registry you're pointing at. This part of \fBnpm doctor\fR just lets you, and maybe whoever's helping you with support, know that you're not using the default registry.
|
||||||
|
.SS "\fBChecking for git executable in PATH\fR"
|
||||||
|
.P
|
||||||
|
While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases \[en] especially on Windows \[en] you may have Git set up in such a way that it's not accessible via your \fBPATH\fR so that npm can find it. This check ensures that Git is available.
|
||||||
|
.SS "Permissions checks"
|
||||||
|
.RS 0
|
||||||
|
.IP \(bu 4
|
||||||
|
Your cache must be readable and writable by the user running npm.
|
||||||
|
.IP \(bu 4
|
||||||
|
Global package binaries must be writable by the user running npm.
|
||||||
|
.IP \(bu 4
|
||||||
|
Your local \fBnode_modules\fR path, if you're running \fBnpm doctor\fR with a project directory, must be readable and writable by the user running npm.
|
||||||
|
.RE 0
|
||||||
|
|
||||||
|
.SS "Validate the checksums of cached packages"
|
||||||
|
.P
|
||||||
|
When an npm package is published, the publishing process generates a checksum that npm uses at install time to verify that the package didn't get corrupted in transit. \fBnpm doctor\fR uses these checksums to validate the package tarballs in your local cache (you can see where that cache is located with \fBnpm config get cache\fR). In the event that there are corrupt packages in your cache, you should probably run \fBnpm cache clean -f\fR and reset the cache.
|
||||||
|
.SS "Configuration"
|
||||||
|
.SS "\fBregistry\fR"
|
||||||
|
.RS 0
|
||||||
|
.IP \(bu 4
|
||||||
|
Default: "https://registry.npmjs.org/"
|
||||||
|
.IP \(bu 4
|
||||||
|
Type: URL
|
||||||
|
.RE 0
|
||||||
|
|
||||||
|
.P
|
||||||
|
The base URL of the npm registry.
|
||||||
|
.SS "See Also"
|
||||||
|
.RS 0
|
||||||
|
.IP \(bu 4
|
||||||
|
npm help bugs
|
||||||
|
.IP \(bu 4
|
||||||
|
npm help help
|
||||||
|
.IP \(bu 4
|
||||||
|
npm help ping
|
||||||
|
.RE 0
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
# resolve-from [](https://travis-ci.org/sindresorhus/resolve-from)
|
||||||
|
|
||||||
|
> Resolve the path of a module like [`require.resolve()`](https://nodejs.org/api/globals.html#globals_require_resolve) but from a given path
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install resolve-from
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const resolveFrom = require('resolve-from');
|
||||||
|
|
||||||
|
// There is a file at `./foo/bar.js`
|
||||||
|
|
||||||
|
resolveFrom('foo', './bar');
|
||||||
|
//=> '/Users/sindresorhus/dev/test/foo/bar.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### resolveFrom(fromDirectory, moduleId)
|
||||||
|
|
||||||
|
Like `require()`, throws when the module can't be found.
|
||||||
|
|
||||||
|
### resolveFrom.silent(fromDirectory, moduleId)
|
||||||
|
|
||||||
|
Returns `undefined` instead of throwing when the module can't be found.
|
||||||
|
|
||||||
|
#### fromDirectory
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Directory to resolve from.
|
||||||
|
|
||||||
|
#### moduleId
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
What you would use in `require()`.
|
||||||
|
|
||||||
|
|
||||||
|
## Tip
|
||||||
|
|
||||||
|
Create a partial using a bound function if you want to resolve from the same `fromDirectory` multiple times:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const resolveFromFoo = resolveFrom.bind(null, 'foo');
|
||||||
|
|
||||||
|
resolveFromFoo('./bar');
|
||||||
|
resolveFromFoo('./baz');
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [resolve-cwd](https://github.com/sindresorhus/resolve-cwd) - Resolve the path of a module from the current working directory
|
||||||
|
- [import-from](https://github.com/sindresorhus/import-from) - Import a module from a given path
|
||||||
|
- [import-cwd](https://github.com/sindresorhus/import-cwd) - Import a module from the current working directory
|
||||||
|
- [resolve-pkg](https://github.com/sindresorhus/resolve-pkg) - Resolve the path of a package regardless of it having an entry point
|
||||||
|
- [import-lazy](https://github.com/sindresorhus/import-lazy) - Import a module lazily
|
||||||
|
- [resolve-global](https://github.com/sindresorhus/resolve-global) - Resolve the path of a globally installed module
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||||
+343
@@ -0,0 +1,343 @@
|
|||||||
|
const cacache = require('cacache')
|
||||||
|
const { access, lstat, readdir, constants: { R_OK, W_OK, X_OK } } = require('node:fs/promises')
|
||||||
|
const npmFetch = require('make-fetch-happen')
|
||||||
|
const which = require('which')
|
||||||
|
const pacote = require('pacote')
|
||||||
|
const { resolve } = require('node:path')
|
||||||
|
const semver = require('semver')
|
||||||
|
const { log, output } = require('proc-log')
|
||||||
|
const ping = require('../utils/ping.js')
|
||||||
|
const { defaults } = require('@npmcli/config/lib/definitions')
|
||||||
|
const BaseCommand = require('../base-cmd.js')
|
||||||
|
|
||||||
|
const maskLabel = mask => {
|
||||||
|
const label = []
|
||||||
|
if (mask & R_OK) {
|
||||||
|
label.push('readable')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & W_OK) {
|
||||||
|
label.push('writable')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & X_OK) {
|
||||||
|
label.push('executable')
|
||||||
|
}
|
||||||
|
|
||||||
|
return label.join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
const checks = [
|
||||||
|
{
|
||||||
|
// Ping is left in as a legacy command but is listed as "connection" to make more sense to more people
|
||||||
|
groups: ['connection', 'ping', 'registry'],
|
||||||
|
title: 'Connecting to the registry',
|
||||||
|
cmd: 'checkPing',
|
||||||
|
}, {
|
||||||
|
groups: ['versions'],
|
||||||
|
title: 'Checking npm version',
|
||||||
|
cmd: 'getLatestNpmVersion',
|
||||||
|
}, {
|
||||||
|
groups: ['versions'],
|
||||||
|
title: 'Checking node version',
|
||||||
|
cmd: 'getLatestNodejsVersion',
|
||||||
|
}, {
|
||||||
|
groups: ['registry'],
|
||||||
|
title: 'Checking configured npm registry',
|
||||||
|
cmd: 'checkNpmRegistry',
|
||||||
|
}, {
|
||||||
|
groups: ['environment'],
|
||||||
|
title: 'Checking for git executable in PATH',
|
||||||
|
cmd: 'getGitPath',
|
||||||
|
}, {
|
||||||
|
groups: ['environment'],
|
||||||
|
title: 'Checking for global bin folder in PATH',
|
||||||
|
cmd: 'getBinPath',
|
||||||
|
}, {
|
||||||
|
groups: ['permissions', 'cache'],
|
||||||
|
title: 'Checking permissions on cached files (this may take awhile)',
|
||||||
|
cmd: 'checkCachePermission',
|
||||||
|
windows: false,
|
||||||
|
}, {
|
||||||
|
groups: ['permissions'],
|
||||||
|
title: 'Checking permissions on local node_modules (this may take awhile)',
|
||||||
|
cmd: 'checkLocalModulesPermission',
|
||||||
|
windows: false,
|
||||||
|
}, {
|
||||||
|
groups: ['permissions'],
|
||||||
|
title: 'Checking permissions on global node_modules (this may take awhile)',
|
||||||
|
cmd: 'checkGlobalModulesPermission',
|
||||||
|
windows: false,
|
||||||
|
}, {
|
||||||
|
groups: ['permissions'],
|
||||||
|
title: 'Checking permissions on local bin folder',
|
||||||
|
cmd: 'checkLocalBinPermission',
|
||||||
|
windows: false,
|
||||||
|
}, {
|
||||||
|
groups: ['permissions'],
|
||||||
|
title: 'Checking permissions on global bin folder',
|
||||||
|
cmd: 'checkGlobalBinPermission',
|
||||||
|
windows: false,
|
||||||
|
}, {
|
||||||
|
groups: ['cache'],
|
||||||
|
title: 'Verifying cache contents (this may take awhile)',
|
||||||
|
cmd: 'verifyCachedFiles',
|
||||||
|
windows: false,
|
||||||
|
},
|
||||||
|
// TODO:
|
||||||
|
// group === 'dependencies'?
|
||||||
|
// - ensure arborist.loadActual() runs without errors and no invalid edges
|
||||||
|
// - ensure package-lock.json matches loadActual()
|
||||||
|
// - verify loadActual without hidden lock file matches hidden lockfile
|
||||||
|
// group === '???'
|
||||||
|
// - verify all local packages have bins linked
|
||||||
|
// What is the fix for these?
|
||||||
|
]
|
||||||
|
|
||||||
|
class Doctor extends BaseCommand {
|
||||||
|
static description = 'Check the health of your npm environment'
|
||||||
|
static name = 'doctor'
|
||||||
|
static params = ['registry']
|
||||||
|
static ignoreImplicitWorkspace = false
|
||||||
|
static usage = [`[${checks.flatMap(s => s.groups)
|
||||||
|
.filter((value, index, self) => self.indexOf(value) === index && value !== 'ping')
|
||||||
|
.join('] [')}]`]
|
||||||
|
|
||||||
|
async exec (args) {
|
||||||
|
log.info('doctor', 'Running checkup')
|
||||||
|
let allOk = true
|
||||||
|
|
||||||
|
const actions = this.actions(args)
|
||||||
|
|
||||||
|
const chalk = this.npm.chalk
|
||||||
|
for (const { title, cmd } of actions) {
|
||||||
|
this.output(title)
|
||||||
|
// TODO when we have an in progress indicator that could go here
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
result = await this[cmd]()
|
||||||
|
this.output(`${chalk.green('Ok')}${result ? `\n${result}` : ''}\n`)
|
||||||
|
} catch (err) {
|
||||||
|
allOk = false
|
||||||
|
this.output(`${chalk.red('Not ok')}\n${chalk.cyan(err)}\n`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allOk) {
|
||||||
|
if (this.npm.silent) {
|
||||||
|
throw new Error('Some problems found. Check logs or disable silent mode for recommendations.')
|
||||||
|
} else {
|
||||||
|
throw new Error('Some problems found. See above for recommendations.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkPing () {
|
||||||
|
log.info('doctor', 'Pinging registry')
|
||||||
|
try {
|
||||||
|
await ping({ ...this.npm.flatOptions, retry: false })
|
||||||
|
return ''
|
||||||
|
} catch (er) {
|
||||||
|
if (/^E\d{3}$/.test(er.code || '')) {
|
||||||
|
throw er.code.slice(1) + ' ' + er.message
|
||||||
|
} else {
|
||||||
|
throw er.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLatestNpmVersion () {
|
||||||
|
log.info('doctor', 'Getting npm package information')
|
||||||
|
const latest = (await pacote.manifest('npm@latest', this.npm.flatOptions)).version
|
||||||
|
if (semver.gte(this.npm.version, latest)) {
|
||||||
|
return `current: v${this.npm.version}, latest: v${latest}`
|
||||||
|
} else {
|
||||||
|
throw `Use npm v${latest}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLatestNodejsVersion () {
|
||||||
|
// XXX get the latest in the current major as well
|
||||||
|
const current = process.version
|
||||||
|
const currentRange = `^${current}`
|
||||||
|
const url = 'https://nodejs.org/dist/index.json'
|
||||||
|
log.info('doctor', 'Getting Node.js release information')
|
||||||
|
const res = await npmFetch(url, { method: 'GET', ...this.npm.flatOptions })
|
||||||
|
const data = await res.json()
|
||||||
|
let maxCurrent = '0.0.0'
|
||||||
|
let maxLTS = '0.0.0'
|
||||||
|
for (const { lts, version } of data) {
|
||||||
|
if (lts && semver.gt(version, maxLTS)) {
|
||||||
|
maxLTS = version
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) {
|
||||||
|
maxCurrent = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS
|
||||||
|
if (semver.gte(process.version, recommended)) {
|
||||||
|
return `current: ${current}, recommended: ${recommended}`
|
||||||
|
} else {
|
||||||
|
throw `Use node ${recommended} (current: ${current})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getBinPath () {
|
||||||
|
log.info('doctor', 'getBinPath', 'Finding npm global bin in your PATH')
|
||||||
|
if (!process.env.PATH.includes(this.npm.globalBin)) {
|
||||||
|
throw new Error(`Add ${this.npm.globalBin} to your $PATH`)
|
||||||
|
}
|
||||||
|
return this.npm.globalBin
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkCachePermission () {
|
||||||
|
return this.checkFilesPermission(this.npm.cache, true, R_OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkLocalModulesPermission () {
|
||||||
|
return this.checkFilesPermission(this.npm.localDir, true, R_OK | W_OK, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkGlobalModulesPermission () {
|
||||||
|
return this.checkFilesPermission(this.npm.globalDir, false, R_OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkLocalBinPermission () {
|
||||||
|
return this.checkFilesPermission(this.npm.localBin, false, R_OK | W_OK | X_OK, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkGlobalBinPermission () {
|
||||||
|
return this.checkFilesPermission(this.npm.globalBin, false, X_OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkFilesPermission (root, shouldOwn, mask, missingOk) {
|
||||||
|
let ok = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const uid = process.getuid()
|
||||||
|
const gid = process.getgid()
|
||||||
|
const files = new Set([root])
|
||||||
|
for (const f of files) {
|
||||||
|
const st = await lstat(f).catch(er => {
|
||||||
|
// if it can't be missing, or if it can and the error wasn't that it was missing
|
||||||
|
if (!missingOk || er.code !== 'ENOENT') {
|
||||||
|
ok = false
|
||||||
|
log.warn('doctor', 'checkFilesPermission', 'error getting info for ' + f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!st) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldOwn && (uid !== st.uid || gid !== st.gid)) {
|
||||||
|
log.warn('doctor', 'checkFilesPermission', 'should be owner of ' + f)
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!st.isDirectory() && !st.isFile()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await access(f, mask)
|
||||||
|
} catch {
|
||||||
|
ok = false
|
||||||
|
const msg = `Missing permissions on ${f} (expect: ${maskLabel(mask)})`
|
||||||
|
log.error('doctor', 'checkFilesPermission', msg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.isDirectory()) {
|
||||||
|
const entries = await readdir(f).catch(() => {
|
||||||
|
ok = false
|
||||||
|
log.warn('doctor', 'checkFilesPermission', 'error reading directory ' + f)
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
for (const entry of entries) {
|
||||||
|
files.add(resolve(f, entry))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (!ok) {
|
||||||
|
throw (
|
||||||
|
`Check the permissions of files in ${root}` +
|
||||||
|
(shouldOwn ? ' (should be owned by current user)' : '')
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGitPath () {
|
||||||
|
log.info('doctor', 'Finding git in your PATH')
|
||||||
|
return await which('git').catch(er => {
|
||||||
|
log.warn('doctor', 'getGitPath', er)
|
||||||
|
throw new Error("Install git and ensure it's in your PATH.")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifyCachedFiles () {
|
||||||
|
log.info('doctor', 'verifyCachedFiles', 'Verifying the npm cache')
|
||||||
|
|
||||||
|
const stats = await cacache.verify(this.npm.flatOptions.cache)
|
||||||
|
const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats
|
||||||
|
if (badContentCount || reclaimedCount || missingContent) {
|
||||||
|
if (badContentCount) {
|
||||||
|
log.warn('doctor', 'verifyCachedFiles', `Corrupted content removed: ${badContentCount}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reclaimedCount) {
|
||||||
|
log.warn(
|
||||||
|
'doctor',
|
||||||
|
'verifyCachedFiles',
|
||||||
|
`Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingContent) {
|
||||||
|
log.warn('doctor', 'verifyCachedFiles', `Missing content: ${missingContent}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn('doctor', 'verifyCachedFiles', 'Cache issues have been fixed')
|
||||||
|
}
|
||||||
|
log.info(
|
||||||
|
'doctor',
|
||||||
|
'verifyCachedFiles',
|
||||||
|
`Verification complete. Stats: ${JSON.stringify(stats, null, 2)}`
|
||||||
|
)
|
||||||
|
return `verified ${stats.verifiedContent} tarballs`
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkNpmRegistry () {
|
||||||
|
if (this.npm.flatOptions.registry !== defaults.registry) {
|
||||||
|
throw `Try \`npm config set registry=${defaults.registry}\``
|
||||||
|
} else {
|
||||||
|
return `using default registry (${defaults.registry})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output (...args) {
|
||||||
|
// TODO display layer should do this
|
||||||
|
if (!this.npm.silent) {
|
||||||
|
output.standard(...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions (params) {
|
||||||
|
return checks.filter(subcmd => {
|
||||||
|
if (process.platform === 'win32' && subcmd.windows === false) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (params.length) {
|
||||||
|
return params.some(param => subcmd.groups.includes(param))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Doctor
|
||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { kConstruct } = require('./symbols')
|
||||||
|
const { Cache } = require('./cache')
|
||||||
|
const { webidl } = require('../fetch/webidl')
|
||||||
|
const { kEnumerableProperty } = require('../../core/util')
|
||||||
|
|
||||||
|
class CacheStorage {
|
||||||
|
/**
|
||||||
|
* @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map
|
||||||
|
* @type {Map<string, import('./cache').requestResponseList}
|
||||||
|
*/
|
||||||
|
#caches = new Map()
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
if (arguments[0] !== kConstruct) {
|
||||||
|
webidl.illegalConstructor()
|
||||||
|
}
|
||||||
|
|
||||||
|
webidl.util.markAsUncloneable(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async match (request, options = {}) {
|
||||||
|
webidl.brandCheck(this, CacheStorage)
|
||||||
|
webidl.argumentLengthCheck(arguments, 1, 'CacheStorage.match')
|
||||||
|
|
||||||
|
request = webidl.converters.RequestInfo(request)
|
||||||
|
options = webidl.converters.MultiCacheQueryOptions(options)
|
||||||
|
|
||||||
|
// 1.
|
||||||
|
if (options.cacheName != null) {
|
||||||
|
// 1.1.1.1
|
||||||
|
if (this.#caches.has(options.cacheName)) {
|
||||||
|
// 1.1.1.1.1
|
||||||
|
const cacheList = this.#caches.get(options.cacheName)
|
||||||
|
const cache = new Cache(kConstruct, cacheList)
|
||||||
|
|
||||||
|
return await cache.match(request, options)
|
||||||
|
}
|
||||||
|
} else { // 2.
|
||||||
|
// 2.2
|
||||||
|
for (const cacheList of this.#caches.values()) {
|
||||||
|
const cache = new Cache(kConstruct, cacheList)
|
||||||
|
|
||||||
|
// 2.2.1.2
|
||||||
|
const response = await cache.match(request, options)
|
||||||
|
|
||||||
|
if (response !== undefined) {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-has
|
||||||
|
* @param {string} cacheName
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async has (cacheName) {
|
||||||
|
webidl.brandCheck(this, CacheStorage)
|
||||||
|
|
||||||
|
const prefix = 'CacheStorage.has'
|
||||||
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
||||||
|
|
||||||
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
||||||
|
|
||||||
|
// 2.1.1
|
||||||
|
// 2.2
|
||||||
|
return this.#caches.has(cacheName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open
|
||||||
|
* @param {string} cacheName
|
||||||
|
* @returns {Promise<Cache>}
|
||||||
|
*/
|
||||||
|
async open (cacheName) {
|
||||||
|
webidl.brandCheck(this, CacheStorage)
|
||||||
|
|
||||||
|
const prefix = 'CacheStorage.open'
|
||||||
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
||||||
|
|
||||||
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
||||||
|
|
||||||
|
// 2.1
|
||||||
|
if (this.#caches.has(cacheName)) {
|
||||||
|
// await caches.open('v1') !== await caches.open('v1')
|
||||||
|
|
||||||
|
// 2.1.1
|
||||||
|
const cache = this.#caches.get(cacheName)
|
||||||
|
|
||||||
|
// 2.1.1.1
|
||||||
|
return new Cache(kConstruct, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2
|
||||||
|
const cache = []
|
||||||
|
|
||||||
|
// 2.3
|
||||||
|
this.#caches.set(cacheName, cache)
|
||||||
|
|
||||||
|
// 2.4
|
||||||
|
return new Cache(kConstruct, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-delete
|
||||||
|
* @param {string} cacheName
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async delete (cacheName) {
|
||||||
|
webidl.brandCheck(this, CacheStorage)
|
||||||
|
|
||||||
|
const prefix = 'CacheStorage.delete'
|
||||||
|
webidl.argumentLengthCheck(arguments, 1, prefix)
|
||||||
|
|
||||||
|
cacheName = webidl.converters.DOMString(cacheName, prefix, 'cacheName')
|
||||||
|
|
||||||
|
return this.#caches.delete(cacheName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-keys
|
||||||
|
* @returns {Promise<string[]>}
|
||||||
|
*/
|
||||||
|
async keys () {
|
||||||
|
webidl.brandCheck(this, CacheStorage)
|
||||||
|
|
||||||
|
// 2.1
|
||||||
|
const keys = this.#caches.keys()
|
||||||
|
|
||||||
|
// 2.2
|
||||||
|
return [...keys]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperties(CacheStorage.prototype, {
|
||||||
|
[Symbol.toStringTag]: {
|
||||||
|
value: 'CacheStorage',
|
||||||
|
configurable: true
|
||||||
|
},
|
||||||
|
match: kEnumerableProperty,
|
||||||
|
has: kEnumerableProperty,
|
||||||
|
open: kEnumerableProperty,
|
||||||
|
delete: kEnumerableProperty,
|
||||||
|
keys: kEnumerableProperty
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
CacheStorage
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
const aliases = ['stdin', 'stdout', 'stderr'];
|
||||||
|
|
||||||
|
const hasAlias = options => aliases.some(alias => options[alias] !== undefined);
|
||||||
|
|
||||||
|
export const normalizeStdio = options => {
|
||||||
|
if (!options) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {stdio} = options;
|
||||||
|
|
||||||
|
if (stdio === undefined) {
|
||||||
|
return aliases.map(alias => options[alias]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAlias(options)) {
|
||||||
|
throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof stdio === 'string') {
|
||||||
|
return stdio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(stdio)) {
|
||||||
|
throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``);
|
||||||
|
}
|
||||||
|
|
||||||
|
const length = Math.max(stdio.length, aliases.length);
|
||||||
|
return Array.from({length}, (value, index) => stdio[index]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// `ipc` is pushed unless it is already present
|
||||||
|
export const normalizeStdioNode = options => {
|
||||||
|
const stdio = normalizeStdio(options);
|
||||||
|
|
||||||
|
if (stdio === 'ipc') {
|
||||||
|
return 'ipc';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdio === undefined || typeof stdio === 'string') {
|
||||||
|
return [stdio, stdio, stdio, 'ipc'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdio.includes('ipc')) {
|
||||||
|
return stdio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...stdio, 'ipc'];
|
||||||
|
};
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
# Interface: DispatchInterceptor
|
||||||
|
|
||||||
|
Extends: `Function`
|
||||||
|
|
||||||
|
A function that can be applied to the `Dispatcher.Dispatch` function before it is invoked with a dispatch request.
|
||||||
|
|
||||||
|
This allows one to write logic to intercept both the outgoing request, and the incoming response.
|
||||||
|
|
||||||
|
### Parameter: `Dispatcher.Dispatch`
|
||||||
|
|
||||||
|
The base dispatch function you are decorating.
|
||||||
|
|
||||||
|
### ReturnType: `Dispatcher.Dispatch`
|
||||||
|
|
||||||
|
A dispatch function that has been altered to provide additional logic
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
Here is an example of an interceptor being used to provide a JWT bearer token
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const insertHeaderInterceptor = dispatch => {
|
||||||
|
return function InterceptedDispatch(opts, handler){
|
||||||
|
opts.headers.push('Authorization', 'Bearer [Some token]')
|
||||||
|
return dispatch(opts, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client('https://localhost:3000', {
|
||||||
|
interceptors: { Client: [insertHeaderInterceptor] }
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Basic Example 2
|
||||||
|
|
||||||
|
Here is a contrived example of an interceptor stripping the headers from a response.
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const clearHeadersInterceptor = dispatch => {
|
||||||
|
const { DecoratorHandler } = require('undici')
|
||||||
|
class ResultInterceptor extends DecoratorHandler {
|
||||||
|
onHeaders (statusCode, headers, resume) {
|
||||||
|
return super.onHeaders(statusCode, [], resume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return function InterceptedDispatch(opts, handler){
|
||||||
|
return dispatch(opts, new ResultInterceptor(handler))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client('https://localhost:3000', {
|
||||||
|
interceptors: { Client: [clearHeadersInterceptor] }
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
+1
File diff suppressed because one or more lines are too long
+134
@@ -0,0 +1,134 @@
|
|||||||
|
# through2
|
||||||
|
|
||||||
|
[](https://nodei.co/npm/through2/)
|
||||||
|
|
||||||
|
**A tiny wrapper around Node streams.Transform (Streams2/3) to avoid explicit subclassing noise**
|
||||||
|
|
||||||
|
Inspired by [Dominic Tarr](https://github.com/dominictarr)'s [through](https://github.com/dominictarr/through) in that it's so much easier to make a stream out of a function than it is to set up the prototype chain properly: `through(function (chunk) { ... })`.
|
||||||
|
|
||||||
|
Note: As 2.x.x this module starts using **Streams3** instead of Stream2. To continue using a Streams2 version use `npm install through2@0` to fetch the latest version of 0.x.x. More information about Streams2 vs Streams3 and recommendations see the article **[Why I don't use Node's core 'stream' module](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html)**.
|
||||||
|
|
||||||
|
```js
|
||||||
|
fs.createReadStream('ex.txt')
|
||||||
|
.pipe(through2(function (chunk, enc, callback) {
|
||||||
|
for (var i = 0; i < chunk.length; i++)
|
||||||
|
if (chunk[i] == 97)
|
||||||
|
chunk[i] = 122 // swap 'a' for 'z'
|
||||||
|
|
||||||
|
this.push(chunk)
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}))
|
||||||
|
.pipe(fs.createWriteStream('out.txt'))
|
||||||
|
.on('finish', () => doSomethingSpecial())
|
||||||
|
```
|
||||||
|
|
||||||
|
Or object streams:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var all = []
|
||||||
|
|
||||||
|
fs.createReadStream('data.csv')
|
||||||
|
.pipe(csv2())
|
||||||
|
.pipe(through2.obj(function (chunk, enc, callback) {
|
||||||
|
var data = {
|
||||||
|
name : chunk[0]
|
||||||
|
, address : chunk[3]
|
||||||
|
, phone : chunk[10]
|
||||||
|
}
|
||||||
|
this.push(data)
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}))
|
||||||
|
.on('data', (data) => {
|
||||||
|
all.push(data)
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
doSomethingSpecial(all)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `through2.obj(fn)` is a convenience wrapper around `through2({ objectMode: true }, fn)`.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<b><code>through2([ options, ] [ transformFunction ] [, flushFunction ])</code></b>
|
||||||
|
|
||||||
|
Consult the **[stream.Transform](http://nodejs.org/docs/latest/api/stream.html#stream_class_stream_transform)** documentation for the exact rules of the `transformFunction` (i.e. `this._transform`) and the optional `flushFunction` (i.e. `this._flush`).
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
The options argument is optional and is passed straight through to `stream.Transform`. So you can use `objectMode:true` if you are processing non-binary streams (or just use `through2.obj()`).
|
||||||
|
|
||||||
|
The `options` argument is first, unlike standard convention, because if I'm passing in an anonymous function then I'd prefer for the options argument to not get lost at the end of the call:
|
||||||
|
|
||||||
|
```js
|
||||||
|
fs.createReadStream('/tmp/important.dat')
|
||||||
|
.pipe(through2({ objectMode: true, allowHalfOpen: false },
|
||||||
|
(chunk, enc, cb) => {
|
||||||
|
cb(null, 'wut?') // note we can use the second argument on the callback
|
||||||
|
// to provide data as an alternative to this.push('wut?')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.pipe(fs.createWriteStream('/tmp/wut.txt'))
|
||||||
|
```
|
||||||
|
|
||||||
|
### transformFunction
|
||||||
|
|
||||||
|
The `transformFunction` must have the following signature: `function (chunk, encoding, callback) {}`. A minimal implementation should call the `callback` function to indicate that the transformation is done, even if that transformation means discarding the chunk.
|
||||||
|
|
||||||
|
To queue a new chunk, call `this.push(chunk)`—this can be called as many times as required before the `callback()` if you have multiple pieces to send on.
|
||||||
|
|
||||||
|
Alternatively, you may use `callback(err, chunk)` as shorthand for emitting a single chunk or an error.
|
||||||
|
|
||||||
|
If you **do not provide a `transformFunction`** then you will get a simple pass-through stream.
|
||||||
|
|
||||||
|
### flushFunction
|
||||||
|
|
||||||
|
The optional `flushFunction` is provided as the last argument (2nd or 3rd, depending on whether you've supplied options) is called just prior to the stream ending. Can be used to finish up any processing that may be in progress.
|
||||||
|
|
||||||
|
```js
|
||||||
|
fs.createReadStream('/tmp/important.dat')
|
||||||
|
.pipe(through2(
|
||||||
|
(chunk, enc, cb) => cb(null, chunk), // transform is a noop
|
||||||
|
function (cb) { // flush function
|
||||||
|
this.push('tacking on an extra buffer to the end');
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.pipe(fs.createWriteStream('/tmp/wut.txt'));
|
||||||
|
```
|
||||||
|
|
||||||
|
<b><code>through2.ctor([ options, ] transformFunction[, flushFunction ])</code></b>
|
||||||
|
|
||||||
|
Instead of returning a `stream.Transform` instance, `through2.ctor()` returns a **constructor** for a custom Transform. This is useful when you want to use the same transform logic in multiple instances.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var FToC = through2.ctor({objectMode: true}, function (record, encoding, callback) {
|
||||||
|
if (record.temp != null && record.unit == "F") {
|
||||||
|
record.temp = ( ( record.temp - 32 ) * 5 ) / 9
|
||||||
|
record.unit = "C"
|
||||||
|
}
|
||||||
|
this.push(record)
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create instances of FToC like so:
|
||||||
|
var converter = new FToC()
|
||||||
|
// Or:
|
||||||
|
var converter = FToC()
|
||||||
|
// Or specify/override options when you instantiate, if you prefer:
|
||||||
|
var converter = FToC({objectMode: true})
|
||||||
|
```
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [through2-map](https://github.com/brycebaril/through2-map) - Array.prototype.map analog for streams.
|
||||||
|
- [through2-filter](https://github.com/brycebaril/through2-filter) - Array.prototype.filter analog for streams.
|
||||||
|
- [through2-reduce](https://github.com/brycebaril/through2-reduce) - Array.prototype.reduce analog for streams.
|
||||||
|
- [through2-spy](https://github.com/brycebaril/through2-spy) - Wrapper for simple stream.PassThrough spies.
|
||||||
|
- the [mississippi stream utility collection](https://github.com/maxogden/mississippi) includes `through2` as well as many more useful stream modules similar to this one
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
**through2** is Copyright (c) Rod Vagg [@rvagg](https://twitter.com/rvagg) and additional contributors and licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var through = require('through2');
|
||||||
|
var split = require('split2');
|
||||||
|
var traverse = require('traverse');
|
||||||
|
var fields = require('./fields');
|
||||||
|
var toArgv = require('argv-formatter').format;
|
||||||
|
var combine = require('stream-combiner2');
|
||||||
|
var fwd = require('spawn-error-forwarder');
|
||||||
|
|
||||||
|
var END = '==END==';
|
||||||
|
var FIELD = '==FIELD==';
|
||||||
|
|
||||||
|
function format (fieldMap) {
|
||||||
|
return fieldMap.map(function (field) {
|
||||||
|
return '%' + field.key;
|
||||||
|
})
|
||||||
|
.join(FIELD) + END;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim () {
|
||||||
|
return through(function (chunk, enc, callback) {
|
||||||
|
if (!chunk) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback(null, chunk);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function log (args, options) {
|
||||||
|
return fwd(spawn('git', ['log'].concat(args), options), function (code, stderr) {
|
||||||
|
return new Error('git log failed:\n\n' + stderr);
|
||||||
|
})
|
||||||
|
.stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function args (config, fieldMap) {
|
||||||
|
config.format = format(fieldMap);
|
||||||
|
return toArgv(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.parse = function parseLogStream (config, options) {
|
||||||
|
config = config || {};
|
||||||
|
var map = fields.map();
|
||||||
|
return combine.obj([
|
||||||
|
log(args(config, map), options),
|
||||||
|
split(END + '\n'),
|
||||||
|
trim(),
|
||||||
|
through.obj(function (chunk, enc, callback) {
|
||||||
|
var fields = chunk.toString('utf8').split(FIELD);
|
||||||
|
callback(null, map.reduce(function (parsed, field, index) {
|
||||||
|
var value = fields[index];
|
||||||
|
traverse(parsed).set(field.path, field.type ? new field.type(value) : value);
|
||||||
|
return parsed;
|
||||||
|
}, {}));
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.fields = fields.config;
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
import arrayEach from './_arrayEach.js';
|
||||||
|
import baseEach from './_baseEach.js';
|
||||||
|
import castFunction from './_castFunction.js';
|
||||||
|
import isArray from './isArray.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over elements of `collection` and invokes `iteratee` for each element.
|
||||||
|
* The iteratee is invoked with three arguments: (value, index|key, collection).
|
||||||
|
* Iteratee functions may exit iteration early by explicitly returning `false`.
|
||||||
|
*
|
||||||
|
* **Note:** As with other "Collections" methods, objects with a "length"
|
||||||
|
* property are iterated like arrays. To avoid this behavior use `_.forIn`
|
||||||
|
* or `_.forOwn` for object iteration.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 0.1.0
|
||||||
|
* @alias each
|
||||||
|
* @category Collection
|
||||||
|
* @param {Array|Object} collection The collection to iterate over.
|
||||||
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||||||
|
* @returns {Array|Object} Returns `collection`.
|
||||||
|
* @see _.forEachRight
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.forEach([1, 2], function(value) {
|
||||||
|
* console.log(value);
|
||||||
|
* });
|
||||||
|
* // => Logs `1` then `2`.
|
||||||
|
*
|
||||||
|
* _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
|
||||||
|
* console.log(key);
|
||||||
|
* });
|
||||||
|
* // => Logs 'a' then 'b' (iteration order is not guaranteed).
|
||||||
|
*/
|
||||||
|
function forEach(collection, iteratee) {
|
||||||
|
var func = isArray(collection) ? arrayEach : baseEach;
|
||||||
|
return func(collection, castFunction(iteratee));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default forEach;
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
# brace-expansion
|
||||||
|
|
||||||
|
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
|
||||||
|
as known from sh/bash, in JavaScript.
|
||||||
|
|
||||||
|
[](http://travis-ci.org/juliangruber/brace-expansion)
|
||||||
|
[](https://www.npmjs.org/package/brace-expansion)
|
||||||
|
[](https://greenkeeper.io/)
|
||||||
|
|
||||||
|
[](https://ci.testling.com/juliangruber/brace-expansion)
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
var expand = require('brace-expansion');
|
||||||
|
|
||||||
|
expand('file-{a,b,c}.jpg')
|
||||||
|
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
|
||||||
|
|
||||||
|
expand('-v{,,}')
|
||||||
|
// => ['-v', '-v', '-v']
|
||||||
|
|
||||||
|
expand('file{0..2}.jpg')
|
||||||
|
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
|
||||||
|
|
||||||
|
expand('file-{a..c}.jpg')
|
||||||
|
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
|
||||||
|
|
||||||
|
expand('file{2..0}.jpg')
|
||||||
|
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
|
||||||
|
|
||||||
|
expand('file{0..4..2}.jpg')
|
||||||
|
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
|
||||||
|
|
||||||
|
expand('file-{a..e..2}.jpg')
|
||||||
|
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
|
||||||
|
|
||||||
|
expand('file{00..10..5}.jpg')
|
||||||
|
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
|
||||||
|
|
||||||
|
expand('{{A..C},{a..c}}')
|
||||||
|
// => ['A', 'B', 'C', 'a', 'b', 'c']
|
||||||
|
|
||||||
|
expand('ppp{,config,oe{,conf}}')
|
||||||
|
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
var expand = require('brace-expansion');
|
||||||
|
```
|
||||||
|
|
||||||
|
### var expanded = expand(str)
|
||||||
|
|
||||||
|
Return an array of all possible and valid expansions of `str`. If none are
|
||||||
|
found, `[str]` is returned.
|
||||||
|
|
||||||
|
Valid expansions are:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/^(.*,)+(.+)?$/
|
||||||
|
// {a,b,...}
|
||||||
|
```
|
||||||
|
|
||||||
|
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
|
||||||
|
// {x..y[..incr]}
|
||||||
|
```
|
||||||
|
|
||||||
|
A numeric sequence from `x` to `y` inclusive, with optional increment.
|
||||||
|
If `x` or `y` start with a leading `0`, all the numbers will be padded
|
||||||
|
to have equal length. Negative numbers and backwards iteration work too.
|
||||||
|
|
||||||
|
```js
|
||||||
|
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
|
||||||
|
// {x..y[..incr]}
|
||||||
|
```
|
||||||
|
|
||||||
|
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
|
||||||
|
`x` and `y` must be exactly one character, and if given, `incr` must be a
|
||||||
|
number.
|
||||||
|
|
||||||
|
For compatibility reasons, the string `${` is not eligible for brace expansion.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
With [npm](https://npmjs.org) do:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install brace-expansion
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- [Julian Gruber](https://github.com/juliangruber)
|
||||||
|
- [Isaac Z. Schlueter](https://github.com/isaacs)
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
|
||||||
|
|
||||||
|
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
(MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var test = require('tape');
|
||||||
|
var traverse = require('../');
|
||||||
|
|
||||||
|
test('siblings', function (t) {
|
||||||
|
var obj = { a: 1, b: 2, c: [4, 5, 6] };
|
||||||
|
|
||||||
|
var res = traverse(obj).reduce(function (acc) {
|
||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
|
var p = '/' + this.path.join('/');
|
||||||
|
if (this.parent) {
|
||||||
|
acc[p] = {
|
||||||
|
siblings: this.parent.keys,
|
||||||
|
key: this.key,
|
||||||
|
index: this.parent.keys.indexOf(this.key),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
acc[p] = {
|
||||||
|
siblings: [],
|
||||||
|
key: this.key,
|
||||||
|
index: -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
t.same(res, {
|
||||||
|
'/': { siblings: [], key: undefined, index: -1 },
|
||||||
|
'/a': { siblings: ['a', 'b', 'c'], key: 'a', index: 0 },
|
||||||
|
'/b': { siblings: ['a', 'b', 'c'], key: 'b', index: 1 },
|
||||||
|
'/c': { siblings: ['a', 'b', 'c'], key: 'c', index: 2 },
|
||||||
|
'/c/0': { siblings: ['0', '1', '2'], key: '0', index: 0 },
|
||||||
|
'/c/1': { siblings: ['0', '1', '2'], key: '1', index: 1 },
|
||||||
|
'/c/2': { siblings: ['0', '1', '2'], key: '2', index: 2 },
|
||||||
|
});
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// on windows, either \ or / are valid directory separators.
|
||||||
|
// on unix, \ is a valid character in filenames.
|
||||||
|
// so, on windows, and only on windows, we replace all \ chars with /,
|
||||||
|
// so that we can use / as our one and only directory separator char.
|
||||||
|
const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
||||||
|
export const normalizeWindowsPath = platform !== 'win32' ?
|
||||||
|
(p) => p
|
||||||
|
: (p) => p && p.replace(/\\/g, '/');
|
||||||
|
//# sourceMappingURL=normalize-windows-path.js.map
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* The `node:test` module supports passing `--test-reporter`
|
||||||
|
* flags for the test runner to use a specific reporter.
|
||||||
|
*
|
||||||
|
* The following built-reporters are supported:
|
||||||
|
*
|
||||||
|
* * `spec`
|
||||||
|
* The `spec` reporter outputs the test results in a human-readable format. This
|
||||||
|
* is the default reporter.
|
||||||
|
*
|
||||||
|
* * `tap`
|
||||||
|
* The `tap` reporter outputs the test results in the [TAP](https://testanything.org/) format.
|
||||||
|
*
|
||||||
|
* * `dot`
|
||||||
|
* The `dot` reporter outputs the test results in a compact format,
|
||||||
|
* where each passing test is represented by a `.`,
|
||||||
|
* and each failing test is represented by a `X`.
|
||||||
|
*
|
||||||
|
* * `junit`
|
||||||
|
* The junit reporter outputs test results in a jUnit XML format
|
||||||
|
*
|
||||||
|
* * `lcov`
|
||||||
|
* The `lcov` reporter outputs test coverage when used with the
|
||||||
|
* `--experimental-test-coverage` flag.
|
||||||
|
*
|
||||||
|
* The exact output of these reporters is subject to change between versions of
|
||||||
|
* Node.js, and should not be relied on programmatically. If programmatic access
|
||||||
|
* to the test runner's output is required, use the events emitted by the
|
||||||
|
* `TestsStream`.
|
||||||
|
*
|
||||||
|
* The reporters are available via the `node:test/reporters` module:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0, v18.17.0
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v25.x/lib/test/reporters.js)
|
||||||
|
*/
|
||||||
|
declare module "node:test/reporters" {
|
||||||
|
import { Transform, TransformOptions } from "node:stream";
|
||||||
|
import { EventData } from "node:test";
|
||||||
|
type TestEvent =
|
||||||
|
| { type: "test:coverage"; data: EventData.TestCoverage }
|
||||||
|
| { type: "test:complete"; data: EventData.TestComplete }
|
||||||
|
| { type: "test:dequeue"; data: EventData.TestDequeue }
|
||||||
|
| { type: "test:diagnostic"; data: EventData.TestDiagnostic }
|
||||||
|
| { type: "test:enqueue"; data: EventData.TestEnqueue }
|
||||||
|
| { type: "test:fail"; data: EventData.TestFail }
|
||||||
|
| { type: "test:pass"; data: EventData.TestPass }
|
||||||
|
| { type: "test:plan"; data: EventData.TestPlan }
|
||||||
|
| { type: "test:start"; data: EventData.TestStart }
|
||||||
|
| { type: "test:stderr"; data: EventData.TestStderr }
|
||||||
|
| { type: "test:stdout"; data: EventData.TestStdout }
|
||||||
|
| { type: "test:summary"; data: EventData.TestSummary }
|
||||||
|
| { type: "test:watch:drained"; data: undefined }
|
||||||
|
| { type: "test:watch:restarted"; data: undefined };
|
||||||
|
interface ReporterConstructorWrapper<T extends new(...args: any[]) => Transform> {
|
||||||
|
new(...args: ConstructorParameters<T>): InstanceType<T>;
|
||||||
|
(...args: ConstructorParameters<T>): InstanceType<T>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `dot` reporter outputs the test results in a compact format,
|
||||||
|
* where each passing test is represented by a `.`,
|
||||||
|
* and each failing test is represented by a `X`.
|
||||||
|
* @since v20.0.0
|
||||||
|
*/
|
||||||
|
function dot(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>;
|
||||||
|
/**
|
||||||
|
* The `tap` reporter outputs the test results in the [TAP](https://testanything.org/) format.
|
||||||
|
* @since v20.0.0
|
||||||
|
*/
|
||||||
|
function tap(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>;
|
||||||
|
class SpecReporter extends Transform {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `spec` reporter outputs the test results in a human-readable format.
|
||||||
|
* @since v20.0.0
|
||||||
|
*/
|
||||||
|
const spec: ReporterConstructorWrapper<typeof SpecReporter>;
|
||||||
|
/**
|
||||||
|
* The `junit` reporter outputs test results in a jUnit XML format.
|
||||||
|
* @since v21.0.0
|
||||||
|
*/
|
||||||
|
function junit(source: AsyncIterable<TestEvent>): NodeJS.AsyncIterator<string>;
|
||||||
|
class LcovReporter extends Transform {
|
||||||
|
constructor(options?: Omit<TransformOptions, "writableObjectMode">);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `lcov` reporter outputs test coverage when used with the
|
||||||
|
* [`--experimental-test-coverage`](https://nodejs.org/docs/latest-v25.x/api/cli.html#--experimental-test-coverage) flag.
|
||||||
|
* @since v22.0.0
|
||||||
|
*/
|
||||||
|
const lcov: ReporterConstructorWrapper<typeof LcovReporter>;
|
||||||
|
export { dot, junit, lcov, spec, tap, TestEvent };
|
||||||
|
}
|
||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
1.0.0 / 2024-08-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Drop support for node <18
|
||||||
|
* Added an option preferred encodings array #59
|
||||||
|
|
||||||
|
0.6.3 / 2022-01-22
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Revert "Lazy-load modules from main entry point"
|
||||||
|
|
||||||
|
0.6.2 / 2019-04-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix sorting charset, encoding, and language with extra parameters
|
||||||
|
|
||||||
|
0.6.1 / 2016-05-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* perf: improve `Accept` parsing speed
|
||||||
|
* perf: improve `Accept-Charset` parsing speed
|
||||||
|
* perf: improve `Accept-Encoding` parsing speed
|
||||||
|
* perf: improve `Accept-Language` parsing speed
|
||||||
|
|
||||||
|
0.6.0 / 2015-09-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix including type extensions in parameters in `Accept` parsing
|
||||||
|
* Fix parsing `Accept` parameters with quoted equals
|
||||||
|
* Fix parsing `Accept` parameters with quoted semicolons
|
||||||
|
* Lazy-load modules from main entry point
|
||||||
|
* perf: delay type concatenation until needed
|
||||||
|
* perf: enable strict mode
|
||||||
|
* perf: hoist regular expressions
|
||||||
|
* perf: remove closures getting spec properties
|
||||||
|
* perf: remove a closure from media type parsing
|
||||||
|
* perf: remove property delete from media type parsing
|
||||||
|
|
||||||
|
0.5.3 / 2015-05-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix media type parameter matching to be case-insensitive
|
||||||
|
|
||||||
|
0.5.2 / 2015-05-06
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix comparing media types with quoted values
|
||||||
|
* Fix splitting media types with quoted commas
|
||||||
|
|
||||||
|
0.5.1 / 2015-02-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix preference sorting to be stable for long acceptable lists
|
||||||
|
|
||||||
|
0.5.0 / 2014-12-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix list return order when large accepted list
|
||||||
|
* Fix missing identity encoding when q=0 exists
|
||||||
|
* Remove dynamic building of Negotiator class
|
||||||
|
|
||||||
|
0.4.9 / 2014-10-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when media type has invalid parameter
|
||||||
|
|
||||||
|
0.4.8 / 2014-09-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix all negotiations to be case-insensitive
|
||||||
|
* Stable sort preferences of same quality according to client order
|
||||||
|
* Support Node.js 0.6
|
||||||
|
|
||||||
|
0.4.7 / 2014-06-24
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Handle invalid provided languages
|
||||||
|
* Handle invalid provided media types
|
||||||
|
|
||||||
|
0.4.6 / 2014-06-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Order by specificity when quality is the same
|
||||||
|
|
||||||
|
0.4.5 / 2014-05-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix regression in empty header handling
|
||||||
|
|
||||||
|
0.4.4 / 2014-05-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix behaviors when headers are not present
|
||||||
|
|
||||||
|
0.4.3 / 2014-04-16
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Handle slashes on media params correctly
|
||||||
|
|
||||||
|
0.4.2 / 2014-02-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix media type sorting
|
||||||
|
* Handle media types params strictly
|
||||||
|
|
||||||
|
0.4.1 / 2014-01-16
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Use most specific matches
|
||||||
|
|
||||||
|
0.4.0 / 2014-01-09
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Remove preferred prefix from methods
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
import { IncomingHttpHeaders } from './header'
|
||||||
|
import Dispatcher from './dispatcher';
|
||||||
|
import { BodyInit, Headers } from './fetch'
|
||||||
|
|
||||||
|
export {
|
||||||
|
Interceptable,
|
||||||
|
MockInterceptor,
|
||||||
|
MockScope
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The scope associated with a mock dispatch. */
|
||||||
|
declare class MockScope<TData extends object = object> {
|
||||||
|
constructor(mockDispatch: MockInterceptor.MockDispatch<TData>);
|
||||||
|
/** Delay a reply by a set amount of time in ms. */
|
||||||
|
delay(waitInMs: number): MockScope<TData>;
|
||||||
|
/** Persist the defined mock data for the associated reply. It will return the defined mock data indefinitely. */
|
||||||
|
persist(): MockScope<TData>;
|
||||||
|
/** Define a reply for a set amount of matching requests. */
|
||||||
|
times(repeatTimes: number): MockScope<TData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The interceptor for a Mock. */
|
||||||
|
declare class MockInterceptor {
|
||||||
|
constructor(options: MockInterceptor.Options, mockDispatches: MockInterceptor.MockDispatch[]);
|
||||||
|
/** Mock an undici request with the defined reply. */
|
||||||
|
reply<TData extends object = object>(replyOptionsCallback: MockInterceptor.MockReplyOptionsCallback<TData>): MockScope<TData>;
|
||||||
|
reply<TData extends object = object>(
|
||||||
|
statusCode: number,
|
||||||
|
data?: TData | Buffer | string | MockInterceptor.MockResponseDataHandler<TData>,
|
||||||
|
responseOptions?: MockInterceptor.MockResponseOptions
|
||||||
|
): MockScope<TData>;
|
||||||
|
/** Mock an undici request by throwing the defined reply error. */
|
||||||
|
replyWithError<TError extends Error = Error>(error: TError): MockScope;
|
||||||
|
/** Set default reply headers on the interceptor for subsequent mocked replies. */
|
||||||
|
defaultReplyHeaders(headers: IncomingHttpHeaders): MockInterceptor;
|
||||||
|
/** Set default reply trailers on the interceptor for subsequent mocked replies. */
|
||||||
|
defaultReplyTrailers(trailers: Record<string, string>): MockInterceptor;
|
||||||
|
/** Set automatically calculated content-length header on subsequent mocked replies. */
|
||||||
|
replyContentLength(): MockInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace MockInterceptor {
|
||||||
|
/** MockInterceptor options. */
|
||||||
|
export interface Options {
|
||||||
|
/** Path to intercept on. */
|
||||||
|
path: string | RegExp | ((path: string) => boolean);
|
||||||
|
/** Method to intercept on. Defaults to GET. */
|
||||||
|
method?: string | RegExp | ((method: string) => boolean);
|
||||||
|
/** Body to intercept on. */
|
||||||
|
body?: string | RegExp | ((body: string) => boolean);
|
||||||
|
/** Headers to intercept on. */
|
||||||
|
headers?: Record<string, string | RegExp | ((body: string) => boolean)> | ((headers: Record<string, string>) => boolean);
|
||||||
|
/** Query params to intercept on */
|
||||||
|
query?: Record<string, any>;
|
||||||
|
}
|
||||||
|
export interface MockDispatch<TData extends object = object, TError extends Error = Error> extends Options {
|
||||||
|
times: number | null;
|
||||||
|
persist: boolean;
|
||||||
|
consumed: boolean;
|
||||||
|
data: MockDispatchData<TData, TError>;
|
||||||
|
}
|
||||||
|
export interface MockDispatchData<TData extends object = object, TError extends Error = Error> extends MockResponseOptions {
|
||||||
|
error: TError | null;
|
||||||
|
statusCode?: number;
|
||||||
|
data?: TData | string;
|
||||||
|
}
|
||||||
|
export interface MockResponseOptions {
|
||||||
|
headers?: IncomingHttpHeaders;
|
||||||
|
trailers?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MockResponseCallbackOptions {
|
||||||
|
path: string;
|
||||||
|
method: string;
|
||||||
|
headers?: Headers | Record<string, string>;
|
||||||
|
origin?: string;
|
||||||
|
body?: BodyInit | Dispatcher.DispatchOptions['body'] | null;
|
||||||
|
maxRedirections?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MockResponseDataHandler<TData extends object = object> = (
|
||||||
|
opts: MockResponseCallbackOptions
|
||||||
|
) => TData | Buffer | string;
|
||||||
|
|
||||||
|
export type MockReplyOptionsCallback<TData extends object = object> = (
|
||||||
|
opts: MockResponseCallbackOptions
|
||||||
|
) => { statusCode: number, data?: TData | Buffer | string, responseOptions?: MockResponseOptions }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Interceptable extends Dispatcher {
|
||||||
|
/** Intercepts any matching requests that use the same origin as this mock client. */
|
||||||
|
intercept(options: MockInterceptor.Options): MockInterceptor;
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
import baseFunctions from './_baseFunctions.js';
|
||||||
|
import keys from './keys.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of function property names from own enumerable properties
|
||||||
|
* of `object`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @since 0.1.0
|
||||||
|
* @memberOf _
|
||||||
|
* @category Object
|
||||||
|
* @param {Object} object The object to inspect.
|
||||||
|
* @returns {Array} Returns the function names.
|
||||||
|
* @see _.functionsIn
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* function Foo() {
|
||||||
|
* this.a = _.constant('a');
|
||||||
|
* this.b = _.constant('b');
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Foo.prototype.c = _.constant('c');
|
||||||
|
*
|
||||||
|
* _.functions(new Foo);
|
||||||
|
* // => ['a', 'b']
|
||||||
|
*/
|
||||||
|
function functions(object) {
|
||||||
|
return object == null ? [] : baseFunctions(object, keys(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default functions;
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
title: Package spec
|
||||||
|
section: 7
|
||||||
|
description: Package name specifier
|
||||||
|
---
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Commands like `npm install` and the dependency sections in the `package.json` use a package name specifier.
|
||||||
|
This can be many different things that all refer to a "package". Examples include a package name, git url, tarball, or local directory.
|
||||||
|
These will generally be referred to as `<package-spec>` in the help output for the npm commands that use this package name specifier.
|
||||||
|
|
||||||
|
### Package name
|
||||||
|
|
||||||
|
* `[<@scope>/]<pkg>`
|
||||||
|
* `[<@scope>/]<pkg>@<tag>`
|
||||||
|
* `[<@scope>/]<pkg>@<version>`
|
||||||
|
* `[<@scope>/]<pkg>@<version range>`
|
||||||
|
|
||||||
|
Refers to a package by name, with or without a scope, and optionally tag, version, or version range.
|
||||||
|
This is typically used in combination with the [registry](/using-npm/config#registry) config to refer to a package in a registry.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
* `npm`
|
||||||
|
* `@npmcli/arborist`
|
||||||
|
* `@npmcli/arborist@latest`
|
||||||
|
* `npm@6.13.1`
|
||||||
|
* `npm@^4.0.0`
|
||||||
|
|
||||||
|
### Aliases
|
||||||
|
|
||||||
|
* `<alias>@npm:<name>`
|
||||||
|
|
||||||
|
Primarily used by commands like `npm install` and in the dependency sections in the `package.json`, this refers to a package by an alias.
|
||||||
|
The `<alias>` is the name of the package as it is reified in the `node_modules` folder, and the `<name>` refers to a package name as found in the configured registry.
|
||||||
|
|
||||||
|
See `Package name` above for more info on referring to a package by name, and [registry](/using-npm/config#registry) for configuring which registry is used when referring to a package by name.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
* `semver@npm:@npmcli/semver-with-patch`
|
||||||
|
* `semver@npm:semver@7.2.2`
|
||||||
|
* `semver@npm:semver@legacy`
|
||||||
|
|
||||||
|
### Folders
|
||||||
|
|
||||||
|
* `<folder>`
|
||||||
|
|
||||||
|
This refers to a package on the local filesystem.
|
||||||
|
Specifically this is a folder with a `package.json` file in it.
|
||||||
|
This *should* always be prefixed with a `/` or `./` (or your OS equivalent) to reduce confusion.
|
||||||
|
npm currently will parse a string with more than one `/` in it as a folder, but this is legacy behavior that may be removed in a future version.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* `./my-package`
|
||||||
|
* `/opt/npm/my-package`
|
||||||
|
|
||||||
|
### Tarballs
|
||||||
|
|
||||||
|
* `<tarball file>`
|
||||||
|
* `<tarball url>`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* `./my-package.tgz`
|
||||||
|
* `https://registry.npmjs.org/semver/-/semver-1.0.0.tgz`
|
||||||
|
|
||||||
|
Refers to a package in a tarball format, either on the local filesystem or remotely via url.
|
||||||
|
This is the format that packages exist in when uploaded to a registry.
|
||||||
|
|
||||||
|
### git urls
|
||||||
|
|
||||||
|
* `<git:// url>`
|
||||||
|
* `<github username>/<github project>`
|
||||||
|
|
||||||
|
Refers to a package in a git repo.
|
||||||
|
This can be a full git url, git shorthand, or a username/package on GitHub.
|
||||||
|
You can specify a git tag, branch, or other git ref by appending `#ref`.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* `https://github.com/npm/cli.git`
|
||||||
|
* `git@github.com:npm/cli.git`
|
||||||
|
* `git+ssh://git@github.com/npm/cli#v6.0.0`
|
||||||
|
* `github:npm/cli#HEAD`
|
||||||
|
* `npm/cli#c12ea07`
|
||||||
|
|
||||||
|
### See also
|
||||||
|
|
||||||
|
* [npm-package-arg](https://npm.im/npm-package-arg)
|
||||||
|
* [scope](/using-npm/scope)
|
||||||
|
* [config](/using-npm/config)
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
const { relative } = require('path')
|
||||||
|
const pkgContents = require('../')
|
||||||
|
|
||||||
|
const usage = `Usage:
|
||||||
|
installed-package-contents <path> [-d<n> --depth=<n>]
|
||||||
|
|
||||||
|
Lists the files installed for a package specified by <path>.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-d<n> --depth=<n> Provide a numeric value ("Infinity" is allowed)
|
||||||
|
to specify how deep in the file tree to traverse.
|
||||||
|
Default=1
|
||||||
|
-h --help Show this usage information`
|
||||||
|
|
||||||
|
const options = {}
|
||||||
|
|
||||||
|
process.argv.slice(2).forEach(arg => {
|
||||||
|
let match
|
||||||
|
if ((match = arg.match(/^(?:--depth=|-d)([0-9]+|Infinity)/))) {
|
||||||
|
options.depth = +match[1]
|
||||||
|
} else if (arg === '-h' || arg === '--help') {
|
||||||
|
console.log(usage)
|
||||||
|
process.exit(0)
|
||||||
|
} else {
|
||||||
|
options.path = arg
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!options.path) {
|
||||||
|
console.error('ERROR: no path provided')
|
||||||
|
console.error(usage)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cwd = process.cwd()
|
||||||
|
|
||||||
|
pkgContents(options)
|
||||||
|
.then(list => list.sort().forEach(p => console.log(relative(cwd, p))))
|
||||||
|
.catch(/* istanbul ignore next - pretty unusual */ er => {
|
||||||
|
console.error(er)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
* @returns {RegExp}
|
||||||
|
* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {RegExp | string } re
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function source(re) {
|
||||||
|
if (!re) return null;
|
||||||
|
if (typeof re === "string") return re;
|
||||||
|
|
||||||
|
return re.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {...(RegExp | string) } args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function concat(...args) {
|
||||||
|
const joined = args.map((x) => source(x)).join("");
|
||||||
|
return joined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any of the passed expresssions may match
|
||||||
|
*
|
||||||
|
* Creates a huge this | this | that | that match
|
||||||
|
* @param {(RegExp | string)[] } args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function either(...args) {
|
||||||
|
const joined = '(' + args.map((x) => source(x)).join("|") + ")";
|
||||||
|
return joined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Language: Apache Access Log
|
||||||
|
Author: Oleg Efimov <efimovov@gmail.com>
|
||||||
|
Description: Apache/Nginx Access Logs
|
||||||
|
Website: https://httpd.apache.org/docs/2.4/logs.html#accesslog
|
||||||
|
Audit: 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type LanguageFn */
|
||||||
|
function accesslog(_hljs) {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||||
|
const HTTP_VERBS = [
|
||||||
|
"GET",
|
||||||
|
"POST",
|
||||||
|
"HEAD",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"PATCH",
|
||||||
|
"TRACE"
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
name: 'Apache Access Log',
|
||||||
|
contains: [
|
||||||
|
// IP
|
||||||
|
{
|
||||||
|
className: 'number',
|
||||||
|
begin: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?\b/,
|
||||||
|
relevance: 5
|
||||||
|
},
|
||||||
|
// Other numbers
|
||||||
|
{
|
||||||
|
className: 'number',
|
||||||
|
begin: /\b\d+\b/,
|
||||||
|
relevance: 0
|
||||||
|
},
|
||||||
|
// Requests
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
begin: concat(/"/, either(...HTTP_VERBS)),
|
||||||
|
end: /"/,
|
||||||
|
keywords: HTTP_VERBS,
|
||||||
|
illegal: /\n/,
|
||||||
|
relevance: 5,
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
begin: /HTTP\/[12]\.\d'/,
|
||||||
|
relevance: 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// Dates
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
// dates must have a certain length, this prevents matching
|
||||||
|
// simple array accesses a[123] and [] and other common patterns
|
||||||
|
// found in other languages
|
||||||
|
begin: /\[\d[^\]\n]{8,}\]/,
|
||||||
|
illegal: /\n/,
|
||||||
|
relevance: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
begin: /\[/,
|
||||||
|
end: /\]/,
|
||||||
|
illegal: /\n/,
|
||||||
|
relevance: 0
|
||||||
|
},
|
||||||
|
// User agent / relevance boost
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
begin: /"Mozilla\/\d\.\d \(/,
|
||||||
|
end: /"/,
|
||||||
|
illegal: /\n/,
|
||||||
|
relevance: 3
|
||||||
|
},
|
||||||
|
// Strings
|
||||||
|
{
|
||||||
|
className: 'string',
|
||||||
|
begin: /"/,
|
||||||
|
end: /"/,
|
||||||
|
illegal: /\n/,
|
||||||
|
relevance: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = accesslog;
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
Revert the `Partial` modifier on an object type.
|
||||||
|
|
||||||
|
Use-case: Infer the underlying type `T` when only `Partial<T>` is available or the original type may not be directly accessible.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {UnwrapPartial} from 'type-fest';
|
||||||
|
|
||||||
|
type Config = Partial<{
|
||||||
|
port: number;
|
||||||
|
host: string;
|
||||||
|
secure?: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
type InitializedConfig = UnwrapPartial<Config>;
|
||||||
|
//=> {port: number; host: string; secure?: boolean}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: If the provided type isn’t of `Partial<T>`, `UnwrapPartial` has no effect on the original type.
|
||||||
|
|
||||||
|
@category Object
|
||||||
|
*/
|
||||||
|
export type UnwrapPartial<PartialObjectType> =
|
||||||
|
PartialObjectType extends Partial<infer ObjectType>
|
||||||
|
? (
|
||||||
|
Partial<ObjectType> extends PartialObjectType
|
||||||
|
? ObjectType
|
||||||
|
: PartialObjectType
|
||||||
|
)
|
||||||
|
: PartialObjectType;
|
||||||
|
|
||||||
|
export {};
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* This nodeLocation tracking is not efficient and should only be used
|
||||||
|
* when error recovery is enabled or the Token Vector contains virtual Tokens
|
||||||
|
* (e.g, Python Indent/Outdent)
|
||||||
|
* As it executes the calculation for every single terminal/nonTerminal
|
||||||
|
* and does not rely on the fact the token vector is **sorted**
|
||||||
|
*/
|
||||||
|
export function setNodeLocationOnlyOffset(currNodeLocation, newLocationInfo) {
|
||||||
|
// First (valid) update for this cst node
|
||||||
|
if (isNaN(currNodeLocation.startOffset) === true) {
|
||||||
|
// assumption1: Token location information is either NaN or a valid number
|
||||||
|
// assumption2: Token location information is fully valid if it exist
|
||||||
|
// (both start/end offsets exist and are numbers).
|
||||||
|
currNodeLocation.startOffset = newLocationInfo.startOffset;
|
||||||
|
currNodeLocation.endOffset = newLocationInfo.endOffset;
|
||||||
|
}
|
||||||
|
// Once the startOffset has been updated with a valid number it should never receive
|
||||||
|
// any farther updates as the Token vector is sorted.
|
||||||
|
// We still have to check this this condition for every new possible location info
|
||||||
|
// because with error recovery enabled we may encounter invalid tokens (NaN location props)
|
||||||
|
else if (currNodeLocation.endOffset < newLocationInfo.endOffset === true) {
|
||||||
|
currNodeLocation.endOffset = newLocationInfo.endOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This nodeLocation tracking is not efficient and should only be used
|
||||||
|
* when error recovery is enabled or the Token Vector contains virtual Tokens
|
||||||
|
* (e.g, Python Indent/Outdent)
|
||||||
|
* As it executes the calculation for every single terminal/nonTerminal
|
||||||
|
* and does not rely on the fact the token vector is **sorted**
|
||||||
|
*/
|
||||||
|
export function setNodeLocationFull(currNodeLocation, newLocationInfo) {
|
||||||
|
// First (valid) update for this cst node
|
||||||
|
if (isNaN(currNodeLocation.startOffset) === true) {
|
||||||
|
// assumption1: Token location information is either NaN or a valid number
|
||||||
|
// assumption2: Token location information is fully valid if it exist
|
||||||
|
// (all start/end props exist and are numbers).
|
||||||
|
currNodeLocation.startOffset = newLocationInfo.startOffset;
|
||||||
|
currNodeLocation.startColumn = newLocationInfo.startColumn;
|
||||||
|
currNodeLocation.startLine = newLocationInfo.startLine;
|
||||||
|
currNodeLocation.endOffset = newLocationInfo.endOffset;
|
||||||
|
currNodeLocation.endColumn = newLocationInfo.endColumn;
|
||||||
|
currNodeLocation.endLine = newLocationInfo.endLine;
|
||||||
|
}
|
||||||
|
// Once the start props has been updated with a valid number it should never receive
|
||||||
|
// any farther updates as the Token vector is sorted.
|
||||||
|
// We still have to check this this condition for every new possible location info
|
||||||
|
// because with error recovery enabled we may encounter invalid tokens (NaN location props)
|
||||||
|
else if (currNodeLocation.endOffset < newLocationInfo.endOffset === true) {
|
||||||
|
currNodeLocation.endOffset = newLocationInfo.endOffset;
|
||||||
|
currNodeLocation.endColumn = newLocationInfo.endColumn;
|
||||||
|
currNodeLocation.endLine = newLocationInfo.endLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function addTerminalToCst(node, token, tokenTypeName) {
|
||||||
|
if (node.children[tokenTypeName] === undefined) {
|
||||||
|
node.children[tokenTypeName] = [token];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.children[tokenTypeName].push(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function addNoneTerminalToCst(node, ruleName, ruleResult) {
|
||||||
|
if (node.children[ruleName] === undefined) {
|
||||||
|
node.children[ruleName] = [ruleResult];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.children[ruleName].push(ruleResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=cst.js.map
|
||||||
+191
@@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
title: npm-prune
|
||||||
|
section: 1
|
||||||
|
description: Remove extraneous packages
|
||||||
|
---
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm prune [[<@scope>/]<pkg>...]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This command removes "extraneous" packages.
|
||||||
|
If a package name is provided, then only packages matching one of the supplied names are removed.
|
||||||
|
|
||||||
|
Extraneous packages are those present in the `node_modules` folder that are not listed as any package's dependency list.
|
||||||
|
|
||||||
|
If the `--omit=dev` flag is specified or the `NODE_ENV` environment variable is set to `production`, this command will remove the packages specified in your `devDependencies`.
|
||||||
|
|
||||||
|
If the `--dry-run` flag is used then no changes will actually be made.
|
||||||
|
|
||||||
|
If the `--json` flag is used, then the changes `npm prune` made (or would have made with `--dry-run`) are printed as a JSON object.
|
||||||
|
|
||||||
|
In normal operation, extraneous modules are pruned automatically, so you'll only need this command with the `--production` flag.
|
||||||
|
However, in the real world, operation is not always "normal". When crashes or mistakes happen, this command can help clean up any resulting garbage.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### `omit`
|
||||||
|
|
||||||
|
* Default: 'dev' if the `NODE_ENV` environment variable is set to
|
||||||
|
'production'; otherwise, empty.
|
||||||
|
* Type: "dev", "optional", or "peer" (can be set multiple times)
|
||||||
|
|
||||||
|
Dependency types to omit from the installation tree on disk.
|
||||||
|
|
||||||
|
Note that these dependencies _are_ still resolved and added to the
|
||||||
|
`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
|
||||||
|
physically installed on disk.
|
||||||
|
|
||||||
|
If a package type appears in both the `--include` and `--omit` lists, then
|
||||||
|
it will be included.
|
||||||
|
|
||||||
|
If the resulting omit list includes `'dev'`, then the `NODE_ENV` environment
|
||||||
|
variable will be set to `'production'` for all lifecycle scripts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `include`
|
||||||
|
|
||||||
|
* Default:
|
||||||
|
* Type: "prod", "dev", "optional", or "peer" (can be set multiple times)
|
||||||
|
|
||||||
|
Option that allows for defining which types of dependencies to install.
|
||||||
|
|
||||||
|
This is the inverse of `--omit=<type>`.
|
||||||
|
|
||||||
|
Dependency types specified in `--include` will not be omitted, regardless of
|
||||||
|
the order in which omit/include are specified on the command-line.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `dry-run`
|
||||||
|
|
||||||
|
* Default: false
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
Indicates that you don't want npm to make any changes and that it should
|
||||||
|
only report what it would have done. This can be passed into any of the
|
||||||
|
commands that modify your local installation, eg, `install`, `update`,
|
||||||
|
`dedupe`, `uninstall`, as well as `pack` and `publish`.
|
||||||
|
|
||||||
|
Note: This is NOT honored by other network related commands, eg `dist-tags`,
|
||||||
|
`owner`, etc.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `json`
|
||||||
|
|
||||||
|
* Default: false
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
Whether or not to output JSON data, rather than the normal output.
|
||||||
|
|
||||||
|
* In `npm pkg set` it enables parsing set values with JSON.parse() before
|
||||||
|
saving them to your `package.json`.
|
||||||
|
|
||||||
|
Not supported by all npm commands.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `foreground-scripts`
|
||||||
|
|
||||||
|
* Default: `false` unless when using `npm pack` or `npm publish` where it
|
||||||
|
defaults to `true`
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
Run all build scripts (ie, `preinstall`, `install`, and `postinstall`)
|
||||||
|
scripts for installed packages in the foreground process, sharing standard
|
||||||
|
input, output, and error with the main npm process.
|
||||||
|
|
||||||
|
Note that this will generally make installs run slower, and be much noisier,
|
||||||
|
but can be useful for debugging.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `ignore-scripts`
|
||||||
|
|
||||||
|
* Default: false
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
If true, npm does not run scripts specified in package.json files.
|
||||||
|
|
||||||
|
Note that commands explicitly intended to run a particular script, such as
|
||||||
|
`npm start`, `npm stop`, `npm restart`, `npm test`, and `npm run` will still
|
||||||
|
run their intended script if `ignore-scripts` is set, but they will *not*
|
||||||
|
run any pre- or post-scripts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### `workspace`
|
||||||
|
|
||||||
|
* Default:
|
||||||
|
* Type: String (can be set multiple times)
|
||||||
|
|
||||||
|
Enable running a command in the context of the configured workspaces of the
|
||||||
|
current project while filtering by running only the workspaces defined by
|
||||||
|
this configuration option.
|
||||||
|
|
||||||
|
Valid values for the `workspace` config are either:
|
||||||
|
|
||||||
|
* Workspace names
|
||||||
|
* Path to a workspace directory
|
||||||
|
* Path to a parent workspace directory (will result in selecting all
|
||||||
|
workspaces within that folder)
|
||||||
|
|
||||||
|
When set for the `npm init` command, this may be set to the folder of a
|
||||||
|
workspace which does not yet exist, to create the folder and set it up as a
|
||||||
|
brand new workspace within the project.
|
||||||
|
|
||||||
|
This value is not exported to the environment for child processes.
|
||||||
|
|
||||||
|
#### `workspaces`
|
||||||
|
|
||||||
|
* Default: null
|
||||||
|
* Type: null or Boolean
|
||||||
|
|
||||||
|
Set to true to run the command in the context of **all** configured
|
||||||
|
workspaces.
|
||||||
|
|
||||||
|
Explicitly setting this to false will cause commands like `install` to
|
||||||
|
ignore workspaces altogether. When not set explicitly:
|
||||||
|
|
||||||
|
- Commands that operate on the `node_modules` tree (install, update, etc.)
|
||||||
|
will link workspaces into the `node_modules` folder. - Commands that do
|
||||||
|
other things (test, exec, publish, etc.) will operate on the root project,
|
||||||
|
_unless_ one or more workspaces are specified in the `workspace` config.
|
||||||
|
|
||||||
|
This value is not exported to the environment for child processes.
|
||||||
|
|
||||||
|
#### `include-workspace-root`
|
||||||
|
|
||||||
|
* Default: false
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
Include the workspace root when workspaces are enabled for a command.
|
||||||
|
|
||||||
|
When false, specifying individual workspaces via the `workspace` config, or
|
||||||
|
all workspaces via the `workspaces` flag, will cause npm to operate only on
|
||||||
|
the specified workspaces, and not on the root project.
|
||||||
|
|
||||||
|
This value is not exported to the environment for child processes.
|
||||||
|
|
||||||
|
#### `install-links`
|
||||||
|
|
||||||
|
* Default: false
|
||||||
|
* Type: Boolean
|
||||||
|
|
||||||
|
When set file: protocol dependencies will be packed and installed as regular
|
||||||
|
dependencies instead of creating a symlink. This option has no effect on
|
||||||
|
workspaces.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### See Also
|
||||||
|
|
||||||
|
* [npm uninstall](/commands/npm-uninstall)
|
||||||
|
* [npm folders](/configuring-npm/folders)
|
||||||
|
* [npm ls](/commands/npm-ls)
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "registry-auth-token",
|
||||||
|
"version": "5.1.1",
|
||||||
|
"description": "Get the auth token set for an npm registry (if any)",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --require test/global-hooks.js",
|
||||||
|
"posttest": "standard",
|
||||||
|
"coverage": "istanbul cover _mocha"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+ssh://git@github.com/rexxars/registry-auth-token.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"npm",
|
||||||
|
"conf",
|
||||||
|
"config",
|
||||||
|
"npmconf",
|
||||||
|
"registry",
|
||||||
|
"auth",
|
||||||
|
"token",
|
||||||
|
"authtoken"
|
||||||
|
],
|
||||||
|
"author": "Espen Hovlandsdal <espen@hovlandsdal.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/rexxars/registry-auth-token/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/rexxars/registry-auth-token#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"@pnpm/npm-conf": "^3.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"istanbul": "^0.4.2",
|
||||||
|
"mocha": "^10.0.0",
|
||||||
|
"require-uncached": "^1.0.2",
|
||||||
|
"standard": "^12.0.1"
|
||||||
|
},
|
||||||
|
"standard": {
|
||||||
|
"ignore": [
|
||||||
|
"coverage/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
import { cc } from "./utils.js";
|
||||||
|
export const digitsCharCodes = [];
|
||||||
|
for (let i = cc("0"); i <= cc("9"); i++) {
|
||||||
|
digitsCharCodes.push(i);
|
||||||
|
}
|
||||||
|
export const wordCharCodes = [cc("_")].concat(digitsCharCodes);
|
||||||
|
for (let i = cc("a"); i <= cc("z"); i++) {
|
||||||
|
wordCharCodes.push(i);
|
||||||
|
}
|
||||||
|
for (let i = cc("A"); i <= cc("Z"); i++) {
|
||||||
|
wordCharCodes.push(i);
|
||||||
|
}
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#character-classes
|
||||||
|
export const whitespaceCodes = [
|
||||||
|
cc(" "),
|
||||||
|
cc("\f"),
|
||||||
|
cc("\n"),
|
||||||
|
cc("\r"),
|
||||||
|
cc("\t"),
|
||||||
|
cc("\v"),
|
||||||
|
cc("\t"),
|
||||||
|
cc("\u00a0"),
|
||||||
|
cc("\u1680"),
|
||||||
|
cc("\u2000"),
|
||||||
|
cc("\u2001"),
|
||||||
|
cc("\u2002"),
|
||||||
|
cc("\u2003"),
|
||||||
|
cc("\u2004"),
|
||||||
|
cc("\u2005"),
|
||||||
|
cc("\u2006"),
|
||||||
|
cc("\u2007"),
|
||||||
|
cc("\u2008"),
|
||||||
|
cc("\u2009"),
|
||||||
|
cc("\u200a"),
|
||||||
|
cc("\u2028"),
|
||||||
|
cc("\u2029"),
|
||||||
|
cc("\u202f"),
|
||||||
|
cc("\u205f"),
|
||||||
|
cc("\u3000"),
|
||||||
|
cc("\ufeff"),
|
||||||
|
];
|
||||||
|
//# sourceMappingURL=character-classes.js.map
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
export { default as camelCase } from './camelCase.js';
|
||||||
|
export { default as capitalize } from './capitalize.js';
|
||||||
|
export { default as deburr } from './deburr.js';
|
||||||
|
export { default as endsWith } from './endsWith.js';
|
||||||
|
export { default as escape } from './escape.js';
|
||||||
|
export { default as escapeRegExp } from './escapeRegExp.js';
|
||||||
|
export { default as kebabCase } from './kebabCase.js';
|
||||||
|
export { default as lowerCase } from './lowerCase.js';
|
||||||
|
export { default as lowerFirst } from './lowerFirst.js';
|
||||||
|
export { default as pad } from './pad.js';
|
||||||
|
export { default as padEnd } from './padEnd.js';
|
||||||
|
export { default as padStart } from './padStart.js';
|
||||||
|
export { default as parseInt } from './parseInt.js';
|
||||||
|
export { default as repeat } from './repeat.js';
|
||||||
|
export { default as replace } from './replace.js';
|
||||||
|
export { default as snakeCase } from './snakeCase.js';
|
||||||
|
export { default as split } from './split.js';
|
||||||
|
export { default as startCase } from './startCase.js';
|
||||||
|
export { default as startsWith } from './startsWith.js';
|
||||||
|
export { default as template } from './template.js';
|
||||||
|
export { default as templateSettings } from './templateSettings.js';
|
||||||
|
export { default as toLower } from './toLower.js';
|
||||||
|
export { default as toUpper } from './toUpper.js';
|
||||||
|
export { default as trim } from './trim.js';
|
||||||
|
export { default as trimEnd } from './trimEnd.js';
|
||||||
|
export { default as trimStart } from './trimStart.js';
|
||||||
|
export { default as truncate } from './truncate.js';
|
||||||
|
export { default as unescape } from './unescape.js';
|
||||||
|
export { default as upperCase } from './upperCase.js';
|
||||||
|
export { default as upperFirst } from './upperFirst.js';
|
||||||
|
export { default as words } from './words.js';
|
||||||
|
export { default } from './string.default.js';
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
var arraySome = require('./_arraySome'),
|
||||||
|
createOver = require('./_createOver');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function that checks if **any** of the `predicates` return
|
||||||
|
* truthy when invoked with the arguments it receives.
|
||||||
|
*
|
||||||
|
* Following shorthands are possible for providing predicates.
|
||||||
|
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
|
||||||
|
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 4.0.0
|
||||||
|
* @category Util
|
||||||
|
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
||||||
|
* The predicates to check.
|
||||||
|
* @returns {Function} Returns the new function.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var func = _.overSome([Boolean, isFinite]);
|
||||||
|
*
|
||||||
|
* func('1');
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* func(null);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* func(NaN);
|
||||||
|
* // => false
|
||||||
|
*
|
||||||
|
* var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
|
||||||
|
* var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
|
||||||
|
*/
|
||||||
|
var overSome = createOver(arraySome);
|
||||||
|
|
||||||
|
module.exports = overSome;
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
export const identity = value => value;
|
||||||
|
|
||||||
|
export const noop = () => undefined;
|
||||||
|
|
||||||
|
export const getContentsProperty = ({contents}) => contents;
|
||||||
|
|
||||||
|
export const throwObjectStream = chunk => {
|
||||||
|
throw new Error(`Streams in object mode are not supported: ${String(chunk)}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLengthProperty = convertedChunk => convertedChunk.length;
|
||||||
+1
File diff suppressed because one or more lines are too long
+77
@@ -0,0 +1,77 @@
|
|||||||
|
var baseKeys = require('./_baseKeys'),
|
||||||
|
getTag = require('./_getTag'),
|
||||||
|
isArguments = require('./isArguments'),
|
||||||
|
isArray = require('./isArray'),
|
||||||
|
isArrayLike = require('./isArrayLike'),
|
||||||
|
isBuffer = require('./isBuffer'),
|
||||||
|
isPrototype = require('./_isPrototype'),
|
||||||
|
isTypedArray = require('./isTypedArray');
|
||||||
|
|
||||||
|
/** `Object#toString` result references. */
|
||||||
|
var mapTag = '[object Map]',
|
||||||
|
setTag = '[object Set]';
|
||||||
|
|
||||||
|
/** Used for built-in method references. */
|
||||||
|
var objectProto = Object.prototype;
|
||||||
|
|
||||||
|
/** Used to check objects for own properties. */
|
||||||
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is an empty object, collection, map, or set.
|
||||||
|
*
|
||||||
|
* Objects are considered empty if they have no own enumerable string keyed
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* Array-like values such as `arguments` objects, arrays, buffers, strings, or
|
||||||
|
* jQuery-like collections are considered empty if they have a `length` of `0`.
|
||||||
|
* Similarly, maps and sets are considered empty if they have a `size` of `0`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 0.1.0
|
||||||
|
* @category Lang
|
||||||
|
* @param {*} value The value to check.
|
||||||
|
* @returns {boolean} Returns `true` if `value` is empty, else `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.isEmpty(null);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isEmpty(true);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isEmpty(1);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isEmpty([1, 2, 3]);
|
||||||
|
* // => false
|
||||||
|
*
|
||||||
|
* _.isEmpty({ 'a': 1 });
|
||||||
|
* // => false
|
||||||
|
*/
|
||||||
|
function isEmpty(value) {
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (isArrayLike(value) &&
|
||||||
|
(isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
|
||||||
|
isBuffer(value) || isTypedArray(value) || isArguments(value))) {
|
||||||
|
return !value.length;
|
||||||
|
}
|
||||||
|
var tag = getTag(value);
|
||||||
|
if (tag == mapTag || tag == setTag) {
|
||||||
|
return !value.size;
|
||||||
|
}
|
||||||
|
if (isPrototype(value)) {
|
||||||
|
return !baseKeys(value).length;
|
||||||
|
}
|
||||||
|
for (var key in value) {
|
||||||
|
if (hasOwnProperty.call(value, key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = isEmpty;
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
const platform = process.env.__TESTING_BIN_LINKS_PLATFORM__ || process.platform
|
||||||
|
module.exports = platform === 'win32'
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
import arraySampleSize from './_arraySampleSize.js';
|
||||||
|
import baseSampleSize from './_baseSampleSize.js';
|
||||||
|
import isArray from './isArray.js';
|
||||||
|
import isIterateeCall from './_isIterateeCall.js';
|
||||||
|
import toInteger from './toInteger.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets `n` random elements at unique keys from `collection` up to the
|
||||||
|
* size of `collection`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 4.0.0
|
||||||
|
* @category Collection
|
||||||
|
* @param {Array|Object} collection The collection to sample.
|
||||||
|
* @param {number} [n=1] The number of elements to sample.
|
||||||
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||||||
|
* @returns {Array} Returns the random elements.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.sampleSize([1, 2, 3], 2);
|
||||||
|
* // => [3, 1]
|
||||||
|
*
|
||||||
|
* _.sampleSize([1, 2, 3], 4);
|
||||||
|
* // => [2, 3, 1]
|
||||||
|
*/
|
||||||
|
function sampleSize(collection, n, guard) {
|
||||||
|
if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
|
||||||
|
n = 1;
|
||||||
|
} else {
|
||||||
|
n = toInteger(n);
|
||||||
|
}
|
||||||
|
var func = isArray(collection) ? arraySampleSize : baseSampleSize;
|
||||||
|
return func(collection, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default sampleSize;
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
var baseEach = require('./_baseEach'),
|
||||||
|
isArrayLike = require('./isArrayLike');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base implementation of `_.map` without support for iteratee shorthands.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array|Object} collection The collection to iterate over.
|
||||||
|
* @param {Function} iteratee The function invoked per iteration.
|
||||||
|
* @returns {Array} Returns the new mapped array.
|
||||||
|
*/
|
||||||
|
function baseMap(collection, iteratee) {
|
||||||
|
var index = -1,
|
||||||
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
||||||
|
|
||||||
|
baseEach(collection, function(value, key, collection) {
|
||||||
|
result[++index] = iteratee(value, key, collection);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = baseMap;
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('clone', require('../clone'), require('./_falseOptions'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
import type {IntRange} from './int-range.d.ts';
|
||||||
|
import type {Sum} from './sum.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Generate a union of numbers.
|
||||||
|
|
||||||
|
The numbers are created from the given `Start` (inclusive) parameter to the given `End` (inclusive) parameter.
|
||||||
|
|
||||||
|
You skip over numbers using the `Step` parameter (defaults to `1`). For example, `IntClosedRange<0, 10, 2>` will create a union of `0 | 2 | 4 | 6 | 8 | 10`.
|
||||||
|
|
||||||
|
Note: `Start` or `End` must be non-negative and smaller than `999`.
|
||||||
|
|
||||||
|
Use-cases:
|
||||||
|
1. This can be used to define a set of valid input/output values. for example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {IntClosedRange} from 'type-fest';
|
||||||
|
|
||||||
|
type Age = IntClosedRange<0, 20>;
|
||||||
|
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20
|
||||||
|
|
||||||
|
type FontSize = IntClosedRange<10, 20>;
|
||||||
|
//=> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20
|
||||||
|
|
||||||
|
type EvenNumber = IntClosedRange<0, 10, 2>;
|
||||||
|
//=> 0 | 2 | 4 | 6 | 8 | 10
|
||||||
|
```
|
||||||
|
|
||||||
|
2. This can be used to define random numbers in a range. For example, `type RandomNumber = IntClosedRange<0, 100>;`
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {IntClosedRange} from 'type-fest';
|
||||||
|
|
||||||
|
type ZeroToNine = IntClosedRange<0, 9>;
|
||||||
|
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
|
||||||
|
|
||||||
|
type Hundreds = IntClosedRange<100, 900, 100>;
|
||||||
|
//=> 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||||
|
```
|
||||||
|
|
||||||
|
@see {@link IntRange}
|
||||||
|
*/
|
||||||
|
export type IntClosedRange<Start extends number, End extends number, Skip extends number = 1> = IntRange<Start, Sum<End, 1>, Skip>;
|
||||||
|
|
||||||
|
export {};
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"Commands:": "Commands:",
|
||||||
|
"Options:": "Options:",
|
||||||
|
"Examples:": "Examples:",
|
||||||
|
"boolean": "boolean",
|
||||||
|
"count": "count",
|
||||||
|
"string": "string",
|
||||||
|
"number": "number",
|
||||||
|
"array": "array",
|
||||||
|
"required": "required",
|
||||||
|
"default": "default",
|
||||||
|
"default:": "default:",
|
||||||
|
"choices:": "choices:",
|
||||||
|
"aliases:": "aliases:",
|
||||||
|
"generated-value": "generated-value",
|
||||||
|
"Not enough non-option arguments: got %s, need at least %s": {
|
||||||
|
"one": "Not enough non-option arguments: got %s, need at least %s",
|
||||||
|
"other": "Not enough non-option arguments: got %s, need at least %s"
|
||||||
|
},
|
||||||
|
"Too many non-option arguments: got %s, maximum of %s": {
|
||||||
|
"one": "Too many non-option arguments: got %s, maximum of %s",
|
||||||
|
"other": "Too many non-option arguments: got %s, maximum of %s"
|
||||||
|
},
|
||||||
|
"Missing argument value: %s": {
|
||||||
|
"one": "Missing argument value: %s",
|
||||||
|
"other": "Missing argument values: %s"
|
||||||
|
},
|
||||||
|
"Missing required argument: %s": {
|
||||||
|
"one": "Missing required argument: %s",
|
||||||
|
"other": "Missing required arguments: %s"
|
||||||
|
},
|
||||||
|
"Unknown argument: %s": {
|
||||||
|
"one": "Unknown argument: %s",
|
||||||
|
"other": "Unknown arguments: %s"
|
||||||
|
},
|
||||||
|
"Invalid values:": "Invalid values:",
|
||||||
|
"Argument: %s, Given: %s, Choices: %s": "Argument: %s, Given: %s, Choices: %s",
|
||||||
|
"Argument check failed: %s": "Argument check failed: %s",
|
||||||
|
"Implications failed:": "Missing dependent arguments:",
|
||||||
|
"Not enough arguments following: %s": "Not enough arguments following: %s",
|
||||||
|
"Invalid JSON config file: %s": "Invalid JSON config file: %s",
|
||||||
|
"Path to JSON config file": "Path to JSON config file",
|
||||||
|
"Show help": "Show help",
|
||||||
|
"Show version number": "Show version number",
|
||||||
|
"Did you mean %s?": "Did you mean %s?",
|
||||||
|
"Arguments %s and %s are mutually exclusive" : "Arguments %s and %s are mutually exclusive",
|
||||||
|
"Positionals:": "Positionals:",
|
||||||
|
"command": "command",
|
||||||
|
"deprecated": "deprecated",
|
||||||
|
"deprecated: %s": "deprecated: %s"
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
Language: Hy
|
||||||
|
Description: Hy is a wonderful dialect of Lisp that’s embedded in Python.
|
||||||
|
Author: Sergey Sobko <s.sobko@profitware.ru>
|
||||||
|
Website: http://docs.hylang.org/en/stable/
|
||||||
|
Category: lisp
|
||||||
|
*/
|
||||||
|
|
||||||
|
function hy(hljs) {
|
||||||
|
var SYMBOLSTART = 'a-zA-Z_\\-!.?+*=<>&#\'';
|
||||||
|
var SYMBOL_RE = '[' + SYMBOLSTART + '][' + SYMBOLSTART + '0-9/;:]*';
|
||||||
|
var keywords = {
|
||||||
|
$pattern: SYMBOL_RE,
|
||||||
|
'builtin-name':
|
||||||
|
// keywords
|
||||||
|
'!= % %= & &= * ** **= *= *map ' +
|
||||||
|
'+ += , --build-class-- --import-- -= . / // //= ' +
|
||||||
|
'/= < << <<= <= = > >= >> >>= ' +
|
||||||
|
'@ @= ^ ^= abs accumulate all and any ap-compose ' +
|
||||||
|
'ap-dotimes ap-each ap-each-while ap-filter ap-first ap-if ap-last ap-map ap-map-when ap-pipe ' +
|
||||||
|
'ap-reduce ap-reject apply as-> ascii assert assoc bin break butlast ' +
|
||||||
|
'callable calling-module-name car case cdr chain chr coll? combinations compile ' +
|
||||||
|
'compress cond cons cons? continue count curry cut cycle dec ' +
|
||||||
|
'def default-method defclass defmacro defmacro-alias defmacro/g! defmain defmethod defmulti defn ' +
|
||||||
|
'defn-alias defnc defnr defreader defseq del delattr delete-route dict-comp dir ' +
|
||||||
|
'disassemble dispatch-reader-macro distinct divmod do doto drop drop-last drop-while empty? ' +
|
||||||
|
'end-sequence eval eval-and-compile eval-when-compile even? every? except exec filter first ' +
|
||||||
|
'flatten float? fn fnc fnr for for* format fraction genexpr ' +
|
||||||
|
'gensym get getattr global globals group-by hasattr hash hex id ' +
|
||||||
|
'identity if if* if-not if-python2 import in inc input instance? ' +
|
||||||
|
'integer integer-char? integer? interleave interpose is is-coll is-cons is-empty is-even ' +
|
||||||
|
'is-every is-float is-instance is-integer is-integer-char is-iterable is-iterator is-keyword is-neg is-none ' +
|
||||||
|
'is-not is-numeric is-odd is-pos is-string is-symbol is-zero isinstance islice issubclass ' +
|
||||||
|
'iter iterable? iterate iterator? keyword keyword? lambda last len let ' +
|
||||||
|
'lif lif-not list* list-comp locals loop macro-error macroexpand macroexpand-1 macroexpand-all ' +
|
||||||
|
'map max merge-with method-decorator min multi-decorator multicombinations name neg? next ' +
|
||||||
|
'none? nonlocal not not-in not? nth numeric? oct odd? open ' +
|
||||||
|
'or ord partition permutations pos? post-route postwalk pow prewalk print ' +
|
||||||
|
'product profile/calls profile/cpu put-route quasiquote quote raise range read read-str ' +
|
||||||
|
'recursive-replace reduce remove repeat repeatedly repr require rest round route ' +
|
||||||
|
'route-with-methods rwm second seq set-comp setattr setv some sorted string ' +
|
||||||
|
'string? sum switch symbol? take take-nth take-while tee try unless ' +
|
||||||
|
'unquote unquote-splicing vars walk when while with with* with-decorator with-gensyms ' +
|
||||||
|
'xi xor yield yield-from zero? zip zip-longest | |= ~'
|
||||||
|
};
|
||||||
|
|
||||||
|
var SIMPLE_NUMBER_RE = '[-+]?\\d+(\\.\\d+)?';
|
||||||
|
|
||||||
|
var SYMBOL = {
|
||||||
|
begin: SYMBOL_RE,
|
||||||
|
relevance: 0
|
||||||
|
};
|
||||||
|
var NUMBER = {
|
||||||
|
className: 'number', begin: SIMPLE_NUMBER_RE,
|
||||||
|
relevance: 0
|
||||||
|
};
|
||||||
|
var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null});
|
||||||
|
var COMMENT = hljs.COMMENT(
|
||||||
|
';',
|
||||||
|
'$',
|
||||||
|
{
|
||||||
|
relevance: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
var LITERAL = {
|
||||||
|
className: 'literal',
|
||||||
|
begin: /\b([Tt]rue|[Ff]alse|nil|None)\b/
|
||||||
|
};
|
||||||
|
var COLLECTION = {
|
||||||
|
begin: '[\\[\\{]', end: '[\\]\\}]'
|
||||||
|
};
|
||||||
|
var HINT = {
|
||||||
|
className: 'comment',
|
||||||
|
begin: '\\^' + SYMBOL_RE
|
||||||
|
};
|
||||||
|
var HINT_COL = hljs.COMMENT('\\^\\{', '\\}');
|
||||||
|
var KEY = {
|
||||||
|
className: 'symbol',
|
||||||
|
begin: '[:]{1,2}' + SYMBOL_RE
|
||||||
|
};
|
||||||
|
var LIST = {
|
||||||
|
begin: '\\(', end: '\\)'
|
||||||
|
};
|
||||||
|
var BODY = {
|
||||||
|
endsWithParent: true,
|
||||||
|
relevance: 0
|
||||||
|
};
|
||||||
|
var NAME = {
|
||||||
|
className: 'name',
|
||||||
|
relevance: 0,
|
||||||
|
keywords: keywords,
|
||||||
|
begin: SYMBOL_RE,
|
||||||
|
starts: BODY
|
||||||
|
};
|
||||||
|
var DEFAULT_CONTAINS = [LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL, SYMBOL];
|
||||||
|
|
||||||
|
LIST.contains = [hljs.COMMENT('comment', ''), NAME, BODY];
|
||||||
|
BODY.contains = DEFAULT_CONTAINS;
|
||||||
|
COLLECTION.contains = DEFAULT_CONTAINS;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'Hy',
|
||||||
|
aliases: ['hylang'],
|
||||||
|
illegal: /\S/,
|
||||||
|
contains: [hljs.SHEBANG(), LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = hy;
|
||||||
+712
@@ -0,0 +1,712 @@
|
|||||||
|
import {
|
||||||
|
clone,
|
||||||
|
compact,
|
||||||
|
difference,
|
||||||
|
drop,
|
||||||
|
dropRight,
|
||||||
|
filter,
|
||||||
|
first,
|
||||||
|
flatMap,
|
||||||
|
flatten,
|
||||||
|
forEach,
|
||||||
|
groupBy,
|
||||||
|
includes,
|
||||||
|
isEmpty,
|
||||||
|
map,
|
||||||
|
pickBy,
|
||||||
|
reduce,
|
||||||
|
reject,
|
||||||
|
values,
|
||||||
|
} from "lodash-es";
|
||||||
|
import {
|
||||||
|
IParserAmbiguousAlternativesDefinitionError,
|
||||||
|
IParserDuplicatesDefinitionError,
|
||||||
|
IParserEmptyAlternativeDefinitionError,
|
||||||
|
ParserDefinitionErrorType,
|
||||||
|
} from "../parser/parser.js";
|
||||||
|
import {
|
||||||
|
Alternation,
|
||||||
|
Alternative as AlternativeGAST,
|
||||||
|
GAstVisitor,
|
||||||
|
getProductionDslName,
|
||||||
|
isOptionalProd,
|
||||||
|
NonTerminal,
|
||||||
|
Option,
|
||||||
|
Repetition,
|
||||||
|
RepetitionMandatory,
|
||||||
|
RepetitionMandatoryWithSeparator,
|
||||||
|
RepetitionWithSeparator,
|
||||||
|
Terminal,
|
||||||
|
} from "@chevrotain/gast";
|
||||||
|
import {
|
||||||
|
Alternative,
|
||||||
|
containsPath,
|
||||||
|
getLookaheadPathsForOptionalProd,
|
||||||
|
getLookaheadPathsForOr,
|
||||||
|
getProdType,
|
||||||
|
isStrictPrefixOfPath,
|
||||||
|
} from "./lookahead.js";
|
||||||
|
import { nextPossibleTokensAfter } from "./interpreter.js";
|
||||||
|
import {
|
||||||
|
ILookaheadStrategy,
|
||||||
|
IProduction,
|
||||||
|
IProductionWithOccurrence,
|
||||||
|
Rule,
|
||||||
|
TokenType,
|
||||||
|
} from "@chevrotain/types";
|
||||||
|
import {
|
||||||
|
IGrammarValidatorErrorMessageProvider,
|
||||||
|
IParserDefinitionError,
|
||||||
|
} from "./types.js";
|
||||||
|
import { tokenStructuredMatcher } from "../../scan/tokens.js";
|
||||||
|
|
||||||
|
export function validateLookahead(options: {
|
||||||
|
lookaheadStrategy: ILookaheadStrategy;
|
||||||
|
rules: Rule[];
|
||||||
|
tokenTypes: TokenType[];
|
||||||
|
grammarName: string;
|
||||||
|
}): IParserDefinitionError[] {
|
||||||
|
const lookaheadValidationErrorMessages = options.lookaheadStrategy.validate({
|
||||||
|
rules: options.rules,
|
||||||
|
tokenTypes: options.tokenTypes,
|
||||||
|
grammarName: options.grammarName,
|
||||||
|
});
|
||||||
|
return map(lookaheadValidationErrorMessages, (errorMessage) => ({
|
||||||
|
type: ParserDefinitionErrorType.CUSTOM_LOOKAHEAD_VALIDATION,
|
||||||
|
...errorMessage,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateGrammar(
|
||||||
|
topLevels: Rule[],
|
||||||
|
tokenTypes: TokenType[],
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
grammarName: string,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const duplicateErrors: IParserDefinitionError[] = flatMap(
|
||||||
|
topLevels,
|
||||||
|
(currTopLevel) =>
|
||||||
|
validateDuplicateProductions(currTopLevel, errMsgProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
const termsNamespaceConflictErrors = checkTerminalAndNoneTerminalsNameSpace(
|
||||||
|
topLevels,
|
||||||
|
tokenTypes,
|
||||||
|
errMsgProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
const tooManyAltsErrors = flatMap(topLevels, (curRule) =>
|
||||||
|
validateTooManyAlts(curRule, errMsgProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
const duplicateRulesError = flatMap(topLevels, (curRule) =>
|
||||||
|
validateRuleDoesNotAlreadyExist(
|
||||||
|
curRule,
|
||||||
|
topLevels,
|
||||||
|
grammarName,
|
||||||
|
errMsgProvider,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return duplicateErrors.concat(
|
||||||
|
termsNamespaceConflictErrors,
|
||||||
|
tooManyAltsErrors,
|
||||||
|
duplicateRulesError,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateDuplicateProductions(
|
||||||
|
topLevelRule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserDuplicatesDefinitionError[] {
|
||||||
|
const collectorVisitor = new OccurrenceValidationCollector();
|
||||||
|
topLevelRule.accept(collectorVisitor);
|
||||||
|
const allRuleProductions = collectorVisitor.allProductions;
|
||||||
|
|
||||||
|
const productionGroups = groupBy(
|
||||||
|
allRuleProductions,
|
||||||
|
identifyProductionForDuplicates,
|
||||||
|
);
|
||||||
|
|
||||||
|
const duplicates: any = pickBy(productionGroups, (currGroup) => {
|
||||||
|
return currGroup.length > 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const errors = map(values(duplicates), (currDuplicates: any) => {
|
||||||
|
const firstProd: any = first(currDuplicates);
|
||||||
|
const msg = errMsgProvider.buildDuplicateFoundError(
|
||||||
|
topLevelRule,
|
||||||
|
currDuplicates,
|
||||||
|
);
|
||||||
|
const dslName = getProductionDslName(firstProd);
|
||||||
|
const defError: IParserDuplicatesDefinitionError = {
|
||||||
|
message: msg,
|
||||||
|
type: ParserDefinitionErrorType.DUPLICATE_PRODUCTIONS,
|
||||||
|
ruleName: topLevelRule.name,
|
||||||
|
dslName: dslName,
|
||||||
|
occurrence: firstProd.idx,
|
||||||
|
};
|
||||||
|
|
||||||
|
const param = getExtraProductionArgument(firstProd);
|
||||||
|
if (param) {
|
||||||
|
defError.parameter = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defError;
|
||||||
|
});
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function identifyProductionForDuplicates(
|
||||||
|
prod: IProductionWithOccurrence,
|
||||||
|
): string {
|
||||||
|
return `${getProductionDslName(prod)}_#_${
|
||||||
|
prod.idx
|
||||||
|
}_#_${getExtraProductionArgument(prod)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExtraProductionArgument(prod: IProductionWithOccurrence): string {
|
||||||
|
if (prod instanceof Terminal) {
|
||||||
|
return prod.terminalType.name;
|
||||||
|
} else if (prod instanceof NonTerminal) {
|
||||||
|
return prod.nonTerminalName;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OccurrenceValidationCollector extends GAstVisitor {
|
||||||
|
public allProductions: IProductionWithOccurrence[] = [];
|
||||||
|
|
||||||
|
public visitNonTerminal(subrule: NonTerminal): void {
|
||||||
|
this.allProductions.push(subrule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitOption(option: Option): void {
|
||||||
|
this.allProductions.push(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetitionWithSeparator(manySep: RepetitionWithSeparator): void {
|
||||||
|
this.allProductions.push(manySep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetitionMandatory(atLeastOne: RepetitionMandatory): void {
|
||||||
|
this.allProductions.push(atLeastOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetitionMandatoryWithSeparator(
|
||||||
|
atLeastOneSep: RepetitionMandatoryWithSeparator,
|
||||||
|
): void {
|
||||||
|
this.allProductions.push(atLeastOneSep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetition(many: Repetition): void {
|
||||||
|
this.allProductions.push(many);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitAlternation(or: Alternation): void {
|
||||||
|
this.allProductions.push(or);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitTerminal(terminal: Terminal): void {
|
||||||
|
this.allProductions.push(terminal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateRuleDoesNotAlreadyExist(
|
||||||
|
rule: Rule,
|
||||||
|
allRules: Rule[],
|
||||||
|
className: string,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const errors = [];
|
||||||
|
const occurrences = reduce(
|
||||||
|
allRules,
|
||||||
|
(result, curRule) => {
|
||||||
|
if (curRule.name === rule.name) {
|
||||||
|
return result + 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
if (occurrences > 1) {
|
||||||
|
const errMsg = errMsgProvider.buildDuplicateRuleNameError({
|
||||||
|
topLevelRule: rule,
|
||||||
|
grammarName: className,
|
||||||
|
});
|
||||||
|
errors.push({
|
||||||
|
message: errMsg,
|
||||||
|
type: ParserDefinitionErrorType.DUPLICATE_RULE_NAME,
|
||||||
|
ruleName: rule.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: is there anyway to get only the rule names of rules inherited from the super grammars?
|
||||||
|
// This is not part of the IGrammarErrorProvider because the validation cannot be performed on
|
||||||
|
// The grammar structure, only at runtime.
|
||||||
|
export function validateRuleIsOverridden(
|
||||||
|
ruleName: string,
|
||||||
|
definedRulesNames: string[],
|
||||||
|
className: string,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const errors = [];
|
||||||
|
let errMsg;
|
||||||
|
|
||||||
|
if (!includes(definedRulesNames, ruleName)) {
|
||||||
|
errMsg =
|
||||||
|
`Invalid rule override, rule: ->${ruleName}<- cannot be overridden in the grammar: ->${className}<-` +
|
||||||
|
`as it is not defined in any of the super grammars `;
|
||||||
|
errors.push({
|
||||||
|
message: errMsg,
|
||||||
|
type: ParserDefinitionErrorType.INVALID_RULE_OVERRIDE,
|
||||||
|
ruleName: ruleName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateNoLeftRecursion(
|
||||||
|
topRule: Rule,
|
||||||
|
currRule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
path: Rule[] = [],
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const errors: IParserDefinitionError[] = [];
|
||||||
|
const nextNonTerminals = getFirstNoneTerminal(currRule.definition);
|
||||||
|
if (isEmpty(nextNonTerminals)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
const ruleName = topRule.name;
|
||||||
|
const foundLeftRecursion = includes(nextNonTerminals, topRule);
|
||||||
|
if (foundLeftRecursion) {
|
||||||
|
errors.push({
|
||||||
|
message: errMsgProvider.buildLeftRecursionError({
|
||||||
|
topLevelRule: topRule,
|
||||||
|
leftRecursionPath: path,
|
||||||
|
}),
|
||||||
|
type: ParserDefinitionErrorType.LEFT_RECURSION,
|
||||||
|
ruleName: ruleName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are only looking for cyclic paths leading back to the specific topRule
|
||||||
|
// other cyclic paths are ignored, we still need this difference to avoid infinite loops...
|
||||||
|
const validNextSteps = difference(nextNonTerminals, path.concat([topRule]));
|
||||||
|
const errorsFromNextSteps = flatMap(validNextSteps, (currRefRule) => {
|
||||||
|
const newPath = clone(path);
|
||||||
|
newPath.push(currRefRule);
|
||||||
|
return validateNoLeftRecursion(
|
||||||
|
topRule,
|
||||||
|
currRefRule,
|
||||||
|
errMsgProvider,
|
||||||
|
newPath,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors.concat(errorsFromNextSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFirstNoneTerminal(definition: IProduction[]): Rule[] {
|
||||||
|
let result: Rule[] = [];
|
||||||
|
if (isEmpty(definition)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const firstProd = first(definition);
|
||||||
|
|
||||||
|
/* istanbul ignore else */
|
||||||
|
if (firstProd instanceof NonTerminal) {
|
||||||
|
result.push(firstProd.referencedRule);
|
||||||
|
} else if (
|
||||||
|
firstProd instanceof AlternativeGAST ||
|
||||||
|
firstProd instanceof Option ||
|
||||||
|
firstProd instanceof RepetitionMandatory ||
|
||||||
|
firstProd instanceof RepetitionMandatoryWithSeparator ||
|
||||||
|
firstProd instanceof RepetitionWithSeparator ||
|
||||||
|
firstProd instanceof Repetition
|
||||||
|
) {
|
||||||
|
result = result.concat(
|
||||||
|
getFirstNoneTerminal(<IProduction[]>firstProd.definition),
|
||||||
|
);
|
||||||
|
} else if (firstProd instanceof Alternation) {
|
||||||
|
// each sub definition in alternation is a FLAT
|
||||||
|
result = flatten(
|
||||||
|
map(firstProd.definition, (currSubDef) =>
|
||||||
|
getFirstNoneTerminal((<AlternativeGAST>currSubDef).definition),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (firstProd instanceof Terminal) {
|
||||||
|
// nothing to see, move along
|
||||||
|
} else {
|
||||||
|
throw Error("non exhaustive match");
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFirstOptional = isOptionalProd(firstProd);
|
||||||
|
const hasMore = definition.length > 1;
|
||||||
|
if (isFirstOptional && hasMore) {
|
||||||
|
const rest = drop(definition);
|
||||||
|
return result.concat(getFirstNoneTerminal(rest));
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrCollector extends GAstVisitor {
|
||||||
|
public alternations: Alternation[] = [];
|
||||||
|
|
||||||
|
public visitAlternation(node: Alternation): void {
|
||||||
|
this.alternations.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateEmptyOrAlternative(
|
||||||
|
topLevelRule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserEmptyAlternativeDefinitionError[] {
|
||||||
|
const orCollector = new OrCollector();
|
||||||
|
topLevelRule.accept(orCollector);
|
||||||
|
const ors = orCollector.alternations;
|
||||||
|
|
||||||
|
const errors = flatMap<Alternation, IParserEmptyAlternativeDefinitionError>(
|
||||||
|
ors,
|
||||||
|
(currOr) => {
|
||||||
|
const exceptLast = dropRight(currOr.definition);
|
||||||
|
return flatMap(exceptLast, (currAlternative, currAltIdx) => {
|
||||||
|
const possibleFirstInAlt = nextPossibleTokensAfter(
|
||||||
|
[currAlternative],
|
||||||
|
[],
|
||||||
|
tokenStructuredMatcher,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
if (isEmpty(possibleFirstInAlt)) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
message: errMsgProvider.buildEmptyAlternationError({
|
||||||
|
topLevelRule: topLevelRule,
|
||||||
|
alternation: currOr,
|
||||||
|
emptyChoiceIdx: currAltIdx,
|
||||||
|
}),
|
||||||
|
type: ParserDefinitionErrorType.NONE_LAST_EMPTY_ALT,
|
||||||
|
ruleName: topLevelRule.name,
|
||||||
|
occurrence: currOr.idx,
|
||||||
|
alternative: currAltIdx + 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateAmbiguousAlternationAlternatives(
|
||||||
|
topLevelRule: Rule,
|
||||||
|
globalMaxLookahead: number,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserAmbiguousAlternativesDefinitionError[] {
|
||||||
|
const orCollector = new OrCollector();
|
||||||
|
topLevelRule.accept(orCollector);
|
||||||
|
let ors = orCollector.alternations;
|
||||||
|
|
||||||
|
// New Handling of ignoring ambiguities
|
||||||
|
// - https://github.com/chevrotain/chevrotain/issues/869
|
||||||
|
ors = reject(ors, (currOr) => currOr.ignoreAmbiguities === true);
|
||||||
|
|
||||||
|
const errors = flatMap(ors, (currOr: Alternation) => {
|
||||||
|
const currOccurrence = currOr.idx;
|
||||||
|
const actualMaxLookahead = currOr.maxLookahead || globalMaxLookahead;
|
||||||
|
const alternatives = getLookaheadPathsForOr(
|
||||||
|
currOccurrence,
|
||||||
|
topLevelRule,
|
||||||
|
actualMaxLookahead,
|
||||||
|
currOr,
|
||||||
|
);
|
||||||
|
const altsAmbiguityErrors = checkAlternativesAmbiguities(
|
||||||
|
alternatives,
|
||||||
|
currOr,
|
||||||
|
topLevelRule,
|
||||||
|
errMsgProvider,
|
||||||
|
);
|
||||||
|
const altsPrefixAmbiguityErrors = checkPrefixAlternativesAmbiguities(
|
||||||
|
alternatives,
|
||||||
|
currOr,
|
||||||
|
topLevelRule,
|
||||||
|
errMsgProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
return altsAmbiguityErrors.concat(altsPrefixAmbiguityErrors);
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RepetitionCollector extends GAstVisitor {
|
||||||
|
public allProductions: (IProductionWithOccurrence & {
|
||||||
|
maxLookahead?: number;
|
||||||
|
})[] = [];
|
||||||
|
|
||||||
|
public visitRepetitionWithSeparator(manySep: RepetitionWithSeparator): void {
|
||||||
|
this.allProductions.push(manySep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetitionMandatory(atLeastOne: RepetitionMandatory): void {
|
||||||
|
this.allProductions.push(atLeastOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetitionMandatoryWithSeparator(
|
||||||
|
atLeastOneSep: RepetitionMandatoryWithSeparator,
|
||||||
|
): void {
|
||||||
|
this.allProductions.push(atLeastOneSep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public visitRepetition(many: Repetition): void {
|
||||||
|
this.allProductions.push(many);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateTooManyAlts(
|
||||||
|
topLevelRule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const orCollector = new OrCollector();
|
||||||
|
topLevelRule.accept(orCollector);
|
||||||
|
const ors = orCollector.alternations;
|
||||||
|
|
||||||
|
const errors = flatMap(ors, (currOr) => {
|
||||||
|
if (currOr.definition.length > 255) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
message: errMsgProvider.buildTooManyAlternativesError({
|
||||||
|
topLevelRule: topLevelRule,
|
||||||
|
alternation: currOr,
|
||||||
|
}),
|
||||||
|
type: ParserDefinitionErrorType.TOO_MANY_ALTS,
|
||||||
|
ruleName: topLevelRule.name,
|
||||||
|
occurrence: currOr.idx,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateSomeNonEmptyLookaheadPath(
|
||||||
|
topLevelRules: Rule[],
|
||||||
|
maxLookahead: number,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const errors: IParserDefinitionError[] = [];
|
||||||
|
forEach(topLevelRules, (currTopRule) => {
|
||||||
|
const collectorVisitor = new RepetitionCollector();
|
||||||
|
currTopRule.accept(collectorVisitor);
|
||||||
|
const allRuleProductions = collectorVisitor.allProductions;
|
||||||
|
forEach(allRuleProductions, (currProd) => {
|
||||||
|
const prodType = getProdType(currProd);
|
||||||
|
const actualMaxLookahead = currProd.maxLookahead || maxLookahead;
|
||||||
|
const currOccurrence = currProd.idx;
|
||||||
|
const paths = getLookaheadPathsForOptionalProd(
|
||||||
|
currOccurrence,
|
||||||
|
currTopRule,
|
||||||
|
prodType,
|
||||||
|
actualMaxLookahead,
|
||||||
|
);
|
||||||
|
const pathsInsideProduction = paths[0];
|
||||||
|
if (isEmpty(flatten(pathsInsideProduction))) {
|
||||||
|
const errMsg = errMsgProvider.buildEmptyRepetitionError({
|
||||||
|
topLevelRule: currTopRule,
|
||||||
|
repetition: currProd,
|
||||||
|
});
|
||||||
|
errors.push({
|
||||||
|
message: errMsg,
|
||||||
|
type: ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,
|
||||||
|
ruleName: currTopRule.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAmbiguityDescriptor {
|
||||||
|
alts: number[];
|
||||||
|
path: TokenType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAlternativesAmbiguities(
|
||||||
|
alternatives: Alternative[],
|
||||||
|
alternation: Alternation,
|
||||||
|
rule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserAmbiguousAlternativesDefinitionError[] {
|
||||||
|
const foundAmbiguousPaths: Alternative = [];
|
||||||
|
const identicalAmbiguities = reduce(
|
||||||
|
alternatives,
|
||||||
|
(result, currAlt, currAltIdx) => {
|
||||||
|
// ignore (skip) ambiguities with this alternative
|
||||||
|
if (alternation.definition[currAltIdx].ignoreAmbiguities === true) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(currAlt, (currPath) => {
|
||||||
|
const altsCurrPathAppearsIn = [currAltIdx];
|
||||||
|
forEach(alternatives, (currOtherAlt, currOtherAltIdx) => {
|
||||||
|
if (
|
||||||
|
currAltIdx !== currOtherAltIdx &&
|
||||||
|
containsPath(currOtherAlt, currPath) &&
|
||||||
|
// ignore (skip) ambiguities with this "other" alternative
|
||||||
|
alternation.definition[currOtherAltIdx].ignoreAmbiguities !== true
|
||||||
|
) {
|
||||||
|
altsCurrPathAppearsIn.push(currOtherAltIdx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
altsCurrPathAppearsIn.length > 1 &&
|
||||||
|
!containsPath(foundAmbiguousPaths, currPath)
|
||||||
|
) {
|
||||||
|
foundAmbiguousPaths.push(currPath);
|
||||||
|
result.push({
|
||||||
|
alts: altsCurrPathAppearsIn,
|
||||||
|
path: currPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
[] as { alts: number[]; path: TokenType[] }[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const currErrors = map(identicalAmbiguities, (currAmbDescriptor) => {
|
||||||
|
const ambgIndices = map(
|
||||||
|
currAmbDescriptor.alts,
|
||||||
|
(currAltIdx) => currAltIdx + 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
const currMessage = errMsgProvider.buildAlternationAmbiguityError({
|
||||||
|
topLevelRule: rule,
|
||||||
|
alternation: alternation,
|
||||||
|
ambiguityIndices: ambgIndices,
|
||||||
|
prefixPath: currAmbDescriptor.path,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: currMessage,
|
||||||
|
type: ParserDefinitionErrorType.AMBIGUOUS_ALTS,
|
||||||
|
ruleName: rule.name,
|
||||||
|
occurrence: alternation.idx,
|
||||||
|
alternatives: currAmbDescriptor.alts,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return currErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkPrefixAlternativesAmbiguities(
|
||||||
|
alternatives: Alternative[],
|
||||||
|
alternation: Alternation,
|
||||||
|
rule: Rule,
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserAmbiguousAlternativesDefinitionError[] {
|
||||||
|
// flatten
|
||||||
|
const pathsAndIndices = reduce(
|
||||||
|
alternatives,
|
||||||
|
(result, currAlt, idx) => {
|
||||||
|
const currPathsAndIdx = map(currAlt, (currPath) => {
|
||||||
|
return { idx: idx, path: currPath };
|
||||||
|
});
|
||||||
|
return result.concat(currPathsAndIdx);
|
||||||
|
},
|
||||||
|
[] as { idx: number; path: TokenType[] }[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const errors = compact(
|
||||||
|
flatMap(pathsAndIndices, (currPathAndIdx) => {
|
||||||
|
const alternativeGast = alternation.definition[currPathAndIdx.idx];
|
||||||
|
// ignore (skip) ambiguities with this alternative
|
||||||
|
if (alternativeGast.ignoreAmbiguities === true) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const targetIdx = currPathAndIdx.idx;
|
||||||
|
const targetPath = currPathAndIdx.path;
|
||||||
|
|
||||||
|
const prefixAmbiguitiesPathsAndIndices = filter(
|
||||||
|
pathsAndIndices,
|
||||||
|
(searchPathAndIdx) => {
|
||||||
|
// prefix ambiguity can only be created from lower idx (higher priority) path
|
||||||
|
return (
|
||||||
|
// ignore (skip) ambiguities with this "other" alternative
|
||||||
|
alternation.definition[searchPathAndIdx.idx].ignoreAmbiguities !==
|
||||||
|
true &&
|
||||||
|
searchPathAndIdx.idx < targetIdx &&
|
||||||
|
// checking for strict prefix because identical lookaheads
|
||||||
|
// will be be detected using a different validation.
|
||||||
|
isStrictPrefixOfPath(searchPathAndIdx.path, targetPath)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const currPathPrefixErrors = map(
|
||||||
|
prefixAmbiguitiesPathsAndIndices,
|
||||||
|
(currAmbPathAndIdx): IParserAmbiguousAlternativesDefinitionError => {
|
||||||
|
const ambgIndices = [currAmbPathAndIdx.idx + 1, targetIdx + 1];
|
||||||
|
const occurrence = alternation.idx === 0 ? "" : alternation.idx;
|
||||||
|
|
||||||
|
const message = errMsgProvider.buildAlternationPrefixAmbiguityError({
|
||||||
|
topLevelRule: rule,
|
||||||
|
alternation: alternation,
|
||||||
|
ambiguityIndices: ambgIndices,
|
||||||
|
prefixPath: currAmbPathAndIdx.path,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
message: message,
|
||||||
|
type: ParserDefinitionErrorType.AMBIGUOUS_PREFIX_ALTS,
|
||||||
|
ruleName: rule.name,
|
||||||
|
occurrence: occurrence,
|
||||||
|
alternatives: ambgIndices,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return currPathPrefixErrors;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTerminalAndNoneTerminalsNameSpace(
|
||||||
|
topLevels: Rule[],
|
||||||
|
tokenTypes: TokenType[],
|
||||||
|
errMsgProvider: IGrammarValidatorErrorMessageProvider,
|
||||||
|
): IParserDefinitionError[] {
|
||||||
|
const errors: IParserDefinitionError[] = [];
|
||||||
|
|
||||||
|
const tokenNames = map(tokenTypes, (currToken) => currToken.name);
|
||||||
|
|
||||||
|
forEach(topLevels, (currRule) => {
|
||||||
|
const currRuleName = currRule.name;
|
||||||
|
if (includes(tokenNames, currRuleName)) {
|
||||||
|
const errMsg = errMsgProvider.buildNamespaceConflictError(currRule);
|
||||||
|
|
||||||
|
errors.push({
|
||||||
|
message: errMsg,
|
||||||
|
type: ParserDefinitionErrorType.CONFLICT_TOKENS_RULES_NAMESPACE,
|
||||||
|
ruleName: currRuleName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
declare function setToStringTag(
|
||||||
|
object: object & { [Symbol.toStringTag]?: unknown },
|
||||||
|
value: string | unknown,
|
||||||
|
options?: {
|
||||||
|
force?: boolean;
|
||||||
|
nonConfigurable?: boolean;
|
||||||
|
},
|
||||||
|
): void;
|
||||||
|
|
||||||
|
export = setToStringTag;
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
import type {And} from './and.d.ts';
|
||||||
|
import type {ApplyDefaultOptions, Not} from './internal/index.d.ts';
|
||||||
|
import type {IsStringLiteral} from './is-literal.d.ts';
|
||||||
|
import type {Or} from './or.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Split options.
|
||||||
|
|
||||||
|
@see {@link Split}
|
||||||
|
*/
|
||||||
|
export type SplitOptions = {
|
||||||
|
/**
|
||||||
|
When enabled, instantiations with non-literal string types (e.g., `string`, `Uppercase<string>`, `on${string}`) simply return back `string[]` without performing any splitting, as the exact structure cannot be statically determined.
|
||||||
|
|
||||||
|
@default true
|
||||||
|
|
||||||
|
@example
|
||||||
|
```ts
|
||||||
|
import type {Split} from 'type-fest';
|
||||||
|
|
||||||
|
type Example1 = Split<`foo.${string}.bar`, '.', {strictLiteralChecks: false}>;
|
||||||
|
//=> ['foo', string, 'bar']
|
||||||
|
|
||||||
|
type Example2 = Split<`foo.${string}`, '.', {strictLiteralChecks: true}>;
|
||||||
|
//=> string[]
|
||||||
|
|
||||||
|
type Example3 = Split<'foobarbaz', `b${string}`, {strictLiteralChecks: false}>;
|
||||||
|
//=> ['foo', 'r', 'z']
|
||||||
|
|
||||||
|
type Example4 = Split<'foobarbaz', `b${string}`, {strictLiteralChecks: true}>;
|
||||||
|
//=> string[]
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
strictLiteralChecks?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DefaultSplitOptions = {
|
||||||
|
strictLiteralChecks: true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Represents an array of strings split using a given character or character set.
|
||||||
|
|
||||||
|
Use-case: Defining the return type of a method like `String.prototype.split`.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {Split} from 'type-fest';
|
||||||
|
|
||||||
|
declare function split<S extends string, D extends string>(string: S, separator: D): Split<S, D>;
|
||||||
|
|
||||||
|
type Item = 'foo' | 'bar' | 'baz' | 'waldo';
|
||||||
|
const items = 'foo,bar,baz,waldo';
|
||||||
|
const array: Item[] = split(items, ',');
|
||||||
|
```
|
||||||
|
|
||||||
|
@see {@link SplitOptions}
|
||||||
|
|
||||||
|
@category String
|
||||||
|
@category Template literal
|
||||||
|
*/
|
||||||
|
export type Split<
|
||||||
|
S extends string,
|
||||||
|
Delimiter extends string,
|
||||||
|
Options extends SplitOptions = {},
|
||||||
|
> =
|
||||||
|
SplitHelper<S, Delimiter, ApplyDefaultOptions<SplitOptions, DefaultSplitOptions, Options>>;
|
||||||
|
|
||||||
|
type SplitHelper<
|
||||||
|
S extends string,
|
||||||
|
Delimiter extends string,
|
||||||
|
Options extends Required<SplitOptions>,
|
||||||
|
Accumulator extends string[] = [],
|
||||||
|
> = S extends string // For distributing `S`
|
||||||
|
? Delimiter extends string // For distributing `Delimiter`
|
||||||
|
// If `strictLiteralChecks` is `false` OR `S` and `Delimiter` both are string literals, then perform the split
|
||||||
|
? Or<Not<Options['strictLiteralChecks']>, And<IsStringLiteral<S>, IsStringLiteral<Delimiter>>> extends true
|
||||||
|
? S extends `${infer Head}${Delimiter}${infer Tail}`
|
||||||
|
? SplitHelper<Tail, Delimiter, Options, [...Accumulator, Head]>
|
||||||
|
: Delimiter extends ''
|
||||||
|
? S extends ''
|
||||||
|
? Accumulator
|
||||||
|
: [...Accumulator, S]
|
||||||
|
: [...Accumulator, S]
|
||||||
|
// Otherwise, return `string[]`
|
||||||
|
: string[]
|
||||||
|
: never // Should never happen
|
||||||
|
: never; // Should never happen
|
||||||
|
|
||||||
|
export {};
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import arrayShuffle from './_arrayShuffle.js';
|
||||||
|
import baseShuffle from './_baseShuffle.js';
|
||||||
|
import isArray from './isArray.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of shuffled values, using a version of the
|
||||||
|
* [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 0.1.0
|
||||||
|
* @category Collection
|
||||||
|
* @param {Array|Object} collection The collection to shuffle.
|
||||||
|
* @returns {Array} Returns the new shuffled array.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.shuffle([1, 2, 3, 4]);
|
||||||
|
* // => [4, 1, 3, 2]
|
||||||
|
*/
|
||||||
|
function shuffle(collection) {
|
||||||
|
var func = isArray(collection) ? arrayShuffle : baseShuffle;
|
||||||
|
return func(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default shuffle;
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import { defaults, forEach } from "lodash-es";
|
||||||
|
import { resolveGrammar as orgResolveGrammar } from "../resolver.js";
|
||||||
|
import { validateGrammar as orgValidateGrammar } from "../checks.js";
|
||||||
|
import { defaultGrammarResolverErrorProvider, defaultGrammarValidatorErrorProvider, } from "../../errors_public.js";
|
||||||
|
export function resolveGrammar(options) {
|
||||||
|
const actualOptions = defaults(options, {
|
||||||
|
errMsgProvider: defaultGrammarResolverErrorProvider,
|
||||||
|
});
|
||||||
|
const topRulesTable = {};
|
||||||
|
forEach(options.rules, (rule) => {
|
||||||
|
topRulesTable[rule.name] = rule;
|
||||||
|
});
|
||||||
|
return orgResolveGrammar(topRulesTable, actualOptions.errMsgProvider);
|
||||||
|
}
|
||||||
|
export function validateGrammar(options) {
|
||||||
|
options = defaults(options, {
|
||||||
|
errMsgProvider: defaultGrammarValidatorErrorProvider,
|
||||||
|
});
|
||||||
|
return orgValidateGrammar(options.rules, options.tokenTypes, options.errMsgProvider, options.grammarName);
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=gast_resolver_public.js.map
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
import { v4 as v4$1, v6 as v6$1 } from "cidr-regex";
|
||||||
|
const re4 = v4$1({ exact: true });
|
||||||
|
const re6 = v6$1({ exact: true });
|
||||||
|
const isCidr = (str) => re4.test(str) ? 4 : re6.test(str) ? 6 : 0;
|
||||||
|
const v4 = isCidr.v4 = (str) => re4.test(str);
|
||||||
|
const v6 = isCidr.v6 = (str) => re6.test(str);
|
||||||
|
export {
|
||||||
|
isCidr as default,
|
||||||
|
v4,
|
||||||
|
v6
|
||||||
|
};
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('toPath', require('../toPath'), require('./_falseOptions'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
import {verboseLog} from './log.js';
|
||||||
|
|
||||||
|
// When `verbose` is `short|full|custom`, print each command's error when it fails
|
||||||
|
export const logError = (result, verboseInfo) => {
|
||||||
|
if (result.failed) {
|
||||||
|
verboseLog({
|
||||||
|
type: 'error',
|
||||||
|
verboseMessage: result.shortMessage,
|
||||||
|
verboseInfo,
|
||||||
|
result,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = require('neostandard')({
|
||||||
|
ignores: require('neostandard').resolveIgnoresFromGitignore(),
|
||||||
|
ts: true
|
||||||
|
})
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('toSafeInteger', require('../toSafeInteger'), require('./_falseOptions'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
import type {ObjectValue} from './internal/index.d.ts';
|
||||||
|
import type {ArrayElement} from './array-element.d.ts';
|
||||||
|
import type {IsEqual} from './is-equal.d.ts';
|
||||||
|
import type {KeysOfUnion} from './keys-of-union.d.ts';
|
||||||
|
import type {IsUnknown} from './is-unknown.d.ts';
|
||||||
|
import type {Primitive} from './primitive.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a type from `ParameterType` and `InputType` and change keys exclusive to `InputType` to `never`.
|
||||||
|
- Generate a list of keys that exists in `InputType` but not in `ParameterType`.
|
||||||
|
- Mark these excess keys as `never`.
|
||||||
|
*/
|
||||||
|
type ExactObject<ParameterType, InputType> = {[Key in keyof ParameterType]: Exact<ParameterType[Key], ObjectValue<InputType, Key>>}
|
||||||
|
& Record<Exclude<keyof InputType, KeysOfUnion<ParameterType>>, never>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a type that does not allow extra properties, meaning it only allows properties that are explicitly declared.
|
||||||
|
|
||||||
|
This is useful for function type-guarding to reject arguments with excess properties. Due to the nature of TypeScript, it does not complain if excess properties are provided unless the provided value is an object literal.
|
||||||
|
|
||||||
|
*Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/12936) if you want to have this type as a built-in in TypeScript.*
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
type OnlyAcceptName = {name: string};
|
||||||
|
|
||||||
|
declare function onlyAcceptName(arguments_: OnlyAcceptName): void;
|
||||||
|
|
||||||
|
// TypeScript complains about excess properties when an object literal is provided.
|
||||||
|
// @ts-expect-error
|
||||||
|
onlyAcceptName({name: 'name', id: 1});
|
||||||
|
// `id` is excess
|
||||||
|
|
||||||
|
// TypeScript does not complain about excess properties when the provided value is a variable (not an object literal).
|
||||||
|
const invalidInput = {name: 'name', id: 1};
|
||||||
|
onlyAcceptName(invalidInput); // No errors
|
||||||
|
```
|
||||||
|
|
||||||
|
Having `Exact` allows TypeScript to reject excess properties.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {Exact} from 'type-fest';
|
||||||
|
|
||||||
|
type OnlyAcceptName = {name: string};
|
||||||
|
|
||||||
|
declare function onlyAcceptNameImproved<T extends Exact<OnlyAcceptName, T>>(arguments_: T): void;
|
||||||
|
|
||||||
|
const invalidInput = {name: 'name', id: 1};
|
||||||
|
// @ts-expect-error
|
||||||
|
onlyAcceptNameImproved(invalidInput); // Compilation error
|
||||||
|
```
|
||||||
|
|
||||||
|
[Read more](https://stackoverflow.com/questions/49580725/is-it-possible-to-restrict-typescript-object-to-contain-only-properties-defined)
|
||||||
|
|
||||||
|
@category Utilities
|
||||||
|
*/
|
||||||
|
export type Exact<ParameterType, InputType> =
|
||||||
|
// Before distributing, check if the two types are equal and if so, return the parameter type immediately
|
||||||
|
IsEqual<ParameterType, InputType> extends true ? ParameterType
|
||||||
|
// If the parameter is a primitive, return it as is immediately to avoid it being converted to a complex type
|
||||||
|
: ParameterType extends Primitive ? ParameterType
|
||||||
|
// If the parameter is an unknown, return it as is immediately to avoid it being converted to a complex type
|
||||||
|
: IsUnknown<ParameterType> extends true ? unknown
|
||||||
|
// If the parameter is a Function, return it as is because this type is not capable of handling function, leave it to TypeScript
|
||||||
|
: ParameterType extends Function ? ParameterType
|
||||||
|
// Convert union of array to array of union: A[] & B[] => (A & B)[]
|
||||||
|
: ParameterType extends unknown[] ? Array<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
|
||||||
|
// In TypeScript, Array is a subtype of ReadonlyArray, so always test Array before ReadonlyArray.
|
||||||
|
: ParameterType extends readonly unknown[] ? ReadonlyArray<Exact<ArrayElement<ParameterType>, ArrayElement<InputType>>>
|
||||||
|
: ExactObject<ParameterType, InputType>;
|
||||||
|
|
||||||
|
export {};
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/** Used as references for various `Number` constants. */
|
||||||
|
var MAX_SAFE_INTEGER = 9007199254740991;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is a valid array-like length.
|
||||||
|
*
|
||||||
|
* **Note:** This method is loosely based on
|
||||||
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @since 4.0.0
|
||||||
|
* @category Lang
|
||||||
|
* @param {*} value The value to check.
|
||||||
|
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.isLength(3);
|
||||||
|
* // => true
|
||||||
|
*
|
||||||
|
* _.isLength(Number.MIN_VALUE);
|
||||||
|
* // => false
|
||||||
|
*
|
||||||
|
* _.isLength(Infinity);
|
||||||
|
* // => false
|
||||||
|
*
|
||||||
|
* _.isLength('3');
|
||||||
|
* // => false
|
||||||
|
*/
|
||||||
|
function isLength(value) {
|
||||||
|
return typeof value == 'number' &&
|
||||||
|
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default isLength;
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
var baseRest = require('./_baseRest'),
|
||||||
|
isIterateeCall = require('./_isIterateeCall');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function like `_.assign`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Function} assigner The function to assign values.
|
||||||
|
* @returns {Function} Returns the new assigner function.
|
||||||
|
*/
|
||||||
|
function createAssigner(assigner) {
|
||||||
|
return baseRest(function(object, sources) {
|
||||||
|
var index = -1,
|
||||||
|
length = sources.length,
|
||||||
|
customizer = length > 1 ? sources[length - 1] : undefined,
|
||||||
|
guard = length > 2 ? sources[2] : undefined;
|
||||||
|
|
||||||
|
customizer = (assigner.length > 3 && typeof customizer == 'function')
|
||||||
|
? (length--, customizer)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
||||||
|
customizer = length < 3 ? undefined : customizer;
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
object = Object(object);
|
||||||
|
while (++index < length) {
|
||||||
|
var source = sources[index];
|
||||||
|
if (source) {
|
||||||
|
assigner(object, source, index, customizer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createAssigner;
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import eslintJs from "@eslint/js";
|
||||||
|
import eslintConfigPrettier from "eslint-config-prettier";
|
||||||
|
import globals from "globals";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
eslintJs.configs.recommended,
|
||||||
|
eslintConfigPrettier,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.builtin,
|
||||||
|
...globals.jest,
|
||||||
|
...globals.node
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"no-unused-vars": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ ignores: ["bin/languages.js", "dist"] }
|
||||||
|
];
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
var convert = require('./convert'),
|
||||||
|
func = convert('isDate', require('../isDate'), require('./_falseOptions'));
|
||||||
|
|
||||||
|
func.placeholder = require('./placeholder');
|
||||||
|
module.exports = func;
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "array-union",
|
||||||
|
"version": "2.1.0",
|
||||||
|
"description": "Create an array of unique values, in order, from the input arrays",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/array-union",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && ava && tsd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"index.d.ts"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"array",
|
||||||
|
"set",
|
||||||
|
"uniq",
|
||||||
|
"unique",
|
||||||
|
"duplicate",
|
||||||
|
"remove",
|
||||||
|
"union",
|
||||||
|
"combine",
|
||||||
|
"merge"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "^1.4.1",
|
||||||
|
"tsd": "^0.7.2",
|
||||||
|
"xo": "^0.24.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ErrorReportingMixinBase = require('./mixin-base');
|
||||||
|
const ErrorReportingTokenizerMixin = require('./tokenizer-mixin');
|
||||||
|
const LocationInfoTokenizerMixin = require('../location-info/tokenizer-mixin');
|
||||||
|
const Mixin = require('../../utils/mixin');
|
||||||
|
|
||||||
|
class ErrorReportingParserMixin extends ErrorReportingMixinBase {
|
||||||
|
constructor(parser, opts) {
|
||||||
|
super(parser, opts);
|
||||||
|
|
||||||
|
this.opts = opts;
|
||||||
|
this.ctLoc = null;
|
||||||
|
this.locBeforeToken = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setErrorLocation(err) {
|
||||||
|
if (this.ctLoc) {
|
||||||
|
err.startLine = this.ctLoc.startLine;
|
||||||
|
err.startCol = this.ctLoc.startCol;
|
||||||
|
err.startOffset = this.ctLoc.startOffset;
|
||||||
|
|
||||||
|
err.endLine = this.locBeforeToken ? this.ctLoc.startLine : this.ctLoc.endLine;
|
||||||
|
err.endCol = this.locBeforeToken ? this.ctLoc.startCol : this.ctLoc.endCol;
|
||||||
|
err.endOffset = this.locBeforeToken ? this.ctLoc.startOffset : this.ctLoc.endOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getOverriddenMethods(mxn, orig) {
|
||||||
|
return {
|
||||||
|
_bootstrap(document, fragmentContext) {
|
||||||
|
orig._bootstrap.call(this, document, fragmentContext);
|
||||||
|
|
||||||
|
Mixin.install(this.tokenizer, ErrorReportingTokenizerMixin, mxn.opts);
|
||||||
|
Mixin.install(this.tokenizer, LocationInfoTokenizerMixin);
|
||||||
|
},
|
||||||
|
|
||||||
|
_processInputToken(token) {
|
||||||
|
mxn.ctLoc = token.location;
|
||||||
|
|
||||||
|
orig._processInputToken.call(this, token);
|
||||||
|
},
|
||||||
|
|
||||||
|
_err(code, options) {
|
||||||
|
mxn.locBeforeToken = options && options.beforeToken;
|
||||||
|
mxn._reportError(code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ErrorReportingParserMixin;
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import type {IsNull} from './is-null.d.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
An if-else-like type that resolves depending on whether the given type is `null`.
|
||||||
|
|
||||||
|
@deprecated This type will be removed in the next major version. Use the {@link If} type instead.
|
||||||
|
|
||||||
|
@see {@link IsNull}
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import type {IfNull} from 'type-fest';
|
||||||
|
|
||||||
|
type ShouldBeTrue = IfNull<null>;
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
type ShouldBeBar = IfNull<'not null', 'foo', 'bar'>;
|
||||||
|
//=> 'bar'
|
||||||
|
```
|
||||||
|
|
||||||
|
@category Type Guard
|
||||||
|
@category Utilities
|
||||||
|
*/
|
||||||
|
export type IfNull<T, TypeIfNull = true, TypeIfNotNull = false> = (
|
||||||
|
IsNull<T> extends true ? TypeIfNull : TypeIfNotNull
|
||||||
|
);
|
||||||
|
|
||||||
|
export {};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user