Finish removing tfjs-node
This commit is contained in:
1 parent
2fca1d5e74
commit
9ea4666211
590 files changed
+1
-97455
No files matched your search
Generated
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, Tanh, TanhInputs} from '@tensorflow/tfjs';
|
||||
import {NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const tanhConfig: KernelConfig = {
|
||||
kernelName: Tanh,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x} = args.inputs as TanhInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
|
||||
return backend.executeSingleInput(Tanh, x);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, tensor1d, Tile, TileAttrs, TileInputs} from '@tensorflow/tfjs';
|
||||
|
||||
import {createTensorsTypeOpAttr, NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const tileConfig: KernelConfig = {
|
||||
kernelName: Tile,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x} = args.inputs as TileInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
const {reps} = args.attrs as {} as TileAttrs;
|
||||
|
||||
const opAttrs = [
|
||||
createTensorsTypeOpAttr('T', x.dtype),
|
||||
createTensorsTypeOpAttr('Tmultiples', 'int32')
|
||||
];
|
||||
const multiples = tensor1d(reps, 'int32');
|
||||
const res = backend.executeSingleOutput(Tile, opAttrs, [x, multiples]);
|
||||
multiples.dispose();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-46
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, scalar, TopK, TopKAttrs, TopKInputs} from '@tensorflow/tfjs';
|
||||
import {isNullOrUndefined} from 'util';
|
||||
|
||||
import {createTensorsTypeOpAttr, NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const topKConfig: KernelConfig = {
|
||||
kernelName: TopK,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x} = args.inputs as TopKInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
const {k, sorted} = args.attrs as {} as TopKAttrs;
|
||||
|
||||
const kCount = isNullOrUndefined(k) ? 1 : k;
|
||||
const isSorted = isNullOrUndefined(sorted) ? true : sorted;
|
||||
const opAttrs = [
|
||||
{name: 'sorted', type: backend.binding.TF_ATTR_BOOL, value: isSorted},
|
||||
createTensorsTypeOpAttr('T', x.dtype),
|
||||
];
|
||||
const kTensor = scalar(kCount, 'int32');
|
||||
|
||||
// 'TopKV2' has two-hard coded output attributes:
|
||||
// TODO(yassogba) consider renamine constant in kernel names;
|
||||
const res =
|
||||
backend.executeMultipleOutputs('TopKV2', opAttrs, [x, kTensor], 2);
|
||||
kTensor.dispose();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-40
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, tensor1d, Transpose, TransposeAttrs, TransposeInputs} from '@tensorflow/tfjs';
|
||||
|
||||
import {createTensorsTypeOpAttr, NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const transposeConfig: KernelConfig = {
|
||||
kernelName: Transpose,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x} = args.inputs as TransposeInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
const {perm} = args.attrs as {} as TransposeAttrs;
|
||||
|
||||
const permTensor = tensor1d(perm, 'int32');
|
||||
const opAttrs = [
|
||||
createTensorsTypeOpAttr('T', x.dtype),
|
||||
createTensorsTypeOpAttr('Tperm', 'int32')
|
||||
];
|
||||
const res =
|
||||
backend.executeSingleOutput(Transpose, opAttrs, [x, permTensor]);
|
||||
permTensor.dispose();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-46
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, Unpack, UnpackAttrs, UnpackInputs} from '@tensorflow/tfjs';
|
||||
|
||||
import {createTensorsTypeOpAttr, NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const unpackConfig: KernelConfig = {
|
||||
kernelName: Unpack,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {value} = args.inputs as UnpackInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
let {axis} = args.attrs as {} as UnpackAttrs;
|
||||
|
||||
if (axis < 0) {
|
||||
axis += value.shape.length;
|
||||
}
|
||||
|
||||
if (axis >= value.shape.length) {
|
||||
throw new Error(
|
||||
`Invalid axis supplied: ${axis} shape length: ${value.shape.length}`);
|
||||
}
|
||||
const num = value.shape[axis];
|
||||
const opAttrs = [
|
||||
{name: 'num', type: backend.binding.TF_ATTR_INT, value: num},
|
||||
createTensorsTypeOpAttr('T', value.dtype),
|
||||
{name: 'axis', type: backend.binding.TF_ATTR_INT, value: axis}
|
||||
];
|
||||
return backend.executeMultipleOutputs(Unpack, opAttrs, [value], num);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, scalar, UnsortedSegmentSum, UnsortedSegmentSumAttrs, UnsortedSegmentSumInputs} from '@tensorflow/tfjs';
|
||||
|
||||
import {createTensorsTypeOpAttr, NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const unsortedSegmentSumConfig: KernelConfig = {
|
||||
kernelName: UnsortedSegmentSum,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x, segmentIds} = args.inputs as UnsortedSegmentSumInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
const {numSegments} = args.attrs as {} as UnsortedSegmentSumAttrs;
|
||||
|
||||
const opAttrs = [
|
||||
createTensorsTypeOpAttr('T', x.dtype),
|
||||
createTensorsTypeOpAttr('Tindices', 'int32'),
|
||||
createTensorsTypeOpAttr('Tnumsegments', 'int32')
|
||||
];
|
||||
const numSegmentsT = scalar(numSegments, 'int32');
|
||||
const res = backend.executeSingleOutput(
|
||||
UnsortedSegmentSum, opAttrs, [x, segmentIds, numSegmentsT]);
|
||||
numSegmentsT.dispose();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-35
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {KernelConfig, ZerosLike, ZerosLikeInputs} from '@tensorflow/tfjs';
|
||||
import {NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const zerosLikeConfig: KernelConfig = {
|
||||
kernelName: ZerosLike,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {x} = args.inputs as ZerosLikeInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
|
||||
const opAttrs = [{
|
||||
name: 'T',
|
||||
type: backend.binding.TF_ATTR_TYPE,
|
||||
value: backend.getDTypeInteger(x.dtype)
|
||||
}];
|
||||
return backend.executeSingleOutput(ZerosLike, opAttrs, [x]);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {_FusedMatMul, _FusedMatMulAttrs, _FusedMatMulInputs, add, KernelConfig, matMul, Tensor, Tensor3D, tidy} from '@tensorflow/tfjs';
|
||||
|
||||
import {NodeJSKernelBackend} from '../nodejs_kernel_backend';
|
||||
|
||||
export const _fusedMatMulConfig: KernelConfig = {
|
||||
kernelName: _FusedMatMul,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: (args) => {
|
||||
const {a, b, bias, preluActivationWeights} =
|
||||
args.inputs as _FusedMatMulInputs;
|
||||
const backend = args.backend as NodeJSKernelBackend;
|
||||
const {transposeA, transposeB, activation, leakyreluAlpha} =
|
||||
args.attrs as {} as _FusedMatMulAttrs;
|
||||
|
||||
// Core TensorFlow does not have a fused BatchMatMul op. Combine calls to
|
||||
// achieve the same results:
|
||||
return tidy(() => {
|
||||
let result: Tensor3D =
|
||||
matMul(a as Tensor, b as Tensor, transposeA, transposeB);
|
||||
if (bias != null) {
|
||||
result = add(result, bias as Tensor);
|
||||
}
|
||||
|
||||
result = backend.applyActivation(
|
||||
result, activation, preluActivationWeights as Tensor, leakyreluAlpha);
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-40
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Public API symbols under the tf.node.* namespace.
|
||||
*/
|
||||
|
||||
import {tensorBoard} from './callbacks';
|
||||
import {decodeBmp, decodeGif, decodeImage, decodeJpeg, decodePng, encodeJpeg, encodePng} from './image';
|
||||
import {getMetaGraphsFromSavedModel, getNumOfSavedModels, loadSavedModel} from './saved_model';
|
||||
import {summaryFileWriter} from './tensorboard';
|
||||
|
||||
export const node = {
|
||||
decodeImage,
|
||||
decodeBmp,
|
||||
decodeGif,
|
||||
decodePng,
|
||||
decodeJpeg,
|
||||
encodeJpeg,
|
||||
encodePng,
|
||||
summaryFileWriter,
|
||||
tensorBoard,
|
||||
getMetaGraphsFromSavedModel,
|
||||
getNumOfSavedModels,
|
||||
loadSavedModel
|
||||
};
|
||||
Generated
Vendored
-656
@@ -1,656 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
import {backend_util, BackendTimingInfo, DataId, DataType, KernelBackend, ModelTensorInfo, Rank, Scalar, scalar, ScalarLike, Tensor, Tensor1D, Tensor2D, Tensor3D, Tensor4D, TensorInfo, tidy, util} from '@tensorflow/tfjs';
|
||||
import {isArray, isNullOrUndefined} from 'util';
|
||||
|
||||
import {encodeInt32ArrayAsInt64, Int64Scalar} from './int64_tensors';
|
||||
import {TensorMetadata, TFEOpAttr, TFJSBinding} from './tfjs_binding';
|
||||
|
||||
type TensorData = {
|
||||
shape: number[],
|
||||
dtype: number,
|
||||
values: backend_util.BackendValues,
|
||||
id: number,
|
||||
refCount: number;
|
||||
};
|
||||
|
||||
export class NodeJSKernelBackend extends KernelBackend {
|
||||
binding: TFJSBinding;
|
||||
isGPUPackage: boolean;
|
||||
isUsingGpuDevice: boolean;
|
||||
private tensorMap: tf.DataStorage<TensorData>;
|
||||
|
||||
constructor(binding: TFJSBinding, packageName: string) {
|
||||
super();
|
||||
this.binding = binding;
|
||||
this.isGPUPackage = packageName === '@tensorflow/tfjs-node-gpu';
|
||||
this.isUsingGpuDevice = this.binding.isUsingGpuDevice();
|
||||
this.tensorMap = new tf.DataStorage<TensorData>(this, tf.engine());
|
||||
}
|
||||
|
||||
getDTypeInteger(dtype: DataType): number {
|
||||
switch (dtype) {
|
||||
case 'float32':
|
||||
return this.binding.TF_FLOAT;
|
||||
case 'int32':
|
||||
return this.binding.TF_INT32;
|
||||
case 'bool':
|
||||
return this.binding.TF_BOOL;
|
||||
case 'complex64':
|
||||
return this.binding.TF_COMPLEX64;
|
||||
case 'string':
|
||||
return this.binding.TF_STRING;
|
||||
default:
|
||||
throw new Error(`Unsupported DType: ${dtype}`);
|
||||
}
|
||||
}
|
||||
|
||||
private typeAttributeFromTensor(value: Tensor): number {
|
||||
return this.getDTypeInteger(value.dtype);
|
||||
}
|
||||
|
||||
// Creates a new Tensor and maps the dataId to the passed in ID.
|
||||
private createOutputTensor(metadata: TensorMetadata): Tensor {
|
||||
const newId = {};
|
||||
|
||||
this.tensorMap.set(newId, {
|
||||
shape: metadata.shape,
|
||||
dtype: metadata.dtype,
|
||||
id: metadata.id,
|
||||
values: null,
|
||||
refCount: 1
|
||||
});
|
||||
|
||||
let dtype: DataType;
|
||||
switch (metadata.dtype) {
|
||||
case this.binding.TF_FLOAT:
|
||||
dtype = 'float32';
|
||||
break;
|
||||
case this.binding.TF_INT32:
|
||||
dtype = 'int32';
|
||||
break;
|
||||
case this.binding.TF_INT64:
|
||||
console.warn('INT64 output tensor will be stored as BigInt64Array.');
|
||||
// INT64 is not supported in TFJS yet, cast it to int32.
|
||||
dtype = 'int32';
|
||||
break;
|
||||
case this.binding.TF_BOOL:
|
||||
dtype = 'bool';
|
||||
break;
|
||||
case this.binding.TF_COMPLEX64:
|
||||
dtype = 'complex64';
|
||||
break;
|
||||
case this.binding.TF_STRING:
|
||||
dtype = 'string';
|
||||
break;
|
||||
case this.binding.TF_RESOURCE:
|
||||
// NOTE(cais): We currently represent resource-type Tensors
|
||||
// as string of ubytes.
|
||||
dtype = 'string';
|
||||
break;
|
||||
case this.binding.TF_UINT8:
|
||||
// TensorFlow uses UINT8 as dtype for image tensor. UINT8 is not
|
||||
// supported in TFJS yet, cast it to int32.
|
||||
dtype = 'int32';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown dtype enum ${metadata.dtype}`);
|
||||
}
|
||||
|
||||
// TODO(yassogba) Enable this once all the kernels are removed from backend.
|
||||
// We can then change the return type from Tensor to TensorInfo.
|
||||
// return {dataId: newId, shape: metadata.shape, dtype};
|
||||
|
||||
return tf.engine().makeTensorFromDataId(newId, metadata.shape, dtype);
|
||||
}
|
||||
|
||||
// Prepares Tensor instances for Op execution.
|
||||
private getInputTensorIds(tensors: Array<TensorInfo|Int64Scalar>): number[] {
|
||||
const ids: number[] = [];
|
||||
for (let i = 0; i < tensors.length; i++) {
|
||||
if (tensors[i] instanceof Int64Scalar) {
|
||||
// Then `tensors[i]` is a Int64Scalar, which we currently represent
|
||||
// using an `Int32Array`.
|
||||
const value = (tensors[i] as Int64Scalar).valueArray;
|
||||
const id = this.binding.createTensor([], this.binding.TF_INT64, value);
|
||||
ids.push(id);
|
||||
} else {
|
||||
const info = this.tensorMap.get((tensors[i] as TensorInfo).dataId);
|
||||
// TODO - what about ID in this case? Handle in write()??
|
||||
if (info.values != null) {
|
||||
// Values were delayed to write into the TensorHandle. Do that before
|
||||
// Op execution and clear stored values.
|
||||
info.id =
|
||||
this.binding.createTensor(info.shape, info.dtype, info.values);
|
||||
info.values = null;
|
||||
}
|
||||
ids.push(info.id);
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
createReductionOpAttrs(tensor: TensorInfo, keepDims = false): TFEOpAttr[] {
|
||||
return [
|
||||
{name: 'keep_dims', type: this.binding.TF_ATTR_BOOL, value: keepDims},
|
||||
createTensorsTypeOpAttr('T', tensor.dtype),
|
||||
createTensorsTypeOpAttr('Tidx', 'int32')
|
||||
];
|
||||
}
|
||||
|
||||
floatPrecision(): 16|32 {
|
||||
return 32;
|
||||
}
|
||||
|
||||
epsilon(): number {
|
||||
return super.epsilon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an op that has a single input and output.
|
||||
*
|
||||
* Helper function to wrap executeSingleOutput in a particular case.
|
||||
* @param name The name of the Op to execute.
|
||||
* @param input The input Tensor for the Op.
|
||||
*/
|
||||
executeSingleInput(name: string, input: TensorInfo): Tensor {
|
||||
const opAttrs = [createTensorsTypeOpAttr('T', input.dtype)];
|
||||
return this.executeSingleOutput(name, opAttrs, [input]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a TensorFlow Eager Op that provides one output Tensor.
|
||||
* @param name The name of the Op to execute.
|
||||
* @param opAttrs The list of Op attributes required to execute.
|
||||
* @param inputs The list of input Tensors for the Op.
|
||||
* @return A resulting Tensor from Op execution.
|
||||
*/
|
||||
executeSingleOutput(name: string, opAttrs: TFEOpAttr[], inputs: TensorInfo[]):
|
||||
Tensor {
|
||||
const outputMetadata = this.binding.executeOp(
|
||||
name, opAttrs, this.getInputTensorIds(inputs), 1);
|
||||
return this.createOutputTensor(outputMetadata[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a TensorFlow Eager Op that provides multiple output Tensors.
|
||||
* @param name The name of the Op to execute.
|
||||
* @param opAttrs The list of Op attributes required to execute.
|
||||
* @param inputs The list of input Tensors for the Op.
|
||||
* @param numOutputs The number of output Tensors for Op execution.
|
||||
* @return A resulting Tensor array from Op execution.
|
||||
*/
|
||||
executeMultipleOutputs(
|
||||
name: string, opAttrs: TFEOpAttr[], inputs: TensorInfo[],
|
||||
numOutputs: number): Tensor[] {
|
||||
const outputMetadata = this.binding.executeOp(
|
||||
name, opAttrs, this.getInputTensorIds(inputs), numOutputs);
|
||||
return outputMetadata.map(m => this.createOutputTensor(m));
|
||||
}
|
||||
|
||||
numDataIds(): number {
|
||||
return this.tensorMap.numDataIds();
|
||||
}
|
||||
|
||||
dispose(): void {}
|
||||
|
||||
async read(dataId: DataId): Promise<backend_util.BackendValues> {
|
||||
return this.readSync(dataId);
|
||||
}
|
||||
|
||||
readSync(dataId: DataId): backend_util.BackendValues {
|
||||
if (!this.tensorMap.has(dataId)) {
|
||||
throw new Error(`Tensor ${dataId} was not registered!`);
|
||||
}
|
||||
const info = this.tensorMap.get(dataId);
|
||||
if (info.values != null) {
|
||||
return info.values;
|
||||
} else {
|
||||
return this.binding.tensorDataSync(info.id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the memory if the dataId has 0 refCount. Return true if the memory
|
||||
* is released, false otherwise.
|
||||
* @param dataId
|
||||
* @oaram force Optional, remove the data regardless of refCount
|
||||
*/
|
||||
disposeData(dataId: DataId, force = false): boolean {
|
||||
// No-op if already disposed.
|
||||
if (this.tensorMap.has(dataId)) {
|
||||
const id = this.tensorMap.get(dataId).id;
|
||||
this.tensorMap.get(dataId).refCount--;
|
||||
if (!force && this.tensorMap.get(dataId).refCount > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id != null && id >= 0) {
|
||||
this.binding.deleteTensor(id);
|
||||
}
|
||||
this.tensorMap.delete(dataId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/** Return refCount of a `TensorData`. */
|
||||
refCount(dataId: DataId): number {
|
||||
if (this.tensorMap.has(dataId)) {
|
||||
const tensorData = this.tensorMap.get(dataId);
|
||||
return tensorData.refCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
incRef(dataId: DataId) {
|
||||
this.tensorMap.get(dataId).refCount++;
|
||||
}
|
||||
|
||||
move(
|
||||
dataId: DataId, values: backend_util.BackendValues, shape: number[],
|
||||
dtype: DataType, refCount: number): void {
|
||||
this.tensorMap.set(
|
||||
dataId, {shape, dtype: getTFDType(dtype), values, id: -1, refCount});
|
||||
}
|
||||
|
||||
write(values: backend_util.BackendValues, shape: number[], dtype: DataType):
|
||||
DataId {
|
||||
const dataId = {};
|
||||
this.move(dataId, values, shape, dtype, 1);
|
||||
return dataId;
|
||||
}
|
||||
|
||||
applyActivation<T extends Tensor>(
|
||||
input: T, activation: string, preluActivationWeights?: Tensor,
|
||||
leakyreluAlpha?: number): T {
|
||||
let result = input;
|
||||
if (activation != null) {
|
||||
if (activation === 'linear') {
|
||||
// No-op
|
||||
} else if (activation === 'relu') {
|
||||
result = tf.relu(result);
|
||||
} else if (activation === 'prelu') {
|
||||
result = tf.prelu(result, preluActivationWeights) as T;
|
||||
} else if (activation === 'leakyrelu') {
|
||||
result = tf.leakyRelu(result, leakyreluAlpha);
|
||||
} else if (activation === 'elu') {
|
||||
result = tf.elu(result);
|
||||
} else if (activation === 'relu6') {
|
||||
result = tf.relu6(result);
|
||||
} else if (activation === 'sigmoid') {
|
||||
result = tf.sigmoid(result);
|
||||
} else {
|
||||
throw new Error(`Activation: ${
|
||||
activation} has not been implemented for the Node.js backend`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
divide(a: Tensor, b: Tensor): Tensor {
|
||||
const opAttrs = [createTensorsTypeOpAttr(
|
||||
'T', backend_util.upcastType(a.dtype, b.dtype))];
|
||||
return this.executeSingleOutput('Div', opAttrs, [a, b]);
|
||||
}
|
||||
|
||||
divNoNan(a: Tensor, b: Tensor): Tensor {
|
||||
const opAttrs = [createTensorsTypeOpAttr(
|
||||
'T', backend_util.upcastType(a.dtype, b.dtype))];
|
||||
return this.executeSingleOutput('DivNoNan', opAttrs, [a, b]);
|
||||
}
|
||||
|
||||
where(condition: Tensor): Tensor2D {
|
||||
return this.executeSingleOutput('Where', [], [condition]) as Tensor2D;
|
||||
}
|
||||
|
||||
topKValues<T extends Tensor>(x: T, k: number): Tensor1D {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
topKIndices(x: Tensor, k: number): Tensor1D {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
int<T extends Tensor>(x: T): T {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
decodeJpeg(
|
||||
contents: Uint8Array, channels: number, ratio: number,
|
||||
fancyUpscaling: boolean, tryRecoverTruncated: boolean,
|
||||
acceptableFraction: number, dctMethod: string): Tensor3D {
|
||||
const opAttrs = [
|
||||
{name: 'channels', type: this.binding.TF_ATTR_INT, value: channels},
|
||||
{name: 'ratio', type: this.binding.TF_ATTR_INT, value: ratio}, {
|
||||
name: 'fancy_upscaling',
|
||||
type: this.binding.TF_ATTR_BOOL,
|
||||
value: fancyUpscaling
|
||||
},
|
||||
{
|
||||
name: 'try_recover_truncated',
|
||||
type: this.binding.TF_ATTR_BOOL,
|
||||
value: tryRecoverTruncated
|
||||
},
|
||||
{
|
||||
name: 'acceptable_fraction',
|
||||
type: this.binding.TF_ATTR_FLOAT,
|
||||
value: acceptableFraction
|
||||
},
|
||||
{name: 'dct_method', type: this.binding.TF_ATTR_STRING, value: dctMethod}
|
||||
];
|
||||
const inputArgs = [scalar(contents, 'string')];
|
||||
return this.executeSingleOutput('DecodeJpeg', opAttrs, inputArgs) as
|
||||
Tensor<Rank.R3>;
|
||||
}
|
||||
|
||||
decodePng(contents: Uint8Array, channels: number): Tensor3D {
|
||||
const opAttrs =
|
||||
[{name: 'channels', type: this.binding.TF_ATTR_INT, value: channels}];
|
||||
const inputArgs = [scalar(contents, 'string')];
|
||||
|
||||
return this.executeSingleOutput('DecodePng', opAttrs, inputArgs) as
|
||||
Tensor<Rank.R3>;
|
||||
}
|
||||
|
||||
decodeBmp(contents: Uint8Array, channels: number): Tensor3D {
|
||||
const opAttrs =
|
||||
[{name: 'channels', type: this.binding.TF_ATTR_INT, value: channels}];
|
||||
const inputArgs = [scalar(contents, 'string')];
|
||||
return this.executeSingleOutput('DecodeBmp', opAttrs, inputArgs) as
|
||||
Tensor<Rank.R3>;
|
||||
}
|
||||
|
||||
decodeGif(contents: Uint8Array): Tensor4D {
|
||||
const inputArgs = [scalar(contents, 'string')];
|
||||
return this.executeSingleOutput('DecodeGif', [], inputArgs) as
|
||||
Tensor<Rank.R4>;
|
||||
}
|
||||
|
||||
executeEncodeImageOp(
|
||||
name: string, opAttrs: TFEOpAttr[], imageData: Uint8Array,
|
||||
imageShape: number[]): Tensor {
|
||||
const inputTensorId =
|
||||
this.binding.createTensor(imageShape, this.binding.TF_UINT8, imageData);
|
||||
const outputMetadata =
|
||||
this.binding.executeOp(name, opAttrs, [inputTensorId], 1);
|
||||
const outputTensorInfo = outputMetadata[0];
|
||||
// prevent the tensor data from being converted to a UTF8 string, since
|
||||
// the encoded data is not valid UTF8
|
||||
outputTensorInfo.dtype = this.binding.TF_UINT8;
|
||||
return this.createOutputTensor(outputTensorInfo);
|
||||
}
|
||||
|
||||
encodeJpeg(
|
||||
imageData: Uint8Array, imageShape: number[], format: ''|'grayscale'|'rgb',
|
||||
quality: number, progressive: boolean, optimizeSize: boolean,
|
||||
chromaDownsampling: boolean, densityUnit: 'in'|'cm', xDensity: number,
|
||||
yDensity: number, xmpMetadata: string): Tensor {
|
||||
const opAttrs = [
|
||||
{name: 'format', type: this.binding.TF_ATTR_STRING, value: format},
|
||||
{name: 'quality', type: this.binding.TF_ATTR_INT, value: quality}, {
|
||||
name: 'progressive',
|
||||
type: this.binding.TF_ATTR_BOOL,
|
||||
value: progressive
|
||||
},
|
||||
{
|
||||
name: 'optimize_size',
|
||||
type: this.binding.TF_ATTR_BOOL,
|
||||
value: optimizeSize
|
||||
},
|
||||
{
|
||||
name: 'chroma_downsampling',
|
||||
type: this.binding.TF_ATTR_BOOL,
|
||||
value: chromaDownsampling
|
||||
},
|
||||
{
|
||||
name: 'density_unit',
|
||||
type: this.binding.TF_ATTR_STRING,
|
||||
value: densityUnit
|
||||
},
|
||||
{name: 'x_density', type: this.binding.TF_ATTR_INT, value: xDensity},
|
||||
{name: 'y_density', type: this.binding.TF_ATTR_INT, value: yDensity}, {
|
||||
name: 'xmp_metadata',
|
||||
type: this.binding.TF_ATTR_STRING,
|
||||
value: xmpMetadata
|
||||
}
|
||||
];
|
||||
return this.executeEncodeImageOp(
|
||||
'EncodeJpeg', opAttrs, imageData, imageShape);
|
||||
}
|
||||
|
||||
encodePng(imageData: Uint8Array, imageShape: number[], compression: number):
|
||||
Tensor {
|
||||
const opAttrs = [
|
||||
{name: 'compression', type: this.binding.TF_ATTR_INT, value: compression}
|
||||
];
|
||||
return this.executeEncodeImageOp(
|
||||
'EncodePng', opAttrs, imageData, imageShape);
|
||||
}
|
||||
|
||||
deleteSavedModel(id: number): void {
|
||||
this.binding.deleteSavedModel(id);
|
||||
}
|
||||
|
||||
loadSavedModelMetaGraph(path: string, tags: string): number {
|
||||
return this.binding.loadSavedModel(path, tags);
|
||||
}
|
||||
|
||||
private getMappedInputTensorIds(
|
||||
inputs: Tensor[], inputTensorInfos: ModelTensorInfo[]) {
|
||||
const tensorIds = this.getInputTensorIds(inputs);
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
if (inputTensorInfos[i] != null) {
|
||||
if (inputTensorInfos[i].tfDtype === 'DT_UINT8') {
|
||||
const data = Uint8Array.from(inputs[i].dataSync());
|
||||
const inputTensorId = this.binding.createTensor(
|
||||
inputs[i].shape, this.binding.TF_UINT8, data);
|
||||
tensorIds[i] = inputTensorId;
|
||||
} else if (inputTensorInfos[i].tfDtype === 'DT_INT64') {
|
||||
const data =
|
||||
encodeInt32ArrayAsInt64(inputs[i].dataSync() as Int32Array);
|
||||
const inputTensorId = this.binding.createTensor(
|
||||
inputs[i].shape, this.binding.TF_INT64, data);
|
||||
tensorIds[i] = inputTensorId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tensorIds;
|
||||
}
|
||||
|
||||
runSavedModel(
|
||||
id: number, inputs: Tensor[], inputTensorInfos: ModelTensorInfo[],
|
||||
outputOpNames: string[]): Tensor[] {
|
||||
const outputMetadata = this.binding.runSavedModel(
|
||||
id, this.getMappedInputTensorIds(inputs, inputTensorInfos),
|
||||
inputTensorInfos.map(info => info.name).join(','),
|
||||
outputOpNames.join(','));
|
||||
return outputMetadata.map(m => this.createOutputTensor(m));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// TensorBoard-related (tfjs-node-specific) backend kernels.
|
||||
|
||||
summaryWriter(logdir: string): Tensor1D {
|
||||
const opAttrs = [
|
||||
{
|
||||
name: 'shared_name',
|
||||
type: this.binding.TF_ATTR_STRING,
|
||||
value: `logdir:${logdir}`
|
||||
},
|
||||
{name: 'container', type: this.binding.TF_ATTR_STRING, value: ''}
|
||||
];
|
||||
const writerResource =
|
||||
this.executeSingleOutput('SummaryWriter', opAttrs, []);
|
||||
return writerResource as Tensor1D;
|
||||
}
|
||||
|
||||
createSummaryFileWriter(
|
||||
resourceHandle: Tensor, logdir: string, maxQueue?: number,
|
||||
flushMillis?: number, filenameSuffix?: string): void {
|
||||
const inputArgs = [
|
||||
resourceHandle, scalar(logdir),
|
||||
scalar(maxQueue == null ? 10 : maxQueue, 'int32'),
|
||||
scalar(flushMillis == null ? 2 * 60 * 1000 : flushMillis, 'int32'),
|
||||
scalar(filenameSuffix == null ? '.v2' : filenameSuffix)
|
||||
];
|
||||
this.executeMultipleOutputs('CreateSummaryFileWriter', [], inputArgs, 0);
|
||||
}
|
||||
|
||||
writeScalarSummary(
|
||||
resourceHandle: Tensor, step: number, name: string,
|
||||
value: Scalar|number): void {
|
||||
tidy(() => {
|
||||
util.assert(
|
||||
Number.isInteger(step),
|
||||
() => `step is expected to be an integer, but is instead ${step}`);
|
||||
const inputArgs: Array<Tensor|Int64Scalar> =
|
||||
[resourceHandle, new Int64Scalar(step), scalar(name, 'string')];
|
||||
|
||||
let typeAttr: number;
|
||||
if (typeof value === 'number') {
|
||||
inputArgs.push(scalar(value));
|
||||
typeAttr = this.binding.TF_FLOAT;
|
||||
} else {
|
||||
// `value` is a Scalar.
|
||||
util.assert(
|
||||
value.rank === 0,
|
||||
() => `A non-scalar tensor (rank ${value.rank}) is passed to ` +
|
||||
`writeScalarSummary()`);
|
||||
inputArgs.push(value);
|
||||
typeAttr = this.typeAttributeFromTensor(value);
|
||||
}
|
||||
const opAttrs: TFEOpAttr[] =
|
||||
[{name: 'T', type: this.binding.TF_ATTR_TYPE, value: typeAttr}];
|
||||
|
||||
this.binding.executeOp(
|
||||
'WriteScalarSummary', opAttrs, this.getInputTensorIds(inputArgs), 0);
|
||||
});
|
||||
}
|
||||
|
||||
flushSummaryWriter(resourceHandle: Tensor): void {
|
||||
const inputArgs: Tensor[] = [resourceHandle];
|
||||
this.executeMultipleOutputs('FlushSummaryWriter', [], inputArgs, 0);
|
||||
}
|
||||
|
||||
// ~ TensorBoard-related (tfjs-node-specific) backend kernels.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
memory() {
|
||||
// Due to automatic garbage collection, the numbers are unreliable.
|
||||
// TODO(kreeger): Since there is finalization in C, count the true
|
||||
// number of undisposed tensors.
|
||||
return {unreliable: true};
|
||||
}
|
||||
|
||||
async time(f: () => void): Promise<BackendTimingInfo> {
|
||||
const start = process.hrtime();
|
||||
f();
|
||||
// hrtime() returns tuple of [seconds, nanoseconds], and we need to return
|
||||
// milliseconds.
|
||||
const elapsed = process.hrtime(start);
|
||||
return {kernelMs: elapsed[0] * 1000 + elapsed[1] / 1000000};
|
||||
}
|
||||
|
||||
getNumOfSavedModels() {
|
||||
return this.binding.getNumOfSavedModels();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns an instance of the Node.js backend. */
|
||||
export function nodeBackend(): NodeJSKernelBackend {
|
||||
return tf.findBackend('tensorflow') as NodeJSKernelBackend;
|
||||
}
|
||||
|
||||
/** Returns the TF dtype for a given DataType. */
|
||||
export function getTFDType(dataType: tf.DataType): number {
|
||||
const binding = nodeBackend().binding;
|
||||
switch (dataType) {
|
||||
case 'float32':
|
||||
return binding.TF_FLOAT;
|
||||
case 'int32':
|
||||
return binding.TF_INT32;
|
||||
case 'bool':
|
||||
return binding.TF_BOOL;
|
||||
case 'complex64':
|
||||
return binding.TF_COMPLEX64;
|
||||
case 'string':
|
||||
return binding.TF_STRING;
|
||||
// tslint:disable-next-line:no-any
|
||||
case 'int64' as any:
|
||||
// int64 is not a generally supported dtype in TensorFlow.js
|
||||
// (tfjs-core). However, it needs to be included here for the purpose of
|
||||
// writing the `step` value to TensorBoard via WriteScalarSummary and
|
||||
// other op kernels.
|
||||
return binding.TF_INT64;
|
||||
default:
|
||||
const errorMessage = `Unknown dtype: ${dataType}`;
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TFEOpAttr for a 'type' OpDef attribute from a Tensor or list of
|
||||
* Tensors.
|
||||
*/
|
||||
export function createTensorsTypeOpAttr(
|
||||
attrName: string,
|
||||
tensorsOrDtype: tf.Tensor|tf.Tensor[]|tf.DataType): TFEOpAttr {
|
||||
if (isNullOrUndefined(tensorsOrDtype)) {
|
||||
throw new Error('Invalid input tensors value.');
|
||||
}
|
||||
return {
|
||||
name: attrName,
|
||||
type: nodeBackend().binding.TF_ATTR_TYPE,
|
||||
value:
|
||||
(tensorsOrDtype instanceof tf.Tensor || Array.isArray(tensorsOrDtype)) ?
|
||||
getTFDTypeForInputs(tensorsOrDtype) :
|
||||
getTFDType(tensorsOrDtype)
|
||||
};
|
||||
}
|
||||
|
||||
// TODO(yassogba) remove? who uses this?
|
||||
export function createOpAttr(
|
||||
attrName: string, tensorsOrDtype: tf.Tensor|tf.Tensor[]|tf.DataType,
|
||||
value: ScalarLike): TFEOpAttr {
|
||||
if (isNullOrUndefined(tensorsOrDtype)) {
|
||||
throw new Error('Invalid input tensors value.');
|
||||
}
|
||||
return {name: attrName, type: nodeBackend().binding.TF_BOOL, value};
|
||||
}
|
||||
|
||||
/** Returns the dtype number for a single or list of input Tensors. */
|
||||
function getTFDTypeForInputs(tensors: tf.Tensor|tf.Tensor[]): number {
|
||||
if (isNullOrUndefined(tensors)) {
|
||||
throw new Error('Invalid input tensors value.');
|
||||
}
|
||||
if (isArray(tensors)) {
|
||||
for (let i = 0; i < tensors.length; i++) {
|
||||
return getTFDType(tensors[i].dtype);
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return getTFDType(tensors.dtype);
|
||||
}
|
||||
}
|
||||
|
||||
export function ensureTensorflowBackend() {
|
||||
tf.util.assert(
|
||||
tf.getBackend() === 'tensorflow',
|
||||
() => `Expect the current backend to be "tensorflow", but got "${
|
||||
tf.getBackend()}"`);
|
||||
}
|
||||
Generated
Vendored
-360
@@ -1,360 +0,0 @@
|
||||
// api.proto
|
||||
// Definition of various TensorFlow protobuf messages for use with the TensorFlow API.
|
||||
//
|
||||
// Assembled from these relevant proto sources:
|
||||
// https://github.com/google/protobuf/blob/master/src/google/protobuf/any.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/types.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/tensor.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/tensor_shape.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/attr_value.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/versions.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/graph.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/node_def.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/op_def.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/saver.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/meta_graph.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/saved_model.proto
|
||||
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/function.proto
|
||||
|
||||
|
||||
// This file is used to generate the api_pb.js file with the JavaScript Protocol
|
||||
// Buffers runtime library (https://github.com/protocolbuffers/protobuf/tree/master/js).
|
||||
// The protocol compiler (https://github.com/protocolbuffers/protobuf/releases)
|
||||
// translated this file (same as proto file in tfjs-converter:
|
||||
// https://github.com/tensorflow/tfjs/blob/master/tfjs-converter/src/data/api.proto)
|
||||
// into the api_pb.js file with command:
|
||||
//
|
||||
// ```
|
||||
// $ protoc --js_out=import_style=commonjs,binary:. api.proto
|
||||
// ```
|
||||
|
||||
|
||||
syntax = "proto3";
|
||||
package tensorflow;
|
||||
|
||||
message Any {
|
||||
string type_url = 1;
|
||||
bytes value = 2;
|
||||
}
|
||||
|
||||
enum DataType {
|
||||
// Not a legal value for DataType. Used to indicate a DataType field
|
||||
// has not been set.
|
||||
DT_INVALID = 0;
|
||||
|
||||
// Data types that all computation devices are expected to be
|
||||
// capable to support.
|
||||
DT_FLOAT = 1;
|
||||
DT_DOUBLE = 2;
|
||||
DT_INT32 = 3;
|
||||
DT_UINT8 = 4;
|
||||
DT_INT16 = 5;
|
||||
DT_INT8 = 6;
|
||||
DT_STRING = 7;
|
||||
DT_COMPLEX64 = 8; // Single-precision complex
|
||||
DT_INT64 = 9;
|
||||
DT_BOOL = 10;
|
||||
DT_QINT8 = 11; // Quantized int8
|
||||
DT_QUINT8 = 12; // Quantized uint8
|
||||
DT_QINT32 = 13; // Quantized int32
|
||||
DT_BFLOAT16 = 14; // Float32 truncated to 16 bits. Only for cast ops.
|
||||
|
||||
// Do not use! These are only for parameters. Every enum above
|
||||
// should have a corresponding value below (verified by types_test).
|
||||
DT_FLOAT_REF = 101;
|
||||
DT_DOUBLE_REF = 102;
|
||||
DT_INT32_REF = 103;
|
||||
DT_UINT8_REF = 104;
|
||||
DT_INT16_REF = 105;
|
||||
DT_INT8_REF = 106;
|
||||
DT_STRING_REF = 107;
|
||||
DT_COMPLEX64_REF = 108;
|
||||
DT_INT64_REF = 109;
|
||||
DT_BOOL_REF = 110;
|
||||
DT_QINT8_REF = 111;
|
||||
DT_QUINT8_REF = 112;
|
||||
DT_QINT32_REF = 113;
|
||||
DT_BFLOAT16_REF = 114;
|
||||
}
|
||||
|
||||
message TensorShape {
|
||||
// One dimension of the tensor.
|
||||
message Dim {
|
||||
// Size of the tensor in that dimension.
|
||||
int64 size = 1;
|
||||
|
||||
// Optional name of the tensor dimension.
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
// Dimensions of the tensor, such as {"input", 30}, {"output", 40} for a 30 x
|
||||
// 40 2D tensor. The names are optional.
|
||||
//
|
||||
// The order of entries in "dim" matters: It indicates the layout of the
|
||||
// values in the tensor in-memory representation.
|
||||
//
|
||||
// The first entry in "dim" is the outermost dimension used to layout the
|
||||
// values, the last entry is the innermost dimension. This matches the
|
||||
// in-memory layout of RowMajor Eigen tensors.
|
||||
repeated Dim dim = 2;
|
||||
|
||||
bool unknown_rank = 3;
|
||||
}
|
||||
|
||||
message Tensor {
|
||||
DataType dtype = 1;
|
||||
|
||||
// Shape of the tensor. TODO(touts): sort out the 0-rank issues.
|
||||
TensorShape tensor_shape = 2;
|
||||
|
||||
// Only one of the representations below is set, one of "tensor_contents" and
|
||||
// the "xxx_val" attributes. We are not using oneof because as oneofs cannot
|
||||
// contain repeated fields it would require another extra set of messages.
|
||||
|
||||
// Version number.
|
||||
//
|
||||
// In version 0, if the "repeated xxx" representations contain only one
|
||||
// element, that element is repeated to fill the shape. This makes it easy
|
||||
// to represent a constant Tensor with a single value.
|
||||
int32 version_number = 3;
|
||||
|
||||
// Serialized content from TensorBase::Serialize() This representation can be
|
||||
// used for all tensor types.
|
||||
bytes tensor_content = 4;
|
||||
|
||||
// Type specific representations that make it easy to create tensor protos in
|
||||
// all languages. Only the representation corresponding to "dtype" can
|
||||
// be set. The values hold the flattened representation of the tensor in
|
||||
// row major order.
|
||||
|
||||
// DT_FLOAT.
|
||||
repeated float float_val = 5 [packed = true];
|
||||
|
||||
// DT_DOUBLE.
|
||||
repeated double double_val = 6 [packed = true];
|
||||
|
||||
// DT_INT32, DT_INT16, DT_INT8, DT_UINT8.
|
||||
repeated int32 int_val = 7 [packed = true];
|
||||
|
||||
// DT_STRING
|
||||
repeated bytes string_val = 8;
|
||||
|
||||
// DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real
|
||||
// and imaginary parts of i-th single precision complex.
|
||||
repeated float scomplex_val = 9 [packed = true];
|
||||
|
||||
// DT_INT64
|
||||
repeated int64 int64_val = 10 [packed = true];
|
||||
|
||||
// DT_BOOL
|
||||
repeated bool bool_val = 11 [packed = true];
|
||||
|
||||
// DT_UINT32
|
||||
repeated uint32 uint32_val = 16 [packed = true];
|
||||
|
||||
// DT_UINT64
|
||||
repeated uint64 uint64_val = 17 [packed = true];
|
||||
}
|
||||
|
||||
message AttrValue {
|
||||
message ListValue {
|
||||
repeated bytes s = 2;
|
||||
repeated int64 i = 3 [packed = true];
|
||||
repeated float f = 4 [packed = true];
|
||||
repeated bool b = 5 [packed = true];
|
||||
repeated DataType type = 6 [packed = true];
|
||||
repeated TensorShape shape = 7;
|
||||
repeated Tensor tensor = 8;
|
||||
repeated NameAttrList func = 9;
|
||||
}
|
||||
|
||||
oneof value {
|
||||
ListValue list = 1;
|
||||
bytes s = 2;
|
||||
int64 i = 3;
|
||||
float f = 4;
|
||||
bool b = 5;
|
||||
DataType type = 6;
|
||||
TensorShape shape = 7;
|
||||
Tensor tensor = 8;
|
||||
string placeholder = 9;
|
||||
NameAttrList func = 10;
|
||||
}
|
||||
}
|
||||
|
||||
message NameAttrList {
|
||||
string name = 1;
|
||||
map<string, AttrValue> attr = 2;
|
||||
}
|
||||
|
||||
message NodeDef {
|
||||
string name = 1;
|
||||
string op = 2;
|
||||
repeated string input = 3;
|
||||
string device = 4;
|
||||
map<string, AttrValue> attr = 5;
|
||||
}
|
||||
|
||||
message VersionDef {
|
||||
int32 producer = 1;
|
||||
int32 min_consumer = 2;
|
||||
repeated int32 bad_consumers = 3;
|
||||
}
|
||||
|
||||
message GraphDef {
|
||||
repeated NodeDef node = 1;
|
||||
VersionDef versions = 4;
|
||||
FunctionDefLibrary library = 2;
|
||||
}
|
||||
|
||||
message CollectionDef {
|
||||
message NodeList {
|
||||
repeated string value = 1;
|
||||
}
|
||||
message BytesList {
|
||||
repeated bytes value = 1;
|
||||
}
|
||||
message Int64List {
|
||||
repeated int64 value = 1 [packed = true];
|
||||
}
|
||||
message FloatList {
|
||||
repeated float value = 1 [packed = true];
|
||||
}
|
||||
message AnyList {
|
||||
repeated Any value = 1;
|
||||
}
|
||||
|
||||
oneof kind {
|
||||
NodeList node_list = 1;
|
||||
BytesList bytes_list = 2;
|
||||
Int64List int64_list = 3;
|
||||
FloatList float_list = 4;
|
||||
AnyList any_list = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message SaverDef {
|
||||
string filename_tensor_name = 1;
|
||||
string save_tensor_name = 2;
|
||||
string restore_op_name = 3;
|
||||
int32 max_to_keep = 4;
|
||||
bool sharded = 5;
|
||||
float keep_checkpoint_every_n_hours = 6;
|
||||
|
||||
enum CheckpointFormatVersion {
|
||||
LEGACY = 0;
|
||||
V1 = 1;
|
||||
V2 = 2;
|
||||
}
|
||||
CheckpointFormatVersion version = 7;
|
||||
}
|
||||
|
||||
message TensorInfo {
|
||||
message CooSparse {
|
||||
string values_tensor_name = 1;
|
||||
string indices_tensor_name = 2;
|
||||
string dense_shape_tensor_name = 3;
|
||||
}
|
||||
|
||||
oneof encoding {
|
||||
string name = 1;
|
||||
CooSparse coo_sparse = 4;
|
||||
}
|
||||
DataType dtype = 2;
|
||||
TensorShape tensor_shape = 3;
|
||||
}
|
||||
|
||||
message SignatureDef {
|
||||
map<string, TensorInfo> inputs = 1;
|
||||
map<string, TensorInfo> outputs = 2;
|
||||
string method_name = 3;
|
||||
}
|
||||
|
||||
message AssetFileDef {
|
||||
TensorInfo tensor_info = 1;
|
||||
string filename = 2;
|
||||
}
|
||||
|
||||
message OpDef {
|
||||
string name = 1;
|
||||
|
||||
message ArgDef {
|
||||
string name = 1;
|
||||
string description = 2;
|
||||
DataType type = 3;
|
||||
string type_attr = 4; // if specified, attr must have type "type"
|
||||
string number_attr = 5; // if specified, attr must have type "int"
|
||||
string type_list_attr = 6;
|
||||
bool is_ref = 16;
|
||||
}
|
||||
repeated ArgDef input_arg = 2;
|
||||
repeated ArgDef output_arg = 3;
|
||||
|
||||
message AttrDef {
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
AttrValue default_value = 3;
|
||||
string description = 4;
|
||||
bool has_minimum = 5;
|
||||
int64 minimum = 6;
|
||||
AttrValue allowed_values = 7;
|
||||
}
|
||||
repeated AttrDef attr = 4;
|
||||
|
||||
message OpDeprecation {
|
||||
int32 version = 1;
|
||||
string explanation = 2;
|
||||
}
|
||||
OpDeprecation deprecation = 8;
|
||||
|
||||
string summary = 5;
|
||||
string description = 6;
|
||||
bool is_commutative = 18;
|
||||
bool is_aggregate = 16; // for things like add
|
||||
bool is_stateful = 17; // for things like variables, queue
|
||||
bool allows_uninitialized_input = 19; // for Assign, etc.
|
||||
}
|
||||
|
||||
message OpList {
|
||||
repeated OpDef op = 1;
|
||||
}
|
||||
|
||||
message MetaGraphDef {
|
||||
message MetaInfoDef {
|
||||
string meta_graph_version = 1;
|
||||
OpList stripped_op_list = 2;
|
||||
Any any_info = 3;
|
||||
repeated string tags = 4;
|
||||
string tensorflow_version = 5;
|
||||
string tensorflow_git_version = 6;
|
||||
}
|
||||
MetaInfoDef meta_info_def = 1;
|
||||
GraphDef graph_def = 2;
|
||||
SaverDef saver_def = 3;
|
||||
map<string, CollectionDef> collection_def = 4;
|
||||
map<string, SignatureDef> signature_def = 5;
|
||||
repeated AssetFileDef asset_file_def = 6;
|
||||
}
|
||||
|
||||
message SavedModel {
|
||||
int64 saved_model_schema_version = 1;
|
||||
repeated MetaGraphDef meta_graphs = 2;
|
||||
}
|
||||
|
||||
message FunctionDefLibrary {
|
||||
repeated FunctionDef function = 1;
|
||||
repeated GradientDef gradient = 2;
|
||||
}
|
||||
|
||||
message FunctionDef {
|
||||
OpDef signature = 1;
|
||||
map<string, AttrValue> attr = 5;
|
||||
reserved 2;
|
||||
repeated NodeDef node_def = 3;
|
||||
map<string, string> ret = 4;
|
||||
}
|
||||
|
||||
message GradientDef {
|
||||
string function_name = 1; // The function name.
|
||||
string gradient_func = 2; // The gradient function's name.
|
||||
}
|
||||
Generated
Vendored
-9136
File diff suppressed because it is too large.
Load diff
Generated
Vendored
-325
@@ -1,325 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
// We explicitly import the modular kernels so they get registered in the
|
||||
// global registry when we compile the library. A modular build would replace
|
||||
// the contents of this file and import only the kernels that are needed.
|
||||
import {KernelConfig, registerKernel} from '@tensorflow/tfjs';
|
||||
|
||||
import {_fusedMatMulConfig} from './kernels/_FusedMatMul';
|
||||
import {absConfig} from './kernels/Abs';
|
||||
import {acosConfig} from './kernels/Acos';
|
||||
import {acoshConfig} from './kernels/Acosh';
|
||||
import {addConfig} from './kernels/Add';
|
||||
import {addNConfig} from './kernels/AddN';
|
||||
import {allConfig} from './kernels/All';
|
||||
import {anyConfig} from './kernels/Any';
|
||||
import {argMaxConfig} from './kernels/ArgMax';
|
||||
import {argMinConfig} from './kernels/ArgMin';
|
||||
import {asinConfig} from './kernels/Asin';
|
||||
import {asinhConfig} from './kernels/Asinh';
|
||||
import {atanConfig} from './kernels/Atan';
|
||||
import {atan2Config} from './kernels/Atan2';
|
||||
import {atanhConfig} from './kernels/Atanh';
|
||||
import {avgPoolConfig} from './kernels/AvgPool';
|
||||
import {avgPool3DConfig} from './kernels/AvgPool3D';
|
||||
import {avgPool3DGradConfig} from './kernels/AvgPool3DGrad';
|
||||
import {avgPoolGradConfig} from './kernels/AvgPoolGrad';
|
||||
import {batchMatMulConfig} from './kernels/BatchMatMul';
|
||||
import {batchToSpaceNDConfig} from './kernels/BatchToSpaceND';
|
||||
import {bincountConfig} from './kernels/Bincount';
|
||||
import {castConfig} from './kernels/Cast';
|
||||
import {ceilConfig} from './kernels/Ceil';
|
||||
import {clipByValueConfig} from './kernels/ClipByValue';
|
||||
import {complexConfig} from './kernels/Complex';
|
||||
import {complexAbsConfig} from './kernels/ComplexAbs';
|
||||
import {concatConfig} from './kernels/Concat';
|
||||
import {conv2DConfig} from './kernels/Conv2D';
|
||||
import {conv2DBackpropFilterConfig} from './kernels/Conv2DBackpropFilter';
|
||||
import {conv2DBackpropInputConfig} from './kernels/Conv2DBackpropInput';
|
||||
import {conv3DConfig} from './kernels/Conv3D';
|
||||
import {conv3DBackpropFilterV2Config} from './kernels/Conv3DBackpropFilterV2';
|
||||
import {conv3DBackpropInputV2Config} from './kernels/Conv3DBackpropInputV2';
|
||||
import {cosConfig} from './kernels/Cos';
|
||||
import {coshConfig} from './kernels/Cosh';
|
||||
import {cropAndResizeConfig} from './kernels/CropAndResize';
|
||||
import {cumsumConfig} from './kernels/Cumsum';
|
||||
import {depthToSpaceConfig} from './kernels/DepthToSpace';
|
||||
import {depthwiseConv2dNativeConfig} from './kernels/DepthwiseConv2dNative';
|
||||
import {depthwiseConv2dNativeBackpropFilterConfig} from './kernels/DepthwiseConv2dNativeBackpropFilter';
|
||||
import {depthwiseConv2dNativeBackpropInputConfig} from './kernels/DepthwiseConv2dNativeBackpropInput';
|
||||
import {diagConfig} from './kernels/Diag';
|
||||
import {dilation2dConfig} from './kernels/Dilation2D';
|
||||
import {dilation2dBackpropFilterConfig} from './kernels/Dilation2DBackpropFilter';
|
||||
import {dilation2dBackpropInputConfig} from './kernels/Dilation2DBackpropInput';
|
||||
import {eluConfig} from './kernels/Elu';
|
||||
import {eluGradConfig} from './kernels/EluGrad';
|
||||
import {equalConfig} from './kernels/Equal';
|
||||
import {erfConfig} from './kernels/Erf';
|
||||
import {expConfig} from './kernels/Exp';
|
||||
import {expandDimsConfig} from './kernels/ExpandDims';
|
||||
import {expm1Config} from './kernels/Expm1';
|
||||
import {FFTConfig} from './kernels/FFT';
|
||||
import {fillConfig} from './kernels/Fill';
|
||||
import {floorConfig} from './kernels/Floor';
|
||||
import {floorDivConfig} from './kernels/FloorDiv';
|
||||
import {fusedBatchNormConfig} from './kernels/FusedBatchNorm';
|
||||
import {fusedConv2DConfig} from './kernels/FusedConv2D';
|
||||
import {fusedDepthwiseConv2DConfig} from './kernels/FusedDepthwiseConv2D';
|
||||
import {gatherNdConfig} from './kernels/GatherNd';
|
||||
import {gatherV2Config} from './kernels/GatherV2';
|
||||
import {greaterConfig} from './kernels/Greater';
|
||||
import {greaterEqualConfig} from './kernels/GreaterEqual';
|
||||
import {identityConfig} from './kernels/Identity';
|
||||
import {IFFTConfig} from './kernels/IFFT';
|
||||
import {imagConfig} from './kernels/Imag';
|
||||
import {isFiniteConfig} from './kernels/IsFinite';
|
||||
import {isInfConfig} from './kernels/IsInf';
|
||||
import {isNanConfig} from './kernels/IsNan';
|
||||
import {leakyReluConfig} from './kernels/LeakyRelu';
|
||||
import {lessConfig} from './kernels/Less';
|
||||
import {lessEqualConfig} from './kernels/LessEqual';
|
||||
import {linSpaceConfig} from './kernels/LinSpace';
|
||||
import {logConfig} from './kernels/Log';
|
||||
import {log1pConfig} from './kernels/Log1p';
|
||||
import {logicalAndConfig} from './kernels/LogicalAnd';
|
||||
import {logicalNotConfig} from './kernels/LogicalNot';
|
||||
import {logicalOrConfig} from './kernels/LogicalOr';
|
||||
import {LRNConfig} from './kernels/LRN';
|
||||
import {LRNGradConfig} from './kernels/LRNGrad';
|
||||
import {maxConfig} from './kernels/Max';
|
||||
import {maximumConfig} from './kernels/Maximum';
|
||||
import {maxPoolConfig} from './kernels/MaxPool';
|
||||
import {maxPool3DConfig} from './kernels/MaxPool3D';
|
||||
import {maxPool3DGradConfig} from './kernels/MaxPool3DGrad';
|
||||
import {maxPoolGradConfig} from './kernels/MaxPoolGrad';
|
||||
import {meanConfig} from './kernels/Mean';
|
||||
import {minConfig} from './kernels/Min';
|
||||
import {minimumConfig} from './kernels/Minimum';
|
||||
import {mirrorPadConfig} from './kernels/MirrorPad';
|
||||
import {modConfig} from './kernels/Mod';
|
||||
import {multinomialConfig} from './kernels/Multinomial';
|
||||
import {multiplyConfig} from './kernels/Multiply';
|
||||
import {negConfig} from './kernels/Neg';
|
||||
import {nonMaxSuppressionV3Config} from './kernels/NonMaxSuppressionV3';
|
||||
import {nonMaxSuppressionV4Config} from './kernels/NonMaxSuppressionV4';
|
||||
import {nonMaxSuppressionV5Config} from './kernels/NonMaxSuppressionV5';
|
||||
import {notEqualConfig} from './kernels/NotEqual';
|
||||
import {oneHotConfig} from './kernels/OneHot';
|
||||
import {onesLikeConfig} from './kernels/OnesLike';
|
||||
import {packConfig} from './kernels/Pack';
|
||||
import {padV2Config} from './kernels/PadV2';
|
||||
import {powConfig} from './kernels/Pow';
|
||||
import {preluConfig} from './kernels/Prelu';
|
||||
import {prodConfig} from './kernels/Prod';
|
||||
import {rangeConfig} from './kernels/Range';
|
||||
import {realConfig} from './kernels/Real';
|
||||
import {realDivConfig} from './kernels/RealDiv';
|
||||
import {reciprocalConfig} from './kernels/Reciprocal';
|
||||
import {reluConfig} from './kernels/Relu';
|
||||
import {relu6Config} from './kernels/Relu6';
|
||||
import {reshapeConfig} from './kernels/Reshape';
|
||||
import {resizeBilinearConfig} from './kernels/ResizeBilinear';
|
||||
import {resizeBilinearGradConfig} from './kernels/ResizeBilinearGrad';
|
||||
import {resizeNearestNeighborConfig} from './kernels/ResizeNearestNeighbor';
|
||||
import {resizeNearestNeighborGradConfig} from './kernels/ResizeNearestNeighborGrad';
|
||||
import {reverseConfig} from './kernels/Reverse';
|
||||
import {roundConfig} from './kernels/Round';
|
||||
import {rsqrtConfig} from './kernels/Rsqrt';
|
||||
import {scatterNdConfig} from './kernels/ScatterNd';
|
||||
import {selectConfig} from './kernels/Select';
|
||||
import {seluConfig} from './kernels/Selu';
|
||||
import {sigmoidConfig} from './kernels/Sigmoid';
|
||||
import {signConfig} from './kernels/Sign';
|
||||
import {sinConfig} from './kernels/Sin';
|
||||
import {sinhConfig} from './kernels/Sinh';
|
||||
import {sliceConfig} from './kernels/Slice';
|
||||
import {softmaxConfig} from './kernels/Softmax';
|
||||
import {softplusConfig} from './kernels/Softplus';
|
||||
import {spaceToBatchNDConfig} from './kernels/SpaceToBatchND';
|
||||
import {sparseToDenseConfig} from './kernels/SparseToDense';
|
||||
import {splitVConfig} from './kernels/SplitV';
|
||||
import {sqrtConfig} from './kernels/Sqrt';
|
||||
import {squareConfig} from './kernels/Square';
|
||||
import {squaredDifferenceConfig} from './kernels/SquaredDifference';
|
||||
import {stepConfig} from './kernels/Step';
|
||||
import {stridedSliceConfig} from './kernels/StridedSlice';
|
||||
import {subConfig} from './kernels/Sub';
|
||||
import {sumConfig} from './kernels/Sum';
|
||||
import {tanConfig} from './kernels/Tan';
|
||||
import {tanhConfig} from './kernels/Tanh';
|
||||
import {tileConfig} from './kernels/Tile';
|
||||
import {topKConfig} from './kernels/TopK';
|
||||
import {transposeConfig} from './kernels/Transpose';
|
||||
import {unpackConfig} from './kernels/Unpack';
|
||||
import {unsortedSegmentSumConfig} from './kernels/UnsortedSegmentSum';
|
||||
import {zerosLikeConfig} from './kernels/ZerosLike';
|
||||
|
||||
// List all kernel configs here
|
||||
const kernelConfigs: KernelConfig[] = [
|
||||
FFTConfig,
|
||||
IFFTConfig,
|
||||
LRNConfig,
|
||||
LRNGradConfig,
|
||||
_fusedMatMulConfig,
|
||||
absConfig,
|
||||
acosConfig,
|
||||
acoshConfig,
|
||||
addConfig,
|
||||
addNConfig,
|
||||
allConfig,
|
||||
anyConfig,
|
||||
argMaxConfig,
|
||||
argMinConfig,
|
||||
asinConfig,
|
||||
asinhConfig,
|
||||
atan2Config,
|
||||
atanConfig,
|
||||
atanhConfig,
|
||||
avgPool3DConfig,
|
||||
avgPool3DGradConfig,
|
||||
avgPoolConfig,
|
||||
avgPoolGradConfig,
|
||||
batchMatMulConfig,
|
||||
batchToSpaceNDConfig,
|
||||
castConfig,
|
||||
ceilConfig,
|
||||
clipByValueConfig,
|
||||
complexAbsConfig,
|
||||
complexConfig,
|
||||
concatConfig,
|
||||
conv2DBackpropFilterConfig,
|
||||
conv2DBackpropInputConfig,
|
||||
conv2DConfig,
|
||||
conv3DBackpropFilterV2Config,
|
||||
conv3DBackpropInputV2Config,
|
||||
conv3DConfig,
|
||||
cosConfig,
|
||||
coshConfig,
|
||||
cropAndResizeConfig,
|
||||
cumsumConfig,
|
||||
bincountConfig,
|
||||
depthToSpaceConfig,
|
||||
depthwiseConv2dNativeBackpropFilterConfig,
|
||||
depthwiseConv2dNativeBackpropInputConfig,
|
||||
depthwiseConv2dNativeConfig,
|
||||
diagConfig,
|
||||
dilation2dBackpropFilterConfig,
|
||||
dilation2dBackpropInputConfig,
|
||||
dilation2dConfig,
|
||||
eluConfig,
|
||||
eluGradConfig,
|
||||
equalConfig,
|
||||
erfConfig,
|
||||
expConfig,
|
||||
expandDimsConfig,
|
||||
expm1Config,
|
||||
fillConfig,
|
||||
floorConfig,
|
||||
floorDivConfig,
|
||||
fusedBatchNormConfig,
|
||||
fusedConv2DConfig,
|
||||
fusedDepthwiseConv2DConfig,
|
||||
gatherNdConfig,
|
||||
gatherV2Config,
|
||||
greaterConfig,
|
||||
greaterEqualConfig,
|
||||
identityConfig,
|
||||
imagConfig,
|
||||
isFiniteConfig,
|
||||
isInfConfig,
|
||||
isNanConfig,
|
||||
leakyReluConfig,
|
||||
lessConfig,
|
||||
lessEqualConfig,
|
||||
linSpaceConfig,
|
||||
log1pConfig,
|
||||
logConfig,
|
||||
logicalAndConfig,
|
||||
logicalNotConfig,
|
||||
logicalOrConfig,
|
||||
maxConfig,
|
||||
maxPool3DConfig,
|
||||
maxPool3DGradConfig,
|
||||
maxPoolConfig,
|
||||
maxPoolGradConfig,
|
||||
maximumConfig,
|
||||
meanConfig,
|
||||
minConfig,
|
||||
minimumConfig,
|
||||
mirrorPadConfig,
|
||||
modConfig,
|
||||
multinomialConfig,
|
||||
multiplyConfig,
|
||||
negConfig,
|
||||
nonMaxSuppressionV3Config,
|
||||
nonMaxSuppressionV4Config,
|
||||
nonMaxSuppressionV5Config,
|
||||
notEqualConfig,
|
||||
oneHotConfig,
|
||||
onesLikeConfig,
|
||||
packConfig,
|
||||
padV2Config,
|
||||
powConfig,
|
||||
preluConfig,
|
||||
prodConfig,
|
||||
rangeConfig,
|
||||
realConfig,
|
||||
realDivConfig,
|
||||
reciprocalConfig,
|
||||
relu6Config,
|
||||
reluConfig,
|
||||
reshapeConfig,
|
||||
resizeBilinearConfig,
|
||||
resizeBilinearGradConfig,
|
||||
resizeNearestNeighborConfig,
|
||||
resizeNearestNeighborGradConfig,
|
||||
reverseConfig,
|
||||
roundConfig,
|
||||
rsqrtConfig,
|
||||
scatterNdConfig,
|
||||
selectConfig,
|
||||
seluConfig,
|
||||
sigmoidConfig,
|
||||
signConfig,
|
||||
sinConfig,
|
||||
sinhConfig,
|
||||
sliceConfig,
|
||||
softmaxConfig,
|
||||
softplusConfig,
|
||||
spaceToBatchNDConfig,
|
||||
sparseToDenseConfig,
|
||||
splitVConfig,
|
||||
sqrtConfig,
|
||||
squareConfig,
|
||||
squaredDifferenceConfig,
|
||||
stepConfig,
|
||||
stridedSliceConfig,
|
||||
subConfig,
|
||||
sumConfig,
|
||||
tanConfig,
|
||||
tanhConfig,
|
||||
tileConfig,
|
||||
topKConfig,
|
||||
transposeConfig,
|
||||
unpackConfig,
|
||||
unsortedSegmentSumConfig,
|
||||
zerosLikeConfig
|
||||
];
|
||||
|
||||
for (const kernelConfig of kernelConfigs) {
|
||||
registerKernel(kernelConfig);
|
||||
}
|
||||
Generated
Vendored
-154
@@ -1,154 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
// We import index.ts so that the Node backend gets registered.
|
||||
import './index';
|
||||
// tslint:disable-next-line: no-imports-from-dist
|
||||
import '@tensorflow/tfjs-core/dist/public/chained_ops/register_all_chained_ops';
|
||||
// tslint:disable-next-line: no-imports-from-dist
|
||||
import '@tensorflow/tfjs-core/dist/register_all_gradients';
|
||||
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
// tslint:disable-next-line:no-imports-from-dist
|
||||
import * as jasmine_util from '@tensorflow/tfjs-core/dist/jasmine_util';
|
||||
import {argv} from 'yargs';
|
||||
|
||||
import {NodeJSKernelBackend} from './nodejs_kernel_backend';
|
||||
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
const jasmineCtor = require('jasmine');
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
|
||||
process.on('unhandledRejection', e => {
|
||||
throw e;
|
||||
});
|
||||
|
||||
jasmine_util.setTestEnvs([{
|
||||
name: 'test-tensorflow',
|
||||
backendName: 'tensorflow',
|
||||
flags: {},
|
||||
isDataSync: true
|
||||
}]);
|
||||
|
||||
const IGNORE_LIST: string[] = [
|
||||
// Always ignore version tests:
|
||||
'version version',
|
||||
'unreliable is true due to both auto gc and string tensors',
|
||||
'unreliable is true due to auto gc',
|
||||
// See https://github.com/tensorflow/tfjs/issues/161
|
||||
'depthwiseConv2D', // Requires space_to_batch() for dilation > 1.
|
||||
'separableConv2d', // Requires space_to_batch() for dilation > 1.
|
||||
'complex64 memory',
|
||||
// See https://github.com/tensorflow/tfjs-core/pull/1270
|
||||
'depthToSpace test-tensorflow {} throws when blocksize < 2',
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'depthToSpace test-tensorflow {} throws when CPU backend used with data format NCHW',
|
||||
// See https://github.com/tensorflow/tfjs/issues/806
|
||||
'scatterND test-tensorflow {} should work for 2d',
|
||||
'scatterND test-tensorflow {} should work for simple 1d',
|
||||
'scatterND test-tensorflow {} should work for multiple 1d',
|
||||
'scatterND test-tensorflow {} should sum the duplicated indices',
|
||||
'scatterND test-tensorflow {} should work for tensorLike input',
|
||||
// https://github.com/tensorflow/tfjs/issues/1077
|
||||
'maxPool test-tensorflow {} x=[2,2,3] f=[1,1] s=2 p=1 dimRoundingMode=floor',
|
||||
'avgPool test-tensorflow {} x=[2,2,3] f=[1,1] s=2 p=1 dimRoundingMode=floor',
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'avgPool3d test-tensorflow {} x=[1,2,2,2,1] f=[2,2,2] s=1 p=1 roundingMode=floor',
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'maxPool3d test-tensorflow {} x=[1,2,2,2,1] f=[2,2,2] s=1 p=1 roundingMode=floor',
|
||||
// libtensorflow doesn't support 6D ArgMax yet.
|
||||
'argmax test-tensorflow {} 6D, axis=0', 'diag test-tensorflow {} complex',
|
||||
'diag test-tensorflow {} bool',
|
||||
// See https://github.com/tensorflow/tfjs/issues/1891
|
||||
'conv2d test-tensorflow {} x=[2,1,2,2] f=[1,1,1,1] s=1 d=1 p=0 NCHW',
|
||||
'conv2d test-tensorflow {} x=[1,2,2] f=[2,2,1,1] s=1 d=1 p=explicit NCHW',
|
||||
'conv2d test-tensorflow {} x=[1,2,2] f=[2,2,1,1] s=1 d=1 p=same NCHW',
|
||||
'conv2d test-tensorflow {} x=[2,2,2] f=[2,2,2,1] s=1 d=1 p=same NCHW',
|
||||
'conv2d test-tensorflow {} x=[2,1,2,2] f=[2,2,1,1] s=1 d=1 p=same NCHW',
|
||||
'conv2d test-tensorflow {} gradient x=[1,1,3,3] f=[2,2,1,1] s=1 p=0 NCHW',
|
||||
'conv2d test-tensorflow {} gradient x=[2,1,3,3] f=[2,2,1,1] s=1 p=0 NCHW',
|
||||
'maxPoolWithArgmax', 'rotate', 'flipLeftRight', 'unique',
|
||||
// libtensorflow does not yet support tf.matmul with broadcast
|
||||
'broadcast with unequal batch dims', 'broadcast with unequal ranks',
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'pool test-tensorflow {} max x=[2,2,3] f=[1,1] s=2 p=1 fractional outputs default rounding',
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'pool test-tensorflow {} avg x=[2,2,3] f=[1,1] s=2 p=1 fractional outputs default rounding',
|
||||
// not available in tf yet.
|
||||
'denseBincount',
|
||||
// only available in tf addon.
|
||||
'image.transform',
|
||||
// Breaking change in NaN processing
|
||||
// See https://github.com/tensorflow/tfjs/issues/4883
|
||||
'max test-tensorflow {} ignores NaNs', 'min test-tensorflow {} ignores NaNs',
|
||||
'sign test-tensorflow {} basic',
|
||||
'sign test-tensorflow {} does not propagate NaNs',
|
||||
'sign test-tensorflow {} accepts a tensor-like object',
|
||||
// Node kernel for einsum is yet to be implemented.
|
||||
// See: ttps://github.com/tensorflow/tfjs/issues/2349
|
||||
'einsum', 'sparseFillEmptyRows', 'sparseReshape'
|
||||
];
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// Ignore tensorboard on windows because tmp folder cleanup used in tests
|
||||
// fails with tmp folder cleanup:
|
||||
// https://github.com/tensorflow/tfjs/issues/1692
|
||||
IGNORE_LIST.push('tensorboard');
|
||||
IGNORE_LIST.push('tensorBoard');
|
||||
// Windows has two failing tests:
|
||||
// https://github.com/tensorflow/tfjs/issues/598
|
||||
IGNORE_LIST.push('clip test-tensorflow {} propagates NaNs');
|
||||
IGNORE_LIST.push(
|
||||
'maxPool test-tensorflow {} [x=[3,3,1] f=[2,2] s=1 ignores NaNs');
|
||||
}
|
||||
|
||||
const runner = new jasmineCtor();
|
||||
runner.loadConfig({spec_files: ['src/**/*_test.ts'], random: false});
|
||||
// Also import tests from core.
|
||||
// tslint:disable-next-line: no-imports-from-dist
|
||||
import '@tensorflow/tfjs-core/dist/tests';
|
||||
|
||||
if (process.env.JASMINE_SEED) {
|
||||
runner.seed(process.env.JASMINE_SEED);
|
||||
}
|
||||
|
||||
const env = jasmine.getEnv();
|
||||
|
||||
const grepRegex = new RegExp(argv.grep as string);
|
||||
|
||||
// Filter method that returns boolean, if a given test should return.
|
||||
env.specFilter = spec => {
|
||||
// Filter based on the grep flag.
|
||||
if (!grepRegex.test(spec.getFullName())) {
|
||||
return false;
|
||||
}
|
||||
// Return false (skip the test) if the test is in the ignore list.
|
||||
for (let i = 0; i < IGNORE_LIST.length; ++i) {
|
||||
if (spec.getFullName().indexOf(IGNORE_LIST[i]) > -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Otherwise run the test.
|
||||
return true;
|
||||
};
|
||||
|
||||
// TODO(kreeger): Consider moving to C-code.
|
||||
console.log(`Running tests against TensorFlow: ${
|
||||
(tf.backend() as NodeJSKernelBackend).binding.TF_Version}`);
|
||||
runner.execute();
|
||||
Generated
Vendored
-464
@@ -1,464 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2019 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {DataType, InferenceModel, MetaGraph, ModelPredictConfig, ModelTensorInfo, NamedTensorMap, SignatureDef, SignatureDefEntry, Tensor, util} from '@tensorflow/tfjs';
|
||||
import * as fs from 'fs';
|
||||
import {promisify} from 'util';
|
||||
|
||||
import {ensureTensorflowBackend, nodeBackend, NodeJSKernelBackend} from './nodejs_kernel_backend';
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
const messages = require('./proto/api_pb');
|
||||
|
||||
const SAVED_MODEL_FILE_NAME = '/saved_model.pb';
|
||||
|
||||
const SAVED_MODEL_INIT_OP_KEY = '__saved_model_init_op';
|
||||
|
||||
// This map is used to keep track of loaded SavedModel metagraph mapping
|
||||
// information. The map key is TFSavedModel id in JavaScript, value is
|
||||
// an object of path to the SavedModel, metagraph tags, and loaded Session ID in
|
||||
// the c++ bindings. When user loads a SavedModel signature, it will go through
|
||||
// entries in this map to find if the corresponding SavedModel session has
|
||||
// already been loaded in C++ addon and will reuse it if existing.
|
||||
const loadedSavedModelPathMap =
|
||||
new Map<number, {path: string, tags: string[], sessionId: number}>();
|
||||
|
||||
// The ID of loaded TFSavedModel. This ID is used to keep track of loaded
|
||||
// TFSavedModel, so the loaded session in c++ bindings for the corresponding
|
||||
// TFSavedModel can be properly reused/disposed.
|
||||
let nextTFSavedModelId = 0;
|
||||
|
||||
/**
|
||||
* Get a key in an object by its value. This is used to get protobuf enum value
|
||||
* from index.
|
||||
*
|
||||
* @param object
|
||||
* @param value
|
||||
*/
|
||||
// tslint:disable-next-line:no-any
|
||||
export function getEnumKeyFromValue(object: any, value: number): string {
|
||||
return Object.keys(object).find(key => object[key] === value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SavedModel proto message from path.
|
||||
*
|
||||
* @param path Path to SavedModel folder.
|
||||
*/
|
||||
export async function readSavedModelProto(path: string) {
|
||||
// Load the SavedModel pb file and deserialize it into message.
|
||||
try {
|
||||
fs.accessSync(path + SAVED_MODEL_FILE_NAME, fs.constants.R_OK);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
'There is no saved_model.pb file in the directory: ' + path);
|
||||
}
|
||||
const modelFile = await readFile(path + SAVED_MODEL_FILE_NAME);
|
||||
const array = new Uint8Array(modelFile);
|
||||
return messages.SavedModel.deserializeBinary(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect the MetaGraphs of the SavedModel from the provided path. This
|
||||
* function will return an array of `MetaGraphInfo` objects.
|
||||
*
|
||||
* @param path Path to SavedModel folder.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel', namespace: 'node'}
|
||||
*/
|
||||
export async function getMetaGraphsFromSavedModel(path: string):
|
||||
Promise<MetaGraph[]> {
|
||||
const result: MetaGraph[] = [];
|
||||
|
||||
// Get SavedModel proto message
|
||||
const modelMessage = await readSavedModelProto(path);
|
||||
|
||||
// A SavedModel might have multiple MetaGraphs, identified by tags.
|
||||
// Each MetaGraph also has it's own signatureDefs.
|
||||
const metaGraphList = modelMessage.getMetaGraphsList();
|
||||
for (let i = 0; i < metaGraphList.length; i++) {
|
||||
const metaGraph = {} as MetaGraph;
|
||||
const tags = metaGraphList[i].getMetaInfoDef().getTagsList();
|
||||
metaGraph.tags = tags;
|
||||
|
||||
// Each MetaGraph has it's own signatureDefs map.
|
||||
const signatureDef: SignatureDef = {};
|
||||
const signatureDefMap = metaGraphList[i].getSignatureDefMap();
|
||||
const signatureDefKeys = signatureDefMap.keys();
|
||||
|
||||
// Go through all signatureDefs
|
||||
while (true) {
|
||||
const key = signatureDefKeys.next();
|
||||
if (key.done) {
|
||||
break;
|
||||
}
|
||||
// Skip TensorFlow internal Signature '__saved_model_init_op'.
|
||||
if (key.value === SAVED_MODEL_INIT_OP_KEY) {
|
||||
continue;
|
||||
}
|
||||
const signatureDefEntry = signatureDefMap.get(key.value);
|
||||
|
||||
// Get all input tensors information
|
||||
const inputsMapMessage = signatureDefEntry.getInputsMap();
|
||||
const inputsMapKeys = inputsMapMessage.keys();
|
||||
const inputs: {[key: string]: ModelTensorInfo} = {};
|
||||
while (true) {
|
||||
const inputsMapKey = inputsMapKeys.next();
|
||||
if (inputsMapKey.done) {
|
||||
break;
|
||||
}
|
||||
const inputTensor = inputsMapMessage.get(inputsMapKey.value);
|
||||
const inputTensorInfo = {} as ModelTensorInfo;
|
||||
const dtype =
|
||||
getEnumKeyFromValue(messages.DataType, inputTensor.getDtype());
|
||||
inputTensorInfo.dtype = mapTFDtypeToJSDtype(dtype);
|
||||
inputTensorInfo.tfDtype = dtype;
|
||||
inputTensorInfo.name = inputTensor.getName();
|
||||
inputTensorInfo.shape = inputTensor.getTensorShape().getDimList();
|
||||
inputs[inputsMapKey.value] = inputTensorInfo;
|
||||
}
|
||||
|
||||
// Get all output tensors information
|
||||
const outputsMapMessage = signatureDefEntry.getOutputsMap();
|
||||
const outputsMapKeys = outputsMapMessage.keys();
|
||||
const outputs: {[key: string]: ModelTensorInfo} = {};
|
||||
while (true) {
|
||||
const outputsMapKey = outputsMapKeys.next();
|
||||
if (outputsMapKey.done) {
|
||||
break;
|
||||
}
|
||||
const outputTensor = outputsMapMessage.get(outputsMapKey.value);
|
||||
const outputTensorInfo = {} as ModelTensorInfo;
|
||||
const dtype =
|
||||
getEnumKeyFromValue(messages.DataType, outputTensor.getDtype());
|
||||
outputTensorInfo.dtype = mapTFDtypeToJSDtype(dtype);
|
||||
outputTensorInfo.tfDtype = dtype;
|
||||
outputTensorInfo.name = outputTensor.getName();
|
||||
outputTensorInfo.shape = outputTensor.getTensorShape().getDimList();
|
||||
outputs[outputsMapKey.value] = outputTensorInfo;
|
||||
}
|
||||
|
||||
signatureDef[key.value] = {inputs, outputs};
|
||||
}
|
||||
metaGraph.signatureDefs = signatureDef;
|
||||
|
||||
result.push(metaGraph);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SignatureDefEntry from SavedModel metagraphs info. The SignatureDefEntry
|
||||
* will be used when executing a SavedModel signature.
|
||||
*
|
||||
* @param savedModelInfo The MetaGraphInfo array loaded through
|
||||
* getMetaGraphsFromSavedModel().
|
||||
* @param tags The tags of the MetaGraph to get input/output node names from.
|
||||
* @param signature The signature to get input/output node names from.
|
||||
*/
|
||||
export function getSignatureDefEntryFromMetaGraphInfo(
|
||||
savedModelInfo: MetaGraph[], tags: string[],
|
||||
signature: string): SignatureDefEntry {
|
||||
for (let i = 0; i < savedModelInfo.length; i++) {
|
||||
const metaGraphInfo = savedModelInfo[i];
|
||||
if (stringArraysHaveSameElements(tags, metaGraphInfo.tags)) {
|
||||
if (metaGraphInfo.signatureDefs[signature] == null) {
|
||||
throw new Error('The SavedModel does not have signature: ' + signature);
|
||||
}
|
||||
return metaGraphInfo.signatureDefs[signature];
|
||||
}
|
||||
}
|
||||
throw new Error(`The SavedModel does not have tags: ${tags}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* A `tf.TFSavedModel` is a signature loaded from a SavedModel
|
||||
* metagraph, and allows inference execution.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel', namespace: 'node'}
|
||||
*/
|
||||
export class TFSavedModel implements InferenceModel {
|
||||
private disposed = false;
|
||||
private outputNodeNames_: {[key: string]: string};
|
||||
constructor(
|
||||
private sessionId: number, private jsid: number,
|
||||
private signature: SignatureDefEntry,
|
||||
private backend: NodeJSKernelBackend) {}
|
||||
|
||||
/**
|
||||
* Return the array of input tensor info.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel'}
|
||||
*/
|
||||
get inputs(): ModelTensorInfo[] {
|
||||
const entries = this.signature.inputs;
|
||||
const results = Object.keys(entries).map((key: string) => entries[key]);
|
||||
results.forEach((info: ModelTensorInfo) => {
|
||||
info.name = info.name.replace(/:0$/, '');
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of output tensor info.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel'}
|
||||
*/
|
||||
get outputs(): ModelTensorInfo[] {
|
||||
const entries = this.signature.outputs;
|
||||
const results = Object.keys(entries).map((key: string) => entries[key]);
|
||||
results.forEach((info: ModelTensorInfo) => {
|
||||
info.name = info.name.replace(/:0$/, '');
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the SavedModel from nodeBackend and delete corresponding session in
|
||||
* the C++ backend if the session is only used by this TFSavedModel.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel'}
|
||||
*/
|
||||
dispose() {
|
||||
if (!this.disposed) {
|
||||
this.disposed = true;
|
||||
|
||||
loadedSavedModelPathMap.delete(this.jsid);
|
||||
for (const id of Array.from(loadedSavedModelPathMap.keys())) {
|
||||
const value = loadedSavedModelPathMap.get(id);
|
||||
if (value.sessionId === this.sessionId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.backend.deleteSavedModel(this.sessionId);
|
||||
} else {
|
||||
throw new Error('This SavedModel has already been deleted.');
|
||||
}
|
||||
}
|
||||
|
||||
get outputNodeNames() {
|
||||
if (this.outputNodeNames_ != null) {
|
||||
return this.outputNodeNames_;
|
||||
}
|
||||
this.outputNodeNames_ =
|
||||
Object.keys(this.signature.outputs)
|
||||
.reduce((names: {[key: string]: string}, key: string) => {
|
||||
names[key] = this.signature.outputs[key].name;
|
||||
return names;
|
||||
}, {});
|
||||
return this.outputNodeNames_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the inference for the input tensors.
|
||||
*
|
||||
* @param input The input tensors, when there is single input for the model,
|
||||
* inputs param should be a Tensor. For models with multiple inputs, inputs
|
||||
* params should be in either Tensor[] if the input order is fixed, or
|
||||
* otherwise NamedTensorMap format. The keys in the NamedTensorMap are the
|
||||
* name of input tensors in SavedModel signatureDef. It can be found through
|
||||
* `tf.node.getMetaGraphsFromSavedModel()`.
|
||||
*
|
||||
* For batch inference execution, the tensors for each input need to be
|
||||
* concatenated together. For example with mobilenet, the required input shape
|
||||
* is [1, 244, 244, 3], which represents the [batch, height, width, channel].
|
||||
* If we are provide a batched data of 100 images, the input tensor should be
|
||||
* in the shape of [100, 244, 244, 3].
|
||||
*
|
||||
* @param config Prediction configuration for specifying the batch size.
|
||||
*
|
||||
* @returns Inference result tensors. The output would be single Tensor if
|
||||
* model has single output node, otherwise Tensor[] or NamedTensorMap[] will
|
||||
* be returned for model with multiple outputs.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel'}
|
||||
*/
|
||||
predict(inputs: Tensor|Tensor[]|NamedTensorMap, config?: ModelPredictConfig):
|
||||
Tensor|Tensor[]|NamedTensorMap {
|
||||
if (this.disposed) {
|
||||
throw new Error('The TFSavedModel has already been deleted!');
|
||||
} else {
|
||||
let inputTensors: Tensor[] = [];
|
||||
if (inputs instanceof Tensor) {
|
||||
inputTensors.push(inputs);
|
||||
const result = this.backend.runSavedModel(
|
||||
this.sessionId, inputTensors, Object.values(this.signature.inputs),
|
||||
Object.values(this.outputNodeNames));
|
||||
return result.length > 1 ? result : result[0];
|
||||
} else if (Array.isArray(inputs)) {
|
||||
inputTensors = inputs;
|
||||
return this.backend.runSavedModel(
|
||||
this.sessionId, inputTensors, Object.values(this.signature.inputs),
|
||||
Object.values(this.outputNodeNames));
|
||||
} else {
|
||||
const inputTensorNames = Object.keys(this.signature.inputs);
|
||||
const providedInputNames = Object.keys(inputs);
|
||||
if (!stringArraysHaveSameElements(
|
||||
inputTensorNames, providedInputNames)) {
|
||||
throw new Error(`The model signatureDef input names are ${
|
||||
inputTensorNames.join()}, however the provided input names are ${
|
||||
providedInputNames.join()}.`);
|
||||
}
|
||||
const inputNodeNamesArray: ModelTensorInfo[] = [];
|
||||
for (let i = 0; i < inputTensorNames.length; i++) {
|
||||
inputTensors.push(inputs[inputTensorNames[i]]);
|
||||
inputNodeNamesArray.push(this.signature.inputs[inputTensorNames[i]]);
|
||||
}
|
||||
const outputTensorNames = Object.keys(this.outputNodeNames);
|
||||
const outputNodeNamesArray = [];
|
||||
for (let i = 0; i < outputTensorNames.length; i++) {
|
||||
outputNodeNamesArray.push(this.outputNodeNames[outputTensorNames[i]]);
|
||||
}
|
||||
const outputTensors = this.backend.runSavedModel(
|
||||
this.sessionId, inputTensors, inputNodeNamesArray,
|
||||
outputNodeNamesArray);
|
||||
util.assert(
|
||||
outputTensors.length === outputNodeNamesArray.length,
|
||||
() => 'Output tensors do not match output node names, ' +
|
||||
`receive ${outputTensors.length}) output tensors but ` +
|
||||
`there are ${this.outputNodeNames.length} output nodes.`);
|
||||
const outputMap: NamedTensorMap = {};
|
||||
for (let i = 0; i < outputTensorNames.length; i++) {
|
||||
outputMap[outputTensorNames[i]] = outputTensors[i];
|
||||
}
|
||||
return outputMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the inference for the input tensors and return activation
|
||||
* values for specified output node names without batching.
|
||||
*
|
||||
* @param input The input tensors, when there is single input for the model,
|
||||
* inputs param should be a Tensor. For models with multiple inputs, inputs
|
||||
* params should be in either Tensor[] if the input order is fixed, or
|
||||
* otherwise NamedTensorMap format.
|
||||
*
|
||||
* @param outputs string|string[]. List of output node names to retrieve
|
||||
* activation from.
|
||||
*
|
||||
* @returns Activation values for the output nodes result tensors. The return
|
||||
* type matches specified parameter outputs type. The output would be single
|
||||
* Tensor if single output is specified, otherwise Tensor[] for multiple
|
||||
* outputs.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel'}
|
||||
*/
|
||||
execute(inputs: Tensor|Tensor[]|NamedTensorMap, outputs: string|string[]):
|
||||
Tensor|Tensor[] {
|
||||
throw new Error('execute() of TFSavedModel is not supported yet.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a TensorFlow SavedModel from disk. TensorFlow SavedModel is different
|
||||
* from TensorFlow.js model format. A SavedModel is a directory containing
|
||||
* serialized signatures and the states needed to run them. The directory has a
|
||||
* saved_model.pb (or saved_model.pbtxt) file storing the actual TensorFlow
|
||||
* program, or model, and a set of named signatures, each identifying a
|
||||
* function. The directory also has a variables directory contains a standard
|
||||
* training checkpoint. The directory may also has a assets directory contains
|
||||
* files used by the TensorFlow graph, for example text files used to initialize
|
||||
* vocabulary tables. These are supported datatypes: float32, int32, complex64,
|
||||
* string.For more information, see this guide:
|
||||
* https://www.tensorflow.org/guide/saved_model.
|
||||
*
|
||||
* @param path The path to the SavedModel.
|
||||
* @param tags The tags of the MetaGraph to load. The available tags of a
|
||||
* SavedModel can be retrieved through tf.node.getMetaGraphsFromSavedModel()
|
||||
* API. Defaults to ['serve'].
|
||||
* @param signature The name of the SignatureDef to load. The available
|
||||
* SignatureDefs of a SavedModel can be retrieved through
|
||||
* tf.node.getMetaGraphsFromSavedModel() API. Defaults to 'serving_default'.
|
||||
*
|
||||
* @doc {heading: 'Models', subheading: 'SavedModel', namespace: 'node'}
|
||||
*/
|
||||
export async function loadSavedModel(
|
||||
path: string, tags = ['serve'],
|
||||
signature = 'serving_default'): Promise<TFSavedModel> {
|
||||
ensureTensorflowBackend();
|
||||
|
||||
const backend = nodeBackend();
|
||||
|
||||
const savedModelInfo = await getMetaGraphsFromSavedModel(path);
|
||||
const signatureDefEntry =
|
||||
getSignatureDefEntryFromMetaGraphInfo(savedModelInfo, tags, signature);
|
||||
|
||||
let sessionId: number;
|
||||
|
||||
for (const id of Array.from(loadedSavedModelPathMap.keys())) {
|
||||
const modelInfo = loadedSavedModelPathMap.get(id);
|
||||
if (modelInfo.path === path &&
|
||||
stringArraysHaveSameElements(modelInfo.tags, tags)) {
|
||||
sessionId = modelInfo.sessionId;
|
||||
}
|
||||
}
|
||||
if (sessionId == null) {
|
||||
// Convert metagraph tags string array to a string.
|
||||
const tagsString = tags.join(',');
|
||||
sessionId = backend.loadSavedModelMetaGraph(path, tagsString);
|
||||
}
|
||||
const id = nextTFSavedModelId++;
|
||||
const savedModel =
|
||||
new TFSavedModel(sessionId, id, signatureDefEntry, backend);
|
||||
loadedSavedModelPathMap.set(id, {path, tags, sessionId});
|
||||
return savedModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare if two unsorted arrays of string have the same elements.
|
||||
* @param arrayA
|
||||
* @param arrayB
|
||||
*/
|
||||
function stringArraysHaveSameElements(
|
||||
arrayA: string[], arrayB: string[]): boolean {
|
||||
if (arrayA.length === arrayB.length &&
|
||||
arrayA.sort().join() === arrayB.sort().join()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function mapTFDtypeToJSDtype(tfDtype: string): DataType {
|
||||
switch (tfDtype) {
|
||||
case 'DT_FLOAT':
|
||||
return 'float32';
|
||||
case 'DT_INT64':
|
||||
case 'DT_INT32':
|
||||
case 'DT_UINT8':
|
||||
return 'int32';
|
||||
case 'DT_BOOL':
|
||||
return 'bool';
|
||||
case 'DT_COMPLEX64':
|
||||
return 'complex64';
|
||||
case 'DT_STRING':
|
||||
return 'string';
|
||||
default:
|
||||
throw new Error(
|
||||
'Unsupported tensor DataType: ' + tfDtype +
|
||||
', try to modify the model in python to convert the datatype');
|
||||
}
|
||||
}
|
||||
|
||||
export function getNumOfSavedModels() {
|
||||
ensureTensorflowBackend();
|
||||
const backend = nodeBackend();
|
||||
return backend.getNumOfSavedModels();
|
||||
}
|
||||
Generated
Vendored
-111
@@ -1,111 +0,0 @@
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2019 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {Scalar, Tensor, util} from '@tensorflow/tfjs';
|
||||
|
||||
import {ensureTensorflowBackend, nodeBackend, NodeJSKernelBackend} from './nodejs_kernel_backend';
|
||||
|
||||
export class SummaryFileWriter {
|
||||
backend: NodeJSKernelBackend;
|
||||
|
||||
constructor(private readonly resourceHandle: Tensor) {
|
||||
ensureTensorflowBackend();
|
||||
this.backend = nodeBackend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a scalar summary.
|
||||
*
|
||||
* @param name A name of the summary. The summary tag for TensorBoard will be
|
||||
* this name.
|
||||
* @param value A real numeric scalar value, as `tf.Scalar` or a JavaScript
|
||||
* `number`.
|
||||
* @param step Required `int64`-castable, monotically-increasing step value.
|
||||
* @param description Optinal long-form description for this summary, as a
|
||||
* `string`. *Not implemented yet*.
|
||||
*/
|
||||
scalar(
|
||||
name: string, value: Scalar|number, step: number, description?: string) {
|
||||
// N.B.: Unlike the Python TensorFlow API, step is a required parameter,
|
||||
// because the construct of global step does not exist in TensorFlow.js.
|
||||
if (description != null) {
|
||||
throw new Error('scalar() does not support description yet');
|
||||
}
|
||||
|
||||
this.backend.writeScalarSummary(this.resourceHandle, step, name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force summary writer to send all buffered data to storage.
|
||||
*/
|
||||
flush() {
|
||||
this.backend.flushSummaryWriter(this.resourceHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a cache for `SummaryFileWriter` instance.
|
||||
*
|
||||
* Using multiple instances of `SummaryFileWriter` pointing to the same
|
||||
* logdir has potential problems. Using this cache avoids those problems.
|
||||
*/
|
||||
const summaryFileWriterCache: {[logdir: string]: SummaryFileWriter} = {};
|
||||
|
||||
/**
|
||||
* Create a summary file writer for TensorBoard.
|
||||
*
|
||||
* Example:
|
||||
* ```js
|
||||
* const tf = require('@tensorflow/tfjs-node');
|
||||
*
|
||||
* const summaryWriter = tf.node.summaryFileWriter('/tmp/tfjs_tb_logdir');
|
||||
*
|
||||
* for (let step = 0; step < 100; ++step) {
|
||||
* summaryWriter.scalar('dummyValue', Math.sin(2 * Math.PI * step / 8), step);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param logdir Log directory in which the summary data will be written.
|
||||
* @param maxQueue Maximum queue length (default: `10`).
|
||||
* @param flushMillis Flush every __ milliseconds (default: `120e3`, i.e,
|
||||
* `120` seconds).
|
||||
* @param filenameSuffix Suffix of the protocol buffer file names to be
|
||||
* written in the `logdir` (default: `.v2`).
|
||||
* @returns An instance of `SummaryFileWriter`.
|
||||
*
|
||||
* @doc {heading: 'TensorBoard', namespace: 'node'}
|
||||
*/
|
||||
export function summaryFileWriter(
|
||||
logdir: string, maxQueue = 10, flushMillis = 120000,
|
||||
filenameSuffix = '.v2'): SummaryFileWriter {
|
||||
util.assert(
|
||||
logdir != null && typeof logdir === 'string' && logdir.length > 0,
|
||||
() =>
|
||||
`Invalid logdir: ${logdir}. Expected a non-empty string for logdir.`);
|
||||
if (!(logdir in summaryFileWriterCache)) {
|
||||
ensureTensorflowBackend();
|
||||
const backend = nodeBackend();
|
||||
const writerResource = backend.summaryWriter(logdir);
|
||||
|
||||
backend.createSummaryFileWriter(
|
||||
writerResource, logdir, maxQueue, flushMillis, filenameSuffix);
|
||||
|
||||
summaryFileWriterCache[logdir] = new SummaryFileWriter(writerResource);
|
||||
}
|
||||
return summaryFileWriterCache[logdir];
|
||||
}
|
||||
Generated
Vendored
-87
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
import {backend_util} from '@tensorflow/tfjs';
|
||||
|
||||
export declare class TensorMetadata {
|
||||
id: number;
|
||||
shape: number[];
|
||||
dtype: number;
|
||||
}
|
||||
|
||||
export declare class TFEOpAttr {
|
||||
name: string;
|
||||
type: number;
|
||||
value: boolean|number|object|string|number[];
|
||||
}
|
||||
|
||||
export interface TFJSBinding {
|
||||
TensorMetadata: typeof TensorMetadata;
|
||||
TFEOpAttr: typeof TFEOpAttr;
|
||||
|
||||
// Creates a tensor with the backend.
|
||||
createTensor(
|
||||
shape: number[], dtype: number,
|
||||
buffer: backend_util.BackendValues): number;
|
||||
|
||||
// Deletes a tensor with the backend.
|
||||
deleteTensor(tensorId: number): void;
|
||||
|
||||
// Reads data-sync from a tensor on the backend.
|
||||
tensorDataSync(tensorId: number): Float32Array|Int32Array|Uint8Array;
|
||||
|
||||
// Executes an Op on the backend, returns an array of output TensorMetadata.
|
||||
executeOp(
|
||||
opName: string, opAttrs: TFEOpAttr[], inputTensorIds: number[],
|
||||
numOutputs: number): TensorMetadata[];
|
||||
|
||||
// Load a SavedModel from a path.
|
||||
loadSavedModel(exportDir: string, tags: string): number;
|
||||
|
||||
// Remove a SavedModel from memory.
|
||||
deleteSavedModel(savedModelId: number): void;
|
||||
|
||||
// Execute a SavedModel with input, returns an array of output TensorMetadata.
|
||||
runSavedModel(
|
||||
savedModelId: number, inputTensorIds: number[], inputOpNames: string,
|
||||
outputOpNames: string): TensorMetadata[];
|
||||
|
||||
getNumOfSavedModels(): number;
|
||||
|
||||
isUsingGpuDevice(): boolean;
|
||||
|
||||
// TF Types
|
||||
TF_FLOAT: number;
|
||||
TF_INT32: number;
|
||||
TF_INT64: number;
|
||||
TF_BOOL: number;
|
||||
TF_COMPLEX64: number;
|
||||
TF_STRING: number;
|
||||
TF_RESOURCE: number;
|
||||
TF_UINT8: number;
|
||||
|
||||
// TF OpAttrTypes
|
||||
TF_ATTR_STRING: number;
|
||||
TF_ATTR_INT: number;
|
||||
TF_ATTR_FLOAT: number;
|
||||
TF_ATTR_BOOL: number;
|
||||
TF_ATTR_TYPE: number;
|
||||
TF_ATTR_SHAPE: number;
|
||||
TF_ATTR_RESOURCE: number;
|
||||
|
||||
TF_Version: string;
|
||||
}
|
||||
Generated
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
/** @license See the LICENSE file. */
|
||||
|
||||
// This code is auto-generated, do not modify this file!
|
||||
const version = '3.6.1';
|
||||
export {version};
|
||||
Generated
Vendored
-25
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true,
|
||||
"declaration": true,
|
||||
"target": "es5",
|
||||
"lib": ["es2015", "dom"],
|
||||
"outDir": "./dist",
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"noUnusedParameters": false,
|
||||
"pretty": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"allowUnreachableCode": false,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig",
|
||||
"include": [
|
||||
"src/"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules/"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
-46
@@ -1,46 +0,0 @@
|
||||
This software is dual-licensed under the ISC and MIT licenses.
|
||||
You may use this software under EITHER of the following licenses.
|
||||
|
||||
----------
|
||||
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
----------
|
||||
|
||||
Copyright Isaac Z. Schlueter and Contributors
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/abbrev/README.md
Generated
Vendored
-23
@@ -1,23 +0,0 @@
|
||||
# abbrev-js
|
||||
|
||||
Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
|
||||
|
||||
Usage:
|
||||
|
||||
var abbrev = require("abbrev");
|
||||
abbrev("foo", "fool", "folding", "flop");
|
||||
|
||||
// returns:
|
||||
{ fl: 'flop'
|
||||
, flo: 'flop'
|
||||
, flop: 'flop'
|
||||
, fol: 'folding'
|
||||
, fold: 'folding'
|
||||
, foldi: 'folding'
|
||||
, foldin: 'folding'
|
||||
, folding: 'folding'
|
||||
, foo: 'foo'
|
||||
, fool: 'fool'
|
||||
}
|
||||
|
||||
This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.
|
||||
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/abbrev/abbrev.js
Generated
Vendored
-61
@@ -1,61 +0,0 @@
|
||||
module.exports = exports = abbrev.abbrev = abbrev
|
||||
|
||||
abbrev.monkeyPatch = monkeyPatch
|
||||
|
||||
function monkeyPatch () {
|
||||
Object.defineProperty(Array.prototype, 'abbrev', {
|
||||
value: function () { return abbrev(this) },
|
||||
enumerable: false, configurable: true, writable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(Object.prototype, 'abbrev', {
|
||||
value: function () { return abbrev(Object.keys(this)) },
|
||||
enumerable: false, configurable: true, writable: true
|
||||
})
|
||||
}
|
||||
|
||||
function abbrev (list) {
|
||||
if (arguments.length !== 1 || !Array.isArray(list)) {
|
||||
list = Array.prototype.slice.call(arguments, 0)
|
||||
}
|
||||
for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
|
||||
args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
|
||||
}
|
||||
|
||||
// sort them lexicographically, so that they're next to their nearest kin
|
||||
args = args.sort(lexSort)
|
||||
|
||||
// walk through each, seeing how much it has in common with the next and previous
|
||||
var abbrevs = {}
|
||||
, prev = ""
|
||||
for (var i = 0, l = args.length ; i < l ; i ++) {
|
||||
var current = args[i]
|
||||
, next = args[i + 1] || ""
|
||||
, nextMatches = true
|
||||
, prevMatches = true
|
||||
if (current === next) continue
|
||||
for (var j = 0, cl = current.length ; j < cl ; j ++) {
|
||||
var curChar = current.charAt(j)
|
||||
nextMatches = nextMatches && curChar === next.charAt(j)
|
||||
prevMatches = prevMatches && curChar === prev.charAt(j)
|
||||
if (!nextMatches && !prevMatches) {
|
||||
j ++
|
||||
break
|
||||
}
|
||||
}
|
||||
prev = current
|
||||
if (j === cl) {
|
||||
abbrevs[current] = current
|
||||
continue
|
||||
}
|
||||
for (var a = current.substr(0, j) ; j <= cl ; j ++) {
|
||||
abbrevs[a] = current
|
||||
a += current.charAt(j)
|
||||
}
|
||||
}
|
||||
return abbrevs
|
||||
}
|
||||
|
||||
function lexSort (a, b) {
|
||||
return a === b ? 0 : a > b ? 1 : -1
|
||||
}
|
||||
Generated
Vendored
-25
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "abbrev",
|
||||
"version": "1.1.1",
|
||||
"description": "Like ruby's abbrev module, but in js",
|
||||
"author": "Isaac Z. Schlueter <i@izs.me>",
|
||||
"main": "abbrev.js",
|
||||
"scripts": {
|
||||
"test": "tap test.js --100",
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"postpublish": "git push origin --all; git push origin --tags"
|
||||
},
|
||||
"repository": "http://github.com/isaacs/abbrev-js",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"tap": "^10.1"
|
||||
},
|
||||
"files": [
|
||||
"abbrev.js"
|
||||
]
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
|
||||
,"_integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
,"_from": "abbrev@1.1.1"
|
||||
}
|
||||
Generated
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
Copyright (c) 2012 Another-D-Mention Software and other contributors,
|
||||
http://www.another-d-mention.ro/
|
||||
|
||||
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.
|
||||
Generated
Vendored
-65
@@ -1,65 +0,0 @@
|
||||
# ADM-ZIP for NodeJS with added support for electron original-fs
|
||||
|
||||
ADM-ZIP is a pure JavaScript implementation for zip data compression for [NodeJS](https://nodejs.org/).
|
||||
|
||||
# Installation
|
||||
|
||||
With [npm](https://www.npmjs.com/) do:
|
||||
|
||||
$ npm install adm-zip
|
||||
|
||||
## What is it good for?
|
||||
The library allows you to:
|
||||
|
||||
* decompress zip files directly to disk or in memory buffers
|
||||
* compress files and store them to disk in .zip format or in compressed buffers
|
||||
* update content of/add new/delete files from an existing .zip
|
||||
|
||||
# Dependencies
|
||||
There are no other nodeJS libraries that ADM-ZIP is dependent of
|
||||
|
||||
# Examples
|
||||
|
||||
## Basic usage
|
||||
```javascript
|
||||
|
||||
var AdmZip = require('adm-zip');
|
||||
|
||||
// reading archives
|
||||
var zip = new AdmZip("./my_file.zip");
|
||||
var zipEntries = zip.getEntries(); // an array of ZipEntry records
|
||||
|
||||
zipEntries.forEach(function(zipEntry) {
|
||||
console.log(zipEntry.toString()); // outputs zip entries information
|
||||
if (zipEntry.entryName == "my_file.txt") {
|
||||
console.log(zipEntry.getData().toString('utf8'));
|
||||
}
|
||||
});
|
||||
// outputs the content of some_folder/my_file.txt
|
||||
console.log(zip.readAsText("some_folder/my_file.txt"));
|
||||
// extracts the specified file to the specified location
|
||||
zip.extractEntryTo(/*entry name*/"some_folder/my_file.txt", /*target path*/"/home/me/tempfolder", /*maintainEntryPath*/false, /*overwrite*/true);
|
||||
// extracts everything
|
||||
zip.extractAllTo(/*target path*/"/home/me/zipcontent/", /*overwrite*/true);
|
||||
|
||||
|
||||
// creating archives
|
||||
var zip = new AdmZip();
|
||||
|
||||
// add file directly
|
||||
var content = "inner content of the file";
|
||||
zip.addFile("test.txt", Buffer.alloc(content.length, content), "entry comment goes here");
|
||||
// add local file
|
||||
zip.addLocalFile("/home/me/some_picture.png");
|
||||
// get everything as a buffer
|
||||
var willSendthis = zip.toBuffer();
|
||||
// or write everything to disk
|
||||
zip.writeZip(/*target file name*/"/home/me/files.zip");
|
||||
|
||||
|
||||
// ... more examples in the wiki
|
||||
```
|
||||
|
||||
For more detailed information please check out the [wiki](https://github.com/cthackers/adm-zip/wiki).
|
||||
|
||||
[](https://travis-ci.org/cthackers/adm-zip)
|
||||
Generated
Vendored
-639
@@ -1,639 +0,0 @@
|
||||
var Utils = require("./util");
|
||||
var fs = Utils.FileSystem.require(),
|
||||
pth = require("path");
|
||||
|
||||
fs.existsSync = fs.existsSync || pth.existsSync;
|
||||
|
||||
var ZipEntry = require("./zipEntry"),
|
||||
ZipFile = require("./zipFile");
|
||||
|
||||
var isWin = /^win/.test(process.platform);
|
||||
|
||||
|
||||
module.exports = function (/**String*/input) {
|
||||
var _zip = undefined,
|
||||
_filename = "";
|
||||
|
||||
if (input && typeof input === "string") { // load zip file
|
||||
if (fs.existsSync(input)) {
|
||||
_filename = input;
|
||||
_zip = new ZipFile(input, Utils.Constants.FILE);
|
||||
} else {
|
||||
throw new Error(Utils.Errors.INVALID_FILENAME);
|
||||
}
|
||||
} else if (input && Buffer.isBuffer(input)) { // load buffer
|
||||
_zip = new ZipFile(input, Utils.Constants.BUFFER);
|
||||
} else { // create new zip file
|
||||
_zip = new ZipFile(null, Utils.Constants.NONE);
|
||||
}
|
||||
|
||||
function sanitize(prefix, name) {
|
||||
prefix = pth.resolve(pth.normalize(prefix));
|
||||
var parts = name.split('/');
|
||||
for (var i = 0, l = parts.length; i < l; i++) {
|
||||
var path = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
||||
if (path.indexOf(prefix) === 0) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return pth.normalize(pth.join(prefix, pth.basename(name)));
|
||||
}
|
||||
|
||||
function getEntry(/**Object*/entry) {
|
||||
if (entry && _zip) {
|
||||
var item;
|
||||
// If entry was given as a file name
|
||||
if (typeof entry === "string")
|
||||
item = _zip.getEntry(entry);
|
||||
// if entry was given as a ZipEntry object
|
||||
if (typeof entry === "object" && typeof entry.entryName !== "undefined" && typeof entry.header !== "undefined")
|
||||
item = _zip.getEntry(entry.entryName);
|
||||
|
||||
if (item) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Extracts the given entry from the archive and returns the content as a Buffer object
|
||||
* @param entry ZipEntry object or String with the full path of the entry
|
||||
*
|
||||
* @return Buffer or Null in case of error
|
||||
*/
|
||||
readFile: function (/**Object*/entry) {
|
||||
var item = getEntry(entry);
|
||||
return item && item.getData() || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous readFile
|
||||
* @param entry ZipEntry object or String with the full path of the entry
|
||||
* @param callback
|
||||
*
|
||||
* @return Buffer or Null in case of error
|
||||
*/
|
||||
readFileAsync: function (/**Object*/entry, /**Function*/callback) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
item.getDataAsync(callback);
|
||||
} else {
|
||||
callback(null, "getEntry failed for:" + entry)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the given entry from the archive and returns the content as plain text in the given encoding
|
||||
* @param entry ZipEntry object or String with the full path of the entry
|
||||
* @param encoding Optional. If no encoding is specified utf8 is used
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
readAsText: function (/**Object*/entry, /**String=*/encoding) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
var data = item.getData();
|
||||
if (data && data.length) {
|
||||
return data.toString(encoding || "utf8");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous readAsText
|
||||
* @param entry ZipEntry object or String with the full path of the entry
|
||||
* @param callback
|
||||
* @param encoding Optional. If no encoding is specified utf8 is used
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
readAsTextAsync: function (/**Object*/entry, /**Function*/callback, /**String=*/encoding) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
item.getDataAsync(function (data, err) {
|
||||
if (err) {
|
||||
callback(data, err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data && data.length) {
|
||||
callback(data.toString(encoding || "utf8"));
|
||||
} else {
|
||||
callback("");
|
||||
}
|
||||
})
|
||||
} else {
|
||||
callback("");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
|
||||
*
|
||||
* @param entry
|
||||
*/
|
||||
deleteFile: function (/**Object*/entry) { // @TODO: test deleteFile
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
_zip.deleteEntry(item.entryName);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a comment to the zip. The zip must be rewritten after adding the comment.
|
||||
*
|
||||
* @param comment
|
||||
*/
|
||||
addZipComment: function (/**String*/comment) { // @TODO: test addZipComment
|
||||
_zip.comment = comment;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the zip comment
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
getZipComment: function () {
|
||||
return _zip.comment || '';
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment
|
||||
* The comment cannot exceed 65535 characters in length
|
||||
*
|
||||
* @param entry
|
||||
* @param comment
|
||||
*/
|
||||
addZipEntryComment: function (/**Object*/entry, /**String*/comment) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
item.comment = comment;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the comment of the specified entry
|
||||
*
|
||||
* @param entry
|
||||
* @return String
|
||||
*/
|
||||
getZipEntryComment: function (/**Object*/entry) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
return item.comment || '';
|
||||
}
|
||||
return ''
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content
|
||||
*
|
||||
* @param entry
|
||||
* @param content
|
||||
*/
|
||||
updateFile: function (/**Object*/entry, /**Buffer*/content) {
|
||||
var item = getEntry(entry);
|
||||
if (item) {
|
||||
item.setData(content);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a file from the disk to the archive
|
||||
*
|
||||
* @param localPath File to add to zip
|
||||
* @param zipPath Optional path inside the zip
|
||||
* @param zipName Optional name for the file
|
||||
*/
|
||||
addLocalFile: function (/**String*/localPath, /**String=*/zipPath, /**String=*/zipName) {
|
||||
if (fs.existsSync(localPath)) {
|
||||
if (zipPath) {
|
||||
zipPath = zipPath.split("\\").join("/");
|
||||
if (zipPath.charAt(zipPath.length - 1) !== "/") {
|
||||
zipPath += "/";
|
||||
}
|
||||
} else {
|
||||
zipPath = "";
|
||||
}
|
||||
var p = localPath.split("\\").join("/").split("/").pop();
|
||||
|
||||
if (zipName) {
|
||||
this.addFile(zipPath + zipName, fs.readFileSync(localPath), "", 0)
|
||||
} else {
|
||||
this.addFile(zipPath + p, fs.readFileSync(localPath), "", 0)
|
||||
}
|
||||
} else {
|
||||
throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a local directory and all its nested files and directories to the archive
|
||||
*
|
||||
* @param localPath
|
||||
* @param zipPath optional path inside zip
|
||||
* @param filter optional RegExp or Function if files match will
|
||||
* be included.
|
||||
*/
|
||||
addLocalFolder: function (/**String*/localPath, /**String=*/zipPath, /**=RegExp|Function*/filter) {
|
||||
if (filter === undefined) {
|
||||
filter = function () {
|
||||
return true;
|
||||
};
|
||||
} else if (filter instanceof RegExp) {
|
||||
filter = function (filter) {
|
||||
return function (filename) {
|
||||
return filter.test(filename);
|
||||
}
|
||||
}(filter);
|
||||
}
|
||||
|
||||
if (zipPath) {
|
||||
zipPath = zipPath.split("\\").join("/");
|
||||
if (zipPath.charAt(zipPath.length - 1) !== "/") {
|
||||
zipPath += "/";
|
||||
}
|
||||
} else {
|
||||
zipPath = "";
|
||||
}
|
||||
// normalize the path first
|
||||
localPath = pth.normalize(localPath);
|
||||
localPath = localPath.split("\\").join("/"); //windows fix
|
||||
if (localPath.charAt(localPath.length - 1) !== "/")
|
||||
localPath += "/";
|
||||
|
||||
if (fs.existsSync(localPath)) {
|
||||
|
||||
var items = Utils.findFiles(localPath),
|
||||
self = this;
|
||||
|
||||
if (items.length) {
|
||||
items.forEach(function (path) {
|
||||
var p = path.split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\)|\$)/g, '\\$1'), 'i'), ""); //windows fix
|
||||
if (filter(p)) {
|
||||
if (p.charAt(p.length - 1) !== "/") {
|
||||
self.addFile(zipPath + p, fs.readFileSync(path), "", 0)
|
||||
} else {
|
||||
self.addFile(zipPath + p, Buffer.alloc(0), "", 0)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous addLocalFile
|
||||
* @param localPath
|
||||
* @param callback
|
||||
* @param zipPath optional path inside zip
|
||||
* @param filter optional RegExp or Function if files match will
|
||||
* be included.
|
||||
*/
|
||||
addLocalFolderAsync: function (/*String*/localPath, /*Function*/callback, /*String*/zipPath, /*RegExp|Function*/filter) {
|
||||
if (filter === undefined) {
|
||||
filter = function () {
|
||||
return true;
|
||||
};
|
||||
} else if (filter instanceof RegExp) {
|
||||
filter = function (filter) {
|
||||
return function (filename) {
|
||||
return filter.test(filename);
|
||||
}
|
||||
}(filter);
|
||||
}
|
||||
|
||||
if (zipPath) {
|
||||
zipPath = zipPath.split("\\").join("/");
|
||||
if (zipPath.charAt(zipPath.length - 1) !== "/") {
|
||||
zipPath += "/";
|
||||
}
|
||||
} else {
|
||||
zipPath = "";
|
||||
}
|
||||
// normalize the path first
|
||||
localPath = pth.normalize(localPath);
|
||||
localPath = localPath.split("\\").join("/"); //windows fix
|
||||
if (localPath.charAt(localPath.length - 1) !== "/")
|
||||
localPath += "/";
|
||||
|
||||
var self = this;
|
||||
fs.open(localPath, 'r', function (err, fd) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
callback(undefined, Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
|
||||
} else if (err) {
|
||||
callback(undefined, err);
|
||||
} else {
|
||||
var items = Utils.findFiles(localPath);
|
||||
var i = -1;
|
||||
|
||||
var next = function () {
|
||||
i += 1;
|
||||
if (i < items.length) {
|
||||
var p = items[i].split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\))/g, '\\$1'), 'i'), ""); //windows fix
|
||||
p = p.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^\x20-\x7E]/g, '') // accent fix
|
||||
if (filter(p)) {
|
||||
if (p.charAt(p.length - 1) !== "/") {
|
||||
fs.readFile(items[i], function (err, data) {
|
||||
if (err) {
|
||||
callback(undefined, err);
|
||||
} else {
|
||||
self.addFile(zipPath + p, data, '', 0);
|
||||
next();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.addFile(zipPath + p, Buffer.alloc(0), "", 0);
|
||||
next();
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
|
||||
} else {
|
||||
callback(true, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows you to create a entry (file or directory) in the zip file.
|
||||
* If you want to create a directory the entryName must end in / and a null buffer should be provided.
|
||||
* Comment and attributes are optional
|
||||
*
|
||||
* @param entryName
|
||||
* @param content
|
||||
* @param comment
|
||||
* @param attr
|
||||
*/
|
||||
addFile: function (/**String*/entryName, /**Buffer*/content, /**String*/comment, /**Number*/attr) {
|
||||
var entry = new ZipEntry();
|
||||
entry.entryName = entryName;
|
||||
entry.comment = comment || "";
|
||||
|
||||
if (!attr) {
|
||||
if (entry.isDirectory) {
|
||||
attr = (0o40755 << 16) | 0x10; // (permissions drwxr-xr-x) + (MS-DOS directory flag)
|
||||
} else {
|
||||
attr = 0o644 << 16; // permissions -r-wr--r--
|
||||
}
|
||||
}
|
||||
|
||||
entry.attr = attr;
|
||||
|
||||
entry.setData(content);
|
||||
_zip.setEntry(entry);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of ZipEntry objects representing the files and folders inside the archive
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
getEntries: function () {
|
||||
if (_zip) {
|
||||
return _zip.entries;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a ZipEntry object representing the file or folder specified by ``name``.
|
||||
*
|
||||
* @param name
|
||||
* @return ZipEntry
|
||||
*/
|
||||
getEntry: function (/**String*/name) {
|
||||
return getEntry(name);
|
||||
},
|
||||
|
||||
getEntryCount: function() {
|
||||
return _zip.getEntryCount();
|
||||
},
|
||||
|
||||
forEach: function(callback) {
|
||||
return _zip.forEach(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the given entry to the given targetPath
|
||||
* If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted
|
||||
*
|
||||
* @param entry ZipEntry object or String with the full path of the entry
|
||||
* @param targetPath Target folder where to write the file
|
||||
* @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder
|
||||
* will be created in targetPath as well. Default is TRUE
|
||||
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
|
||||
* Default is FALSE
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
extractEntryTo: function (/**Object*/entry, /**String*/targetPath, /**Boolean*/maintainEntryPath, /**Boolean*/overwrite) {
|
||||
overwrite = overwrite || false;
|
||||
maintainEntryPath = typeof maintainEntryPath === "undefined" ? true : maintainEntryPath;
|
||||
|
||||
var item = getEntry(entry);
|
||||
if (!item) {
|
||||
throw new Error(Utils.Errors.NO_ENTRY);
|
||||
}
|
||||
|
||||
var entryName = item.entryName;
|
||||
|
||||
var target = sanitize(targetPath, maintainEntryPath ? entryName : pth.basename(entryName));
|
||||
|
||||
if (item.isDirectory) {
|
||||
target = pth.resolve(target, "..");
|
||||
var children = _zip.getEntryChildren(item);
|
||||
children.forEach(function (child) {
|
||||
if (child.isDirectory) return;
|
||||
var content = child.getData();
|
||||
if (!content) {
|
||||
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
|
||||
}
|
||||
var childName = sanitize(targetPath, maintainEntryPath ? child.entryName : pth.basename(child.entryName));
|
||||
|
||||
Utils.writeFileTo(childName, content, overwrite);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
var content = item.getData();
|
||||
if (!content) throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
|
||||
|
||||
if (fs.existsSync(target) && !overwrite) {
|
||||
throw new Error(Utils.Errors.CANT_OVERRIDE);
|
||||
}
|
||||
Utils.writeFileTo(target, content, overwrite);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Test the archive
|
||||
*
|
||||
*/
|
||||
test: function () {
|
||||
if (!_zip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var entry in _zip.entries) {
|
||||
try {
|
||||
if (entry.isDirectory) {
|
||||
continue;
|
||||
}
|
||||
var content = _zip.entries[entry].getData();
|
||||
if (!content) {
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the entire archive to the given location
|
||||
*
|
||||
* @param targetPath Target location
|
||||
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
|
||||
* Default is FALSE
|
||||
*/
|
||||
extractAllTo: function (/**String*/targetPath, /**Boolean*/overwrite) {
|
||||
overwrite = overwrite || false;
|
||||
if (!_zip) {
|
||||
throw new Error(Utils.Errors.NO_ZIP);
|
||||
}
|
||||
_zip.entries.forEach(function (entry) {
|
||||
var entryName = sanitize(targetPath, entry.entryName.toString());
|
||||
if (entry.isDirectory) {
|
||||
Utils.makeDir(entryName);
|
||||
return;
|
||||
}
|
||||
var content = entry.getData();
|
||||
if (!content) {
|
||||
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
|
||||
}
|
||||
Utils.writeFileTo(entryName, content, overwrite);
|
||||
try {
|
||||
fs.utimesSync(entryName, entry.header.time, entry.header.time)
|
||||
} catch (err) {
|
||||
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous extractAllTo
|
||||
*
|
||||
* @param targetPath Target location
|
||||
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
|
||||
* Default is FALSE
|
||||
* @param callback
|
||||
*/
|
||||
extractAllToAsync: function (/**String*/targetPath, /**Boolean*/overwrite, /**Function*/callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
overwrite = overwrite || false;
|
||||
if (!_zip) {
|
||||
callback(new Error(Utils.Errors.NO_ZIP));
|
||||
return;
|
||||
}
|
||||
|
||||
var entries = _zip.entries;
|
||||
var i = entries.length;
|
||||
entries.forEach(function (entry) {
|
||||
if (i <= 0) return; // Had an error already
|
||||
|
||||
var entryName = pth.normalize(entry.entryName.toString());
|
||||
|
||||
if (entry.isDirectory) {
|
||||
Utils.makeDir(sanitize(targetPath, entryName));
|
||||
if (--i === 0)
|
||||
callback(undefined);
|
||||
return;
|
||||
}
|
||||
entry.getDataAsync(function (content, err) {
|
||||
if (i <= 0) return;
|
||||
if (err) {
|
||||
callback(new Error(err));
|
||||
return;
|
||||
}
|
||||
if (!content) {
|
||||
i = 0;
|
||||
callback(new Error(Utils.Errors.CANT_EXTRACT_FILE));
|
||||
return;
|
||||
}
|
||||
|
||||
Utils.writeFileToAsync(sanitize(targetPath, entryName), content, overwrite, function (succ) {
|
||||
try {
|
||||
fs.utimesSync(pth.resolve(targetPath, entryName), entry.header.time, entry.header.time);
|
||||
} catch (err) {
|
||||
callback(new Error('Unable to set utimes'));
|
||||
}
|
||||
if (i <= 0) return;
|
||||
if (!succ) {
|
||||
i = 0;
|
||||
callback(new Error('Unable to write'));
|
||||
return;
|
||||
}
|
||||
if (--i === 0)
|
||||
callback(undefined);
|
||||
});
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip
|
||||
*
|
||||
* @param targetFileName
|
||||
* @param callback
|
||||
*/
|
||||
writeZip: function (/**String*/targetFileName, /**Function*/callback) {
|
||||
if (arguments.length === 1) {
|
||||
if (typeof targetFileName === "function") {
|
||||
callback = targetFileName;
|
||||
targetFileName = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetFileName && _filename) {
|
||||
targetFileName = _filename;
|
||||
}
|
||||
if (!targetFileName) return;
|
||||
|
||||
var zipData = _zip.compressToBuffer();
|
||||
if (zipData) {
|
||||
var ok = Utils.writeFileTo(targetFileName, zipData, true);
|
||||
if (typeof callback === 'function') callback(!ok ? new Error("failed") : null, "");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the content of the entire zip file as a Buffer object
|
||||
*
|
||||
* @return Buffer
|
||||
*/
|
||||
toBuffer: function (/**Function=*/onSuccess, /**Function=*/onFail, /**Function=*/onItemStart, /**Function=*/onItemEnd) {
|
||||
this.valueOf = 2;
|
||||
if (typeof onSuccess === "function") {
|
||||
_zip.toAsyncBuffer(onSuccess, onFail, onItemStart, onItemEnd);
|
||||
return null;
|
||||
}
|
||||
return _zip.compressToBuffer()
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-261
@@ -1,261 +0,0 @@
|
||||
var Utils = require("../util"),
|
||||
Constants = Utils.Constants;
|
||||
|
||||
/* The central directory file header */
|
||||
module.exports = function () {
|
||||
var _verMade = 0x0A,
|
||||
_version = 0x0A,
|
||||
_flags = 0,
|
||||
_method = 0,
|
||||
_time = 0,
|
||||
_crc = 0,
|
||||
_compressedSize = 0,
|
||||
_size = 0,
|
||||
_fnameLen = 0,
|
||||
_extraLen = 0,
|
||||
|
||||
_comLen = 0,
|
||||
_diskStart = 0,
|
||||
_inattr = 0,
|
||||
_attr = 0,
|
||||
_offset = 0;
|
||||
|
||||
var _dataHeader = {};
|
||||
|
||||
function setTime(val) {
|
||||
val = new Date(val);
|
||||
_time = (val.getFullYear() - 1980 & 0x7f) << 25 // b09-16 years from 1980
|
||||
| (val.getMonth() + 1) << 21 // b05-08 month
|
||||
| val.getDate() << 16 // b00-04 hour
|
||||
|
||||
// 2 bytes time
|
||||
| val.getHours() << 11 // b11-15 hour
|
||||
| val.getMinutes() << 5 // b05-10 minute
|
||||
| val.getSeconds() >> 1; // b00-04 seconds divided by 2
|
||||
}
|
||||
|
||||
setTime(+new Date());
|
||||
|
||||
return {
|
||||
get made () { return _verMade; },
|
||||
set made (val) { _verMade = val; },
|
||||
|
||||
get version () { return _version; },
|
||||
set version (val) { _version = val },
|
||||
|
||||
get flags () { return _flags },
|
||||
set flags (val) { _flags = val; },
|
||||
|
||||
get method () { return _method; },
|
||||
set method (val) { _method = val; },
|
||||
|
||||
get time () { return new Date(
|
||||
((_time >> 25) & 0x7f) + 1980,
|
||||
((_time >> 21) & 0x0f) - 1,
|
||||
(_time >> 16) & 0x1f,
|
||||
(_time >> 11) & 0x1f,
|
||||
(_time >> 5) & 0x3f,
|
||||
(_time & 0x1f) << 1
|
||||
);
|
||||
},
|
||||
set time (val) {
|
||||
setTime(val);
|
||||
},
|
||||
|
||||
get crc () { return _crc; },
|
||||
set crc (val) { _crc = val; },
|
||||
|
||||
get compressedSize () { return _compressedSize; },
|
||||
set compressedSize (val) { _compressedSize = val; },
|
||||
|
||||
get size () { return _size; },
|
||||
set size (val) { _size = val; },
|
||||
|
||||
get fileNameLength () { return _fnameLen; },
|
||||
set fileNameLength (val) { _fnameLen = val; },
|
||||
|
||||
get extraLength () { return _extraLen },
|
||||
set extraLength (val) { _extraLen = val; },
|
||||
|
||||
get commentLength () { return _comLen },
|
||||
set commentLength (val) { _comLen = val },
|
||||
|
||||
get diskNumStart () { return _diskStart },
|
||||
set diskNumStart (val) { _diskStart = val },
|
||||
|
||||
get inAttr () { return _inattr },
|
||||
set inAttr (val) { _inattr = val },
|
||||
|
||||
get attr () { return _attr },
|
||||
set attr (val) { _attr = val },
|
||||
|
||||
get offset () { return _offset },
|
||||
set offset (val) { _offset = val },
|
||||
|
||||
get encripted () { return (_flags & 1) === 1 },
|
||||
|
||||
get entryHeaderSize () {
|
||||
return Constants.CENHDR + _fnameLen + _extraLen + _comLen;
|
||||
},
|
||||
|
||||
get realDataOffset () {
|
||||
return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen;
|
||||
},
|
||||
|
||||
get dataHeader () {
|
||||
return _dataHeader;
|
||||
},
|
||||
|
||||
loadDataHeaderFromBinary : function(/*Buffer*/input) {
|
||||
var data = input.slice(_offset, _offset + Constants.LOCHDR);
|
||||
// 30 bytes and should start with "PK\003\004"
|
||||
if (data.readUInt32LE(0) !== Constants.LOCSIG) {
|
||||
throw new Error(Utils.Errors.INVALID_LOC);
|
||||
}
|
||||
_dataHeader = {
|
||||
// version needed to extract
|
||||
version : data.readUInt16LE(Constants.LOCVER),
|
||||
// general purpose bit flag
|
||||
flags : data.readUInt16LE(Constants.LOCFLG),
|
||||
// compression method
|
||||
method : data.readUInt16LE(Constants.LOCHOW),
|
||||
// modification time (2 bytes time, 2 bytes date)
|
||||
time : data.readUInt32LE(Constants.LOCTIM),
|
||||
// uncompressed file crc-32 value
|
||||
crc : data.readUInt32LE(Constants.LOCCRC),
|
||||
// compressed size
|
||||
compressedSize : data.readUInt32LE(Constants.LOCSIZ),
|
||||
// uncompressed size
|
||||
size : data.readUInt32LE(Constants.LOCLEN),
|
||||
// filename length
|
||||
fnameLen : data.readUInt16LE(Constants.LOCNAM),
|
||||
// extra field length
|
||||
extraLen : data.readUInt16LE(Constants.LOCEXT)
|
||||
}
|
||||
},
|
||||
|
||||
loadFromBinary : function(/*Buffer*/data) {
|
||||
// data should be 46 bytes and start with "PK 01 02"
|
||||
if (data.length !== Constants.CENHDR || data.readUInt32LE(0) !== Constants.CENSIG) {
|
||||
throw new Error(Utils.Errors.INVALID_CEN);
|
||||
}
|
||||
// version made by
|
||||
_verMade = data.readUInt16LE(Constants.CENVEM);
|
||||
// version needed to extract
|
||||
_version = data.readUInt16LE(Constants.CENVER);
|
||||
// encrypt, decrypt flags
|
||||
_flags = data.readUInt16LE(Constants.CENFLG);
|
||||
// compression method
|
||||
_method = data.readUInt16LE(Constants.CENHOW);
|
||||
// modification time (2 bytes time, 2 bytes date)
|
||||
_time = data.readUInt32LE(Constants.CENTIM);
|
||||
// uncompressed file crc-32 value
|
||||
_crc = data.readUInt32LE(Constants.CENCRC);
|
||||
// compressed size
|
||||
_compressedSize = data.readUInt32LE(Constants.CENSIZ);
|
||||
// uncompressed size
|
||||
_size = data.readUInt32LE(Constants.CENLEN);
|
||||
// filename length
|
||||
_fnameLen = data.readUInt16LE(Constants.CENNAM);
|
||||
// extra field length
|
||||
_extraLen = data.readUInt16LE(Constants.CENEXT);
|
||||
// file comment length
|
||||
_comLen = data.readUInt16LE(Constants.CENCOM);
|
||||
// volume number start
|
||||
_diskStart = data.readUInt16LE(Constants.CENDSK);
|
||||
// internal file attributes
|
||||
_inattr = data.readUInt16LE(Constants.CENATT);
|
||||
// external file attributes
|
||||
_attr = data.readUInt32LE(Constants.CENATX);
|
||||
// LOC header offset
|
||||
_offset = data.readUInt32LE(Constants.CENOFF);
|
||||
},
|
||||
|
||||
dataHeaderToBinary : function() {
|
||||
// LOC header size (30 bytes)
|
||||
var data = Buffer.alloc(Constants.LOCHDR);
|
||||
// "PK\003\004"
|
||||
data.writeUInt32LE(Constants.LOCSIG, 0);
|
||||
// version needed to extract
|
||||
data.writeUInt16LE(_version, Constants.LOCVER);
|
||||
// general purpose bit flag
|
||||
data.writeUInt16LE(_flags, Constants.LOCFLG);
|
||||
// compression method
|
||||
data.writeUInt16LE(_method, Constants.LOCHOW);
|
||||
// modification time (2 bytes time, 2 bytes date)
|
||||
data.writeUInt32LE(_time, Constants.LOCTIM);
|
||||
// uncompressed file crc-32 value
|
||||
data.writeUInt32LE(_crc, Constants.LOCCRC);
|
||||
// compressed size
|
||||
data.writeUInt32LE(_compressedSize, Constants.LOCSIZ);
|
||||
// uncompressed size
|
||||
data.writeUInt32LE(_size, Constants.LOCLEN);
|
||||
// filename length
|
||||
data.writeUInt16LE(_fnameLen, Constants.LOCNAM);
|
||||
// extra field length
|
||||
data.writeUInt16LE(_extraLen, Constants.LOCEXT);
|
||||
return data;
|
||||
},
|
||||
|
||||
entryHeaderToBinary : function() {
|
||||
// CEN header size (46 bytes)
|
||||
var data = Buffer.alloc(Constants.CENHDR + _fnameLen + _extraLen + _comLen);
|
||||
// "PK\001\002"
|
||||
data.writeUInt32LE(Constants.CENSIG, 0);
|
||||
// version made by
|
||||
data.writeUInt16LE(_verMade, Constants.CENVEM);
|
||||
// version needed to extract
|
||||
data.writeUInt16LE(_version, Constants.CENVER);
|
||||
// encrypt, decrypt flags
|
||||
data.writeUInt16LE(_flags, Constants.CENFLG);
|
||||
// compression method
|
||||
data.writeUInt16LE(_method, Constants.CENHOW);
|
||||
// modification time (2 bytes time, 2 bytes date)
|
||||
data.writeUInt32LE(_time, Constants.CENTIM);
|
||||
// uncompressed file crc-32 value
|
||||
data.writeUInt32LE(_crc, Constants.CENCRC);
|
||||
// compressed size
|
||||
data.writeUInt32LE(_compressedSize, Constants.CENSIZ);
|
||||
// uncompressed size
|
||||
data.writeUInt32LE(_size, Constants.CENLEN);
|
||||
// filename length
|
||||
data.writeUInt16LE(_fnameLen, Constants.CENNAM);
|
||||
// extra field length
|
||||
data.writeUInt16LE(_extraLen, Constants.CENEXT);
|
||||
// file comment length
|
||||
data.writeUInt16LE(_comLen, Constants.CENCOM);
|
||||
// volume number start
|
||||
data.writeUInt16LE(_diskStart, Constants.CENDSK);
|
||||
// internal file attributes
|
||||
data.writeUInt16LE(_inattr, Constants.CENATT);
|
||||
// external file attributes
|
||||
data.writeUInt32LE(_attr, Constants.CENATX);
|
||||
// LOC header offset
|
||||
data.writeUInt32LE(_offset, Constants.CENOFF);
|
||||
// fill all with
|
||||
data.fill(0x00, Constants.CENHDR);
|
||||
return data;
|
||||
},
|
||||
|
||||
toString : function() {
|
||||
return '{\n' +
|
||||
'\t"made" : ' + _verMade + ",\n" +
|
||||
'\t"version" : ' + _version + ",\n" +
|
||||
'\t"flags" : ' + _flags + ",\n" +
|
||||
'\t"method" : ' + Utils.methodToString(_method) + ",\n" +
|
||||
'\t"time" : ' + this.time + ",\n" +
|
||||
'\t"crc" : 0x' + _crc.toString(16).toUpperCase() + ",\n" +
|
||||
'\t"compressedSize" : ' + _compressedSize + " bytes,\n" +
|
||||
'\t"size" : ' + _size + " bytes,\n" +
|
||||
'\t"fileNameLength" : ' + _fnameLen + ",\n" +
|
||||
'\t"extraLength" : ' + _extraLen + " bytes,\n" +
|
||||
'\t"commentLength" : ' + _comLen + " bytes,\n" +
|
||||
'\t"diskNumStart" : ' + _diskStart + ",\n" +
|
||||
'\t"inAttr" : ' + _inattr + ",\n" +
|
||||
'\t"attr" : ' + _attr + ",\n" +
|
||||
'\t"offset" : ' + _offset + ",\n" +
|
||||
'\t"entryHeaderSize" : ' + (Constants.CENHDR + _fnameLen + _extraLen + _comLen) + " bytes\n" +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
exports.EntryHeader = require("./entryHeader");
|
||||
exports.MainHeader = require("./mainHeader");
|
||||
Generated
Vendored
-98
@@ -1,98 +0,0 @@
|
||||
var Utils = require("../util"),
|
||||
Constants = Utils.Constants;
|
||||
|
||||
/* The entries in the end of central directory */
|
||||
module.exports = function () {
|
||||
var _volumeEntries = 0,
|
||||
_totalEntries = 0,
|
||||
_size = 0,
|
||||
_offset = 0,
|
||||
_commentLength = 0;
|
||||
|
||||
return {
|
||||
get diskEntries () { return _volumeEntries },
|
||||
set diskEntries (/*Number*/val) { _volumeEntries = _totalEntries = val; },
|
||||
|
||||
get totalEntries () { return _totalEntries },
|
||||
set totalEntries (/*Number*/val) { _totalEntries = _volumeEntries = val; },
|
||||
|
||||
get size () { return _size },
|
||||
set size (/*Number*/val) { _size = val; },
|
||||
|
||||
get offset () { return _offset },
|
||||
set offset (/*Number*/val) { _offset = val; },
|
||||
|
||||
get commentLength () { return _commentLength },
|
||||
set commentLength (/*Number*/val) { _commentLength = val; },
|
||||
|
||||
get mainHeaderSize () {
|
||||
return Constants.ENDHDR + _commentLength;
|
||||
},
|
||||
|
||||
loadFromBinary : function(/*Buffer*/data) {
|
||||
// data should be 22 bytes and start with "PK 05 06"
|
||||
// or be 56+ bytes and start with "PK 06 06" for Zip64
|
||||
if ((data.length !== Constants.ENDHDR || data.readUInt32LE(0) !== Constants.ENDSIG) &&
|
||||
(data.length < Constants.ZIP64HDR || data.readUInt32LE(0) !== Constants.ZIP64SIG)) {
|
||||
|
||||
throw new Error(Utils.Errors.INVALID_END);
|
||||
}
|
||||
|
||||
if (data.readUInt32LE(0) === Constants.ENDSIG) {
|
||||
// number of entries on this volume
|
||||
_volumeEntries = data.readUInt16LE(Constants.ENDSUB);
|
||||
// total number of entries
|
||||
_totalEntries = data.readUInt16LE(Constants.ENDTOT);
|
||||
// central directory size in bytes
|
||||
_size = data.readUInt32LE(Constants.ENDSIZ);
|
||||
// offset of first CEN header
|
||||
_offset = data.readUInt32LE(Constants.ENDOFF);
|
||||
// zip file comment length
|
||||
_commentLength = data.readUInt16LE(Constants.ENDCOM);
|
||||
} else {
|
||||
// number of entries on this volume
|
||||
_volumeEntries = Utils.readBigUInt64LE(data, Constants.ZIP64SUB);
|
||||
// total number of entries
|
||||
_totalEntries = Utils.readBigUInt64LE(data, Constants.ZIP64TOT);
|
||||
// central directory size in bytes
|
||||
_size = Utils.readBigUInt64LE(data, Constants.ZIP64SIZ);
|
||||
// offset of first CEN header
|
||||
_offset = Utils.readBigUInt64LE(data, Constants.ZIP64OFF);
|
||||
|
||||
_commentLength = 0;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
toBinary : function() {
|
||||
var b = Buffer.alloc(Constants.ENDHDR + _commentLength);
|
||||
// "PK 05 06" signature
|
||||
b.writeUInt32LE(Constants.ENDSIG, 0);
|
||||
b.writeUInt32LE(0, 4);
|
||||
// number of entries on this volume
|
||||
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
||||
// total number of entries
|
||||
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
||||
// central directory size in bytes
|
||||
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
||||
// offset of first CEN header
|
||||
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
||||
// zip file comment length
|
||||
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
||||
// fill comment memory with spaces so no garbage is left there
|
||||
b.fill(" ", Constants.ENDHDR);
|
||||
|
||||
return b;
|
||||
},
|
||||
|
||||
toString : function() {
|
||||
return '{\n' +
|
||||
'\t"diskEntries" : ' + _volumeEntries + ",\n" +
|
||||
'\t"totalEntries" : ' + _totalEntries + ",\n" +
|
||||
'\t"size" : ' + _size + " bytes,\n" +
|
||||
'\t"offset" : 0x' + _offset.toString(16).toUpperCase() + ",\n" +
|
||||
'\t"commentLength" : 0x' + _commentLength + "\n" +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
module.exports = function (/*Buffer*/inbuf) {
|
||||
|
||||
var zlib = require("zlib");
|
||||
|
||||
var opts = {chunkSize: (parseInt(inbuf.length / 1024) + 1) * 1024};
|
||||
|
||||
return {
|
||||
deflate: function () {
|
||||
return zlib.deflateRawSync(inbuf, opts);
|
||||
},
|
||||
|
||||
deflateAsync: function (/*Function*/callback) {
|
||||
var tmp = zlib.createDeflateRaw(opts), parts = [], total = 0;
|
||||
tmp.on('data', function (data) {
|
||||
parts.push(data);
|
||||
total += data.length;
|
||||
});
|
||||
tmp.on('end', function () {
|
||||
var buf = Buffer.alloc(total), written = 0;
|
||||
buf.fill(0);
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
part.copy(buf, written);
|
||||
written += part.length;
|
||||
}
|
||||
callback && callback(buf);
|
||||
});
|
||||
tmp.end(inbuf);
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
exports.Deflater = require("./deflater");
|
||||
exports.Inflater = require("./inflater");
|
||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
||||
module.exports = function (/*Buffer*/inbuf) {
|
||||
|
||||
var zlib = require("zlib");
|
||||
|
||||
return {
|
||||
inflate: function () {
|
||||
return zlib.inflateRawSync(inbuf);
|
||||
},
|
||||
|
||||
inflateAsync: function (/*Function*/callback) {
|
||||
var tmp = zlib.createInflateRaw(), parts = [], total = 0;
|
||||
tmp.on('data', function (data) {
|
||||
parts.push(data);
|
||||
total += data.length;
|
||||
});
|
||||
tmp.on('end', function () {
|
||||
var buf = Buffer.alloc(total), written = 0;
|
||||
buf.fill(0);
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
part.copy(buf, written);
|
||||
written += part.length;
|
||||
}
|
||||
callback && callback(buf);
|
||||
});
|
||||
tmp.end(inbuf);
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"name": "adm-zip",
|
||||
"version": "0.4.16",
|
||||
"description": "Javascript implementation of zip for nodejs with support for electron original-fs. Allows user to create or extract zip files both in memory or to/from disk",
|
||||
"scripts": {
|
||||
"test": "mocha test/mocha.js test/crc/index.js"
|
||||
},
|
||||
"keywords": [
|
||||
"zip",
|
||||
"methods",
|
||||
"archive",
|
||||
"unzip"
|
||||
],
|
||||
"homepage": "https://github.com/cthackers/adm-zip",
|
||||
"author": "Nasca Iacob <sy@another-d-mention.ro> (https://github.com/cthackers)",
|
||||
"bugs": {
|
||||
"email": "sy@another-d-mention.ro",
|
||||
"url": "https://github.com/cthackers/adm-zip/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"adm-zip.js",
|
||||
"headers",
|
||||
"methods",
|
||||
"util",
|
||||
"zipEntry.js",
|
||||
"zipFile.js",
|
||||
"MIT-LICENSE.txt"
|
||||
],
|
||||
"main": "adm-zip.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cthackers/adm-zip.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.1.2",
|
||||
"mocha": "^8.0.1",
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz"
|
||||
,"_integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg=="
|
||||
,"_from": "adm-zip@0.4.16"
|
||||
}
|
||||
Generated
Vendored
-135
@@ -1,135 +0,0 @@
|
||||
module.exports = {
|
||||
/* The local file header */
|
||||
LOCHDR : 30, // LOC header size
|
||||
LOCSIG : 0x04034b50, // "PK\003\004"
|
||||
LOCVER : 4, // version needed to extract
|
||||
LOCFLG : 6, // general purpose bit flag
|
||||
LOCHOW : 8, // compression method
|
||||
LOCTIM : 10, // modification time (2 bytes time, 2 bytes date)
|
||||
LOCCRC : 14, // uncompressed file crc-32 value
|
||||
LOCSIZ : 18, // compressed size
|
||||
LOCLEN : 22, // uncompressed size
|
||||
LOCNAM : 26, // filename length
|
||||
LOCEXT : 28, // extra field length
|
||||
|
||||
/* The Data descriptor */
|
||||
EXTSIG : 0x08074b50, // "PK\007\008"
|
||||
EXTHDR : 16, // EXT header size
|
||||
EXTCRC : 4, // uncompressed file crc-32 value
|
||||
EXTSIZ : 8, // compressed size
|
||||
EXTLEN : 12, // uncompressed size
|
||||
|
||||
/* The central directory file header */
|
||||
CENHDR : 46, // CEN header size
|
||||
CENSIG : 0x02014b50, // "PK\001\002"
|
||||
CENVEM : 4, // version made by
|
||||
CENVER : 6, // version needed to extract
|
||||
CENFLG : 8, // encrypt, decrypt flags
|
||||
CENHOW : 10, // compression method
|
||||
CENTIM : 12, // modification time (2 bytes time, 2 bytes date)
|
||||
CENCRC : 16, // uncompressed file crc-32 value
|
||||
CENSIZ : 20, // compressed size
|
||||
CENLEN : 24, // uncompressed size
|
||||
CENNAM : 28, // filename length
|
||||
CENEXT : 30, // extra field length
|
||||
CENCOM : 32, // file comment length
|
||||
CENDSK : 34, // volume number start
|
||||
CENATT : 36, // internal file attributes
|
||||
CENATX : 38, // external file attributes (host system dependent)
|
||||
CENOFF : 42, // LOC header offset
|
||||
|
||||
/* The entries in the end of central directory */
|
||||
ENDHDR : 22, // END header size
|
||||
ENDSIG : 0x06054b50, // "PK\005\006"
|
||||
ENDSUB : 8, // number of entries on this disk
|
||||
ENDTOT : 10, // total number of entries
|
||||
ENDSIZ : 12, // central directory size in bytes
|
||||
ENDOFF : 16, // offset of first CEN header
|
||||
ENDCOM : 20, // zip file comment length
|
||||
|
||||
END64HDR : 20, // zip64 END header size
|
||||
END64SIG : 0x07064b50, // zip64 Locator signature, "PK\006\007"
|
||||
END64START : 4, // number of the disk with the start of the zip64
|
||||
END64OFF : 8, // relative offset of the zip64 end of central directory
|
||||
END64NUMDISKS : 16, // total number of disks
|
||||
|
||||
ZIP64SIG : 0x06064b50, // zip64 signature, "PK\006\006"
|
||||
ZIP64HDR : 56, // zip64 record minimum size
|
||||
ZIP64LEAD : 12, // leading bytes at the start of the record, not counted by the value stored in ZIP64SIZE
|
||||
ZIP64SIZE : 4, // zip64 size of the central directory record
|
||||
ZIP64VEM : 12, // zip64 version made by
|
||||
ZIP64VER : 14, // zip64 version needed to extract
|
||||
ZIP64DSK : 16, // zip64 number of this disk
|
||||
ZIP64DSKDIR : 20, // number of the disk with the start of the record directory
|
||||
ZIP64SUB : 24, // number of entries on this disk
|
||||
ZIP64TOT : 32, // total number of entries
|
||||
ZIP64SIZB : 40, // zip64 central directory size in bytes
|
||||
ZIP64OFF : 48, // offset of start of central directory with respect to the starting disk number
|
||||
ZIP64EXTRA : 56, // extensible data sector
|
||||
|
||||
/* Compression methods */
|
||||
STORED : 0, // no compression
|
||||
SHRUNK : 1, // shrunk
|
||||
REDUCED1 : 2, // reduced with compression factor 1
|
||||
REDUCED2 : 3, // reduced with compression factor 2
|
||||
REDUCED3 : 4, // reduced with compression factor 3
|
||||
REDUCED4 : 5, // reduced with compression factor 4
|
||||
IMPLODED : 6, // imploded
|
||||
// 7 reserved
|
||||
DEFLATED : 8, // deflated
|
||||
ENHANCED_DEFLATED: 9, // enhanced deflated
|
||||
PKWARE : 10,// PKWare DCL imploded
|
||||
// 11 reserved
|
||||
BZIP2 : 12, // compressed using BZIP2
|
||||
// 13 reserved
|
||||
LZMA : 14, // LZMA
|
||||
// 15-17 reserved
|
||||
IBM_TERSE : 18, // compressed using IBM TERSE
|
||||
IBM_LZ77 : 19, //IBM LZ77 z
|
||||
|
||||
/* General purpose bit flag */
|
||||
FLG_ENC : 0, // encripted file
|
||||
FLG_COMP1 : 1, // compression option
|
||||
FLG_COMP2 : 2, // compression option
|
||||
FLG_DESC : 4, // data descriptor
|
||||
FLG_ENH : 8, // enhanced deflation
|
||||
FLG_STR : 16, // strong encryption
|
||||
FLG_LNG : 1024, // language encoding
|
||||
FLG_MSK : 4096, // mask header values
|
||||
|
||||
/* Load type */
|
||||
FILE : 0,
|
||||
BUFFER : 1,
|
||||
NONE : 2,
|
||||
|
||||
/* 4.5 Extensible data fields */
|
||||
EF_ID : 0,
|
||||
EF_SIZE : 2,
|
||||
|
||||
/* Header IDs */
|
||||
ID_ZIP64 : 0x0001,
|
||||
ID_AVINFO : 0x0007,
|
||||
ID_PFS : 0x0008,
|
||||
ID_OS2 : 0x0009,
|
||||
ID_NTFS : 0x000a,
|
||||
ID_OPENVMS : 0x000c,
|
||||
ID_UNIX : 0x000d,
|
||||
ID_FORK : 0x000e,
|
||||
ID_PATCH : 0x000f,
|
||||
ID_X509_PKCS7 : 0x0014,
|
||||
ID_X509_CERTID_F : 0x0015,
|
||||
ID_X509_CERTID_C : 0x0016,
|
||||
ID_STRONGENC : 0x0017,
|
||||
ID_RECORD_MGT : 0x0018,
|
||||
ID_X509_PKCS7_RL : 0x0019,
|
||||
ID_IBM1 : 0x0065,
|
||||
ID_IBM2 : 0x0066,
|
||||
ID_POSZIP : 0x4690,
|
||||
|
||||
EF_ZIP64_OR_32 : 0xffffffff,
|
||||
EF_ZIP64_OR_16 : 0xffff,
|
||||
EF_ZIP64_SUNCOMP : 0,
|
||||
EF_ZIP64_SCOMP : 8,
|
||||
EF_ZIP64_RHO : 16,
|
||||
EF_ZIP64_DSN : 24
|
||||
};
|
||||
Generated
Vendored
-35
@@ -1,35 +0,0 @@
|
||||
module.exports = {
|
||||
/* Header error messages */
|
||||
"INVALID_LOC" : "Invalid LOC header (bad signature)",
|
||||
"INVALID_CEN" : "Invalid CEN header (bad signature)",
|
||||
"INVALID_END" : "Invalid END header (bad signature)",
|
||||
|
||||
/* ZipEntry error messages*/
|
||||
"NO_DATA" : "Nothing to decompress",
|
||||
"BAD_CRC" : "CRC32 checksum failed",
|
||||
"FILE_IN_THE_WAY" : "There is a file in the way: %s",
|
||||
"UNKNOWN_METHOD" : "Invalid/unsupported compression method",
|
||||
|
||||
/* Inflater error messages */
|
||||
"AVAIL_DATA" : "inflate::Available inflate data did not terminate",
|
||||
"INVALID_DISTANCE" : "inflate::Invalid literal/length or distance code in fixed or dynamic block",
|
||||
"TO_MANY_CODES" : "inflate::Dynamic block code description: too many length or distance codes",
|
||||
"INVALID_REPEAT_LEN" : "inflate::Dynamic block code description: repeat more than specified lengths",
|
||||
"INVALID_REPEAT_FIRST" : "inflate::Dynamic block code description: repeat lengths with no first length",
|
||||
"INCOMPLETE_CODES" : "inflate::Dynamic block code description: code lengths codes incomplete",
|
||||
"INVALID_DYN_DISTANCE": "inflate::Dynamic block code description: invalid distance code lengths",
|
||||
"INVALID_CODES_LEN": "inflate::Dynamic block code description: invalid literal/length code lengths",
|
||||
"INVALID_STORE_BLOCK" : "inflate::Stored block length did not match one's complement",
|
||||
"INVALID_BLOCK_TYPE" : "inflate::Invalid block type (type == 3)",
|
||||
|
||||
/* ADM-ZIP error messages */
|
||||
"CANT_EXTRACT_FILE" : "Could not extract the file",
|
||||
"CANT_OVERRIDE" : "Target file already exists",
|
||||
"NO_ZIP" : "No zip file was loaded",
|
||||
"NO_ENTRY" : "Entry doesn't exist",
|
||||
"DIRECTORY_CONTENT_ERROR" : "A directory cannot have content",
|
||||
"FILE_NOT_FOUND" : "File not found: %s",
|
||||
"NOT_IMPLEMENTED" : "Not implemented",
|
||||
"INVALID_FILENAME" : "Invalid filename",
|
||||
"INVALID_FORMAT" : "Invalid or unsupported zip format. No END header found"
|
||||
};
|
||||
Generated
Vendored
-84
@@ -1,84 +0,0 @@
|
||||
var fs = require("./fileSystem").require(),
|
||||
pth = require("path");
|
||||
|
||||
fs.existsSync = fs.existsSync || pth.existsSync;
|
||||
|
||||
module.exports = function(/*String*/path) {
|
||||
|
||||
var _path = path || "",
|
||||
_permissions = 0,
|
||||
_obj = newAttr(),
|
||||
_stat = null;
|
||||
|
||||
function newAttr() {
|
||||
return {
|
||||
directory : false,
|
||||
readonly : false,
|
||||
hidden : false,
|
||||
executable : false,
|
||||
mtime : 0,
|
||||
atime : 0
|
||||
}
|
||||
}
|
||||
|
||||
if (_path && fs.existsSync(_path)) {
|
||||
_stat = fs.statSync(_path);
|
||||
_obj.directory = _stat.isDirectory();
|
||||
_obj.mtime = _stat.mtime;
|
||||
_obj.atime = _stat.atime;
|
||||
_obj.executable = !!(1 & parseInt ((_stat.mode & parseInt ("777", 8)).toString (8)[0]));
|
||||
_obj.readonly = !!(2 & parseInt ((_stat.mode & parseInt ("777", 8)).toString (8)[0]));
|
||||
_obj.hidden = pth.basename(_path)[0] === ".";
|
||||
} else {
|
||||
console.warn("Invalid path: " + _path)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
get directory () {
|
||||
return _obj.directory;
|
||||
},
|
||||
|
||||
get readOnly () {
|
||||
return _obj.readonly;
|
||||
},
|
||||
|
||||
get hidden () {
|
||||
return _obj.hidden;
|
||||
},
|
||||
|
||||
get mtime () {
|
||||
return _obj.mtime;
|
||||
},
|
||||
|
||||
get atime () {
|
||||
return _obj.atime;
|
||||
},
|
||||
|
||||
|
||||
get executable () {
|
||||
return _obj.executable;
|
||||
},
|
||||
|
||||
decodeAttributes : function(val) {
|
||||
|
||||
},
|
||||
|
||||
encodeAttributes : function (val) {
|
||||
|
||||
},
|
||||
|
||||
toString : function() {
|
||||
return '{\n' +
|
||||
'\t"path" : "' + _path + ",\n" +
|
||||
'\t"isDirectory" : ' + _obj.directory + ",\n" +
|
||||
'\t"isReadOnly" : ' + _obj.readonly + ",\n" +
|
||||
'\t"isHidden" : ' + _obj.hidden + ",\n" +
|
||||
'\t"isExecutable" : ' + _obj.executable + ",\n" +
|
||||
'\t"mTime" : ' + _obj.mtime + "\n" +
|
||||
'\t"aTime" : ' + _obj.atime + "\n" +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
Generated
Vendored
-12
@@ -1,12 +0,0 @@
|
||||
exports.require = function() {
|
||||
var fs = require("fs");
|
||||
if (process.versions['electron']) {
|
||||
try {
|
||||
originalFs = require("original-fs");
|
||||
if (Object.keys(originalFs).length > 0) {
|
||||
fs = originalFs;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
return fs
|
||||
};
|
||||
Generated
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
module.exports = require("./utils");
|
||||
module.exports.FileSystem = require("./fileSystem");
|
||||
module.exports.Constants = require("./constants");
|
||||
module.exports.Errors = require("./errors");
|
||||
module.exports.FileAttr = require("./fattr");
|
||||
Generated
Vendored
-218
@@ -1,218 +0,0 @@
|
||||
var fs = require("./fileSystem").require(),
|
||||
pth = require('path');
|
||||
|
||||
fs.existsSync = fs.existsSync || pth.existsSync;
|
||||
|
||||
module.exports = (function() {
|
||||
|
||||
var crcTable = [],
|
||||
Constants = require('./constants'),
|
||||
Errors = require('./errors'),
|
||||
|
||||
PATH_SEPARATOR = pth.sep;
|
||||
|
||||
|
||||
function mkdirSync(/*String*/path) {
|
||||
var resolvedPath = path.split(PATH_SEPARATOR)[0];
|
||||
path.split(PATH_SEPARATOR).forEach(function(name) {
|
||||
if (!name || name.substr(-1,1) === ":") return;
|
||||
resolvedPath += PATH_SEPARATOR + name;
|
||||
var stat;
|
||||
try {
|
||||
stat = fs.statSync(resolvedPath);
|
||||
} catch (e) {
|
||||
fs.mkdirSync(resolvedPath);
|
||||
}
|
||||
if (stat && stat.isFile())
|
||||
throw Errors.FILE_IN_THE_WAY.replace("%s", resolvedPath);
|
||||
});
|
||||
}
|
||||
|
||||
function findSync(/*String*/dir, /*RegExp*/pattern, /*Boolean*/recoursive) {
|
||||
if (typeof pattern === 'boolean') {
|
||||
recoursive = pattern;
|
||||
pattern = undefined;
|
||||
}
|
||||
var files = [];
|
||||
fs.readdirSync(dir).forEach(function(file) {
|
||||
var path = pth.join(dir, file);
|
||||
|
||||
if (fs.statSync(path).isDirectory() && recoursive)
|
||||
files = files.concat(findSync(path, pattern, recoursive));
|
||||
|
||||
if (!pattern || pattern.test(path)) {
|
||||
files.push(pth.normalize(path) + (fs.statSync(path).isDirectory() ? PATH_SEPARATOR : ""));
|
||||
}
|
||||
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
function readBigUInt64LE(/*Buffer*/buffer, /*int*/index) {
|
||||
var slice = Buffer.from(buffer.slice(index, index + 8));
|
||||
slice.swap64();
|
||||
|
||||
return parseInt(`0x${ slice.toString('hex') }`);
|
||||
}
|
||||
|
||||
return {
|
||||
makeDir : function(/*String*/path) {
|
||||
mkdirSync(path);
|
||||
},
|
||||
|
||||
crc32 : function(buf) {
|
||||
if (typeof buf === 'string') {
|
||||
buf = Buffer.alloc(buf.length, buf);
|
||||
}
|
||||
var b = Buffer.alloc(4);
|
||||
if (!crcTable.length) {
|
||||
for (var n = 0; n < 256; n++) {
|
||||
var c = n;
|
||||
for (var k = 8; --k >= 0;) //
|
||||
if ((c & 1) !== 0) { c = 0xedb88320 ^ (c >>> 1); } else { c = c >>> 1; }
|
||||
if (c < 0) {
|
||||
b.writeInt32LE(c, 0);
|
||||
c = b.readUInt32LE(0);
|
||||
}
|
||||
crcTable[n] = c;
|
||||
}
|
||||
}
|
||||
var crc = 0, off = 0, len = buf.length, c1 = ~crc;
|
||||
while(--len >= 0) c1 = crcTable[(c1 ^ buf[off++]) & 0xff] ^ (c1 >>> 8);
|
||||
crc = ~c1;
|
||||
b.writeInt32LE(crc & 0xffffffff, 0);
|
||||
return b.readUInt32LE(0);
|
||||
},
|
||||
|
||||
methodToString : function(/*Number*/method) {
|
||||
switch (method) {
|
||||
case Constants.STORED:
|
||||
return 'STORED (' + method + ')';
|
||||
case Constants.DEFLATED:
|
||||
return 'DEFLATED (' + method + ')';
|
||||
default:
|
||||
return 'UNSUPPORTED (' + method + ')';
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
writeFileTo : function(/*String*/path, /*Buffer*/content, /*Boolean*/overwrite, /*Number*/attr) {
|
||||
if (fs.existsSync(path)) {
|
||||
if (!overwrite)
|
||||
return false; // cannot overwrite
|
||||
|
||||
var stat = fs.statSync(path);
|
||||
if (stat.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var folder = pth.dirname(path);
|
||||
if (!fs.existsSync(folder)) {
|
||||
mkdirSync(folder);
|
||||
}
|
||||
|
||||
var fd;
|
||||
try {
|
||||
fd = fs.openSync(path, 'w', 438); // 0666
|
||||
} catch(e) {
|
||||
fs.chmodSync(path, 438);
|
||||
fd = fs.openSync(path, 'w', 438);
|
||||
}
|
||||
if (fd) {
|
||||
try {
|
||||
fs.writeSync(fd, content, 0, content.length, 0);
|
||||
}
|
||||
catch (e){
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
fs.closeSync(fd);
|
||||
}
|
||||
}
|
||||
fs.chmodSync(path, attr || 438);
|
||||
return true;
|
||||
},
|
||||
|
||||
writeFileToAsync : function(/*String*/path, /*Buffer*/content, /*Boolean*/overwrite, /*Number*/attr, /*Function*/callback) {
|
||||
if(typeof attr === 'function') {
|
||||
callback = attr;
|
||||
attr = undefined;
|
||||
}
|
||||
|
||||
fs.exists(path, function(exists) {
|
||||
if(exists && !overwrite)
|
||||
return callback(false);
|
||||
|
||||
fs.stat(path, function(err, stat) {
|
||||
if(exists &&stat.isDirectory()) {
|
||||
return callback(false);
|
||||
}
|
||||
|
||||
var folder = pth.dirname(path);
|
||||
fs.exists(folder, function(exists) {
|
||||
if(!exists)
|
||||
mkdirSync(folder);
|
||||
|
||||
fs.open(path, 'w', 438, function(err, fd) {
|
||||
if(err) {
|
||||
fs.chmod(path, 438, function() {
|
||||
fs.open(path, 'w', 438, function(err, fd) {
|
||||
fs.write(fd, content, 0, content.length, 0, function() {
|
||||
fs.close(fd, function() {
|
||||
fs.chmod(path, attr || 438, function() {
|
||||
callback(true);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
} else {
|
||||
if(fd) {
|
||||
fs.write(fd, content, 0, content.length, 0, function() {
|
||||
fs.close(fd, function() {
|
||||
fs.chmod(path, attr || 438, function() {
|
||||
callback(true);
|
||||
})
|
||||
});
|
||||
});
|
||||
} else {
|
||||
fs.chmod(path, attr || 438, function() {
|
||||
callback(true);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
findFiles : function(/*String*/path) {
|
||||
return findSync(path, true);
|
||||
},
|
||||
|
||||
getAttributes : function(/*String*/path) {
|
||||
|
||||
},
|
||||
|
||||
setAttributes : function(/*String*/path) {
|
||||
|
||||
},
|
||||
|
||||
toBuffer : function(input) {
|
||||
if (Buffer.isBuffer(input)) {
|
||||
return input;
|
||||
} else {
|
||||
if (input.length === 0) {
|
||||
return Buffer.alloc(0)
|
||||
}
|
||||
return Buffer.from(input, 'utf8');
|
||||
}
|
||||
},
|
||||
|
||||
readBigUInt64LE,
|
||||
|
||||
Constants : Constants,
|
||||
Errors : Errors
|
||||
}
|
||||
})();
|
||||
Generated
Vendored
-291
@@ -1,291 +0,0 @@
|
||||
var Utils = require("./util"),
|
||||
Headers = require("./headers"),
|
||||
Constants = Utils.Constants,
|
||||
Methods = require("./methods");
|
||||
|
||||
module.exports = function (/*Buffer*/input) {
|
||||
|
||||
var _entryHeader = new Headers.EntryHeader(),
|
||||
_entryName = Buffer.alloc(0),
|
||||
_comment = Buffer.alloc(0),
|
||||
_isDirectory = false,
|
||||
uncompressedData = null,
|
||||
_extra = Buffer.alloc(0);
|
||||
|
||||
function getCompressedDataFromZip() {
|
||||
if (!input || !Buffer.isBuffer(input)) {
|
||||
return Buffer.alloc(0);
|
||||
}
|
||||
_entryHeader.loadDataHeaderFromBinary(input);
|
||||
return input.slice(_entryHeader.realDataOffset, _entryHeader.realDataOffset + _entryHeader.compressedSize)
|
||||
}
|
||||
|
||||
function crc32OK(data) {
|
||||
// if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written
|
||||
if ((_entryHeader.flags & 0x8) !== 0x8) {
|
||||
if (Utils.crc32(data) !== _entryHeader.dataHeader.crc) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// @TODO: load and check data descriptor header
|
||||
// The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure
|
||||
// (optionally preceded by a 4-byte signature) immediately after the compressed data:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function decompress(/*Boolean*/async, /*Function*/callback, /*String*/pass) {
|
||||
if(typeof callback === 'undefined' && typeof async === 'string') {
|
||||
pass=async;
|
||||
async=void 0;
|
||||
}
|
||||
if (_isDirectory) {
|
||||
if (async && callback) {
|
||||
callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR); //si added error.
|
||||
}
|
||||
return Buffer.alloc(0);
|
||||
}
|
||||
|
||||
var compressedData = getCompressedDataFromZip();
|
||||
|
||||
if (compressedData.length === 0) {
|
||||
// File is empty, nothing to decompress.
|
||||
if (async && callback) callback(compressedData);
|
||||
return compressedData;
|
||||
}
|
||||
|
||||
var data = Buffer.alloc(_entryHeader.size);
|
||||
|
||||
switch (_entryHeader.method) {
|
||||
case Utils.Constants.STORED:
|
||||
compressedData.copy(data);
|
||||
if (!crc32OK(data)) {
|
||||
if (async && callback) callback(data, Utils.Errors.BAD_CRC);//si added error
|
||||
throw new Error(Utils.Errors.BAD_CRC);
|
||||
} else {//si added otherwise did not seem to return data.
|
||||
if (async && callback) callback(data);
|
||||
return data;
|
||||
}
|
||||
case Utils.Constants.DEFLATED:
|
||||
var inflater = new Methods.Inflater(compressedData);
|
||||
if (!async) {
|
||||
var result = inflater.inflate(data);
|
||||
result.copy(data, 0);
|
||||
if (!crc32OK(data)) {
|
||||
throw new Error(Utils.Errors.BAD_CRC + " " + _entryName.toString());
|
||||
}
|
||||
return data;
|
||||
} else {
|
||||
inflater.inflateAsync(function(result) {
|
||||
result.copy(data, 0);
|
||||
if (!crc32OK(data)) {
|
||||
if (callback) callback(data, Utils.Errors.BAD_CRC); //si added error
|
||||
} else { //si added otherwise did not seem to return data.
|
||||
if (callback) callback(data);
|
||||
}
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD);
|
||||
throw new Error(Utils.Errors.UNKNOWN_METHOD);
|
||||
}
|
||||
}
|
||||
|
||||
function compress(/*Boolean*/async, /*Function*/callback) {
|
||||
if ((!uncompressedData || !uncompressedData.length) && Buffer.isBuffer(input)) {
|
||||
// no data set or the data wasn't changed to require recompression
|
||||
if (async && callback) callback(getCompressedDataFromZip());
|
||||
return getCompressedDataFromZip();
|
||||
}
|
||||
|
||||
if (uncompressedData.length && !_isDirectory) {
|
||||
var compressedData;
|
||||
// Local file header
|
||||
switch (_entryHeader.method) {
|
||||
case Utils.Constants.STORED:
|
||||
_entryHeader.compressedSize = _entryHeader.size;
|
||||
|
||||
compressedData = Buffer.alloc(uncompressedData.length);
|
||||
uncompressedData.copy(compressedData);
|
||||
|
||||
if (async && callback) callback(compressedData);
|
||||
return compressedData;
|
||||
default:
|
||||
case Utils.Constants.DEFLATED:
|
||||
|
||||
var deflater = new Methods.Deflater(uncompressedData);
|
||||
if (!async) {
|
||||
var deflated = deflater.deflate();
|
||||
_entryHeader.compressedSize = deflated.length;
|
||||
return deflated;
|
||||
} else {
|
||||
deflater.deflateAsync(function(data) {
|
||||
compressedData = Buffer.alloc(data.length);
|
||||
_entryHeader.compressedSize = data.length;
|
||||
data.copy(compressedData);
|
||||
callback && callback(compressedData);
|
||||
})
|
||||
}
|
||||
deflater = null;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (async && callback) {
|
||||
callback(Buffer.alloc(0));
|
||||
} else {
|
||||
return Buffer.alloc(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readUInt64LE(buffer, offset) {
|
||||
return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
|
||||
}
|
||||
|
||||
function parseExtra(data) {
|
||||
var offset = 0;
|
||||
var signature, size, part;
|
||||
while(offset<data.length) {
|
||||
signature = data.readUInt16LE(offset);
|
||||
offset += 2;
|
||||
size = data.readUInt16LE(offset);
|
||||
offset += 2;
|
||||
part = data.slice(offset, offset+size);
|
||||
offset += size;
|
||||
if(Constants.ID_ZIP64 === signature) {
|
||||
parseZip64ExtendedInformation(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Override header field values with values from the ZIP64 extra field
|
||||
function parseZip64ExtendedInformation(data) {
|
||||
var size, compressedSize, offset, diskNumStart;
|
||||
|
||||
if(data.length >= Constants.EF_ZIP64_SCOMP) {
|
||||
size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
|
||||
if(_entryHeader.size === Constants.EF_ZIP64_OR_32) {
|
||||
_entryHeader.size = size;
|
||||
}
|
||||
}
|
||||
if(data.length >= Constants.EF_ZIP64_RHO) {
|
||||
compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
|
||||
if(_entryHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
|
||||
_entryHeader.compressedSize = compressedSize;
|
||||
}
|
||||
}
|
||||
if(data.length >= Constants.EF_ZIP64_DSN) {
|
||||
offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
|
||||
if(_entryHeader.offset === Constants.EF_ZIP64_OR_32) {
|
||||
_entryHeader.offset = offset;
|
||||
}
|
||||
}
|
||||
if(data.length >= Constants.EF_ZIP64_DSN+4) {
|
||||
diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
|
||||
if(_entryHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
|
||||
_entryHeader.diskNumStart = diskNumStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
get entryName () { return _entryName.toString(); },
|
||||
get rawEntryName() { return _entryName; },
|
||||
set entryName (val) {
|
||||
_entryName = Utils.toBuffer(val);
|
||||
var lastChar = _entryName[_entryName.length - 1];
|
||||
_isDirectory = (lastChar === 47) || (lastChar === 92);
|
||||
_entryHeader.fileNameLength = _entryName.length;
|
||||
},
|
||||
|
||||
get extra () { return _extra; },
|
||||
set extra (val) {
|
||||
_extra = val;
|
||||
_entryHeader.extraLength = val.length;
|
||||
parseExtra(val);
|
||||
},
|
||||
|
||||
get comment () { return _comment.toString(); },
|
||||
set comment (val) {
|
||||
_comment = Utils.toBuffer(val);
|
||||
_entryHeader.commentLength = _comment.length;
|
||||
},
|
||||
|
||||
get name () { var n = _entryName.toString(); return _isDirectory ? n.substr(n.length - 1).split("/").pop() : n.split("/").pop(); },
|
||||
get isDirectory () { return _isDirectory },
|
||||
|
||||
getCompressedData : function() {
|
||||
return compress(false, null)
|
||||
},
|
||||
|
||||
getCompressedDataAsync : function(/*Function*/callback) {
|
||||
compress(true, callback)
|
||||
},
|
||||
|
||||
setData : function(value) {
|
||||
uncompressedData = Utils.toBuffer(value);
|
||||
if (!_isDirectory && uncompressedData.length) {
|
||||
_entryHeader.size = uncompressedData.length;
|
||||
_entryHeader.method = Utils.Constants.DEFLATED;
|
||||
_entryHeader.crc = Utils.crc32(value);
|
||||
_entryHeader.changed = true;
|
||||
} else { // folders and blank files should be stored
|
||||
_entryHeader.method = Utils.Constants.STORED;
|
||||
}
|
||||
},
|
||||
|
||||
getData : function(pass) {
|
||||
if (_entryHeader.changed) {
|
||||
return uncompressedData;
|
||||
} else {
|
||||
return decompress(false, null, pass);
|
||||
}
|
||||
},
|
||||
|
||||
getDataAsync : function(/*Function*/callback, pass) {
|
||||
if (_entryHeader.changed) {
|
||||
callback(uncompressedData)
|
||||
} else {
|
||||
decompress(true, callback, pass)
|
||||
}
|
||||
},
|
||||
|
||||
set attr(attr) { _entryHeader.attr = attr; },
|
||||
get attr() { return _entryHeader.attr; },
|
||||
|
||||
set header(/*Buffer*/data) {
|
||||
_entryHeader.loadFromBinary(data);
|
||||
},
|
||||
|
||||
get header() {
|
||||
return _entryHeader;
|
||||
},
|
||||
|
||||
packHeader : function() {
|
||||
var header = _entryHeader.entryHeaderToBinary();
|
||||
// add
|
||||
_entryName.copy(header, Utils.Constants.CENHDR);
|
||||
if (_entryHeader.extraLength) {
|
||||
_extra.copy(header, Utils.Constants.CENHDR + _entryName.length)
|
||||
}
|
||||
if (_entryHeader.commentLength) {
|
||||
_comment.copy(header, Utils.Constants.CENHDR + _entryName.length + _entryHeader.extraLength, _comment.length);
|
||||
}
|
||||
return header;
|
||||
},
|
||||
|
||||
toString : function() {
|
||||
return '{\n' +
|
||||
'\t"entryName" : "' + _entryName.toString() + "\",\n" +
|
||||
'\t"name" : "' + (_isDirectory ? _entryName.toString().replace(/\/$/, '').split("/").pop() : _entryName.toString().split("/").pop()) + "\",\n" +
|
||||
'\t"comment" : "' + _comment.toString() + "\",\n" +
|
||||
'\t"isDirectory" : ' + _isDirectory + ",\n" +
|
||||
'\t"header" : ' + _entryHeader.toString().replace(/\t/mg, "\t\t").replace(/}/mg, "\t}") + ",\n" +
|
||||
'\t"compressedData" : <' + (input && input.length + " bytes buffer" || "null") + ">\n" +
|
||||
'\t"data" : <' + (uncompressedData && uncompressedData.length + " bytes buffer" || "null") + ">\n" +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-408
@@ -1,408 +0,0 @@
|
||||
var ZipEntry = require("./zipEntry"),
|
||||
Headers = require("./headers"),
|
||||
Utils = require("./util");
|
||||
|
||||
module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
|
||||
var entryList = [],
|
||||
entryTable = {},
|
||||
_comment = Buffer.alloc(0),
|
||||
filename = "",
|
||||
fs = Utils.FileSystem.require(),
|
||||
inBuffer = null,
|
||||
mainHeader = new Headers.MainHeader(),
|
||||
loadedEntries = false;
|
||||
|
||||
if (inputType === Utils.Constants.FILE) {
|
||||
// is a filename
|
||||
filename = input;
|
||||
inBuffer = fs.readFileSync(filename);
|
||||
readMainHeader();
|
||||
} else if (inputType === Utils.Constants.BUFFER) {
|
||||
// is a memory buffer
|
||||
inBuffer = input;
|
||||
readMainHeader();
|
||||
} else {
|
||||
// none. is a new file
|
||||
loadedEntries = true;
|
||||
}
|
||||
|
||||
function iterateEntries(callback) {
|
||||
const totalEntries = mainHeader.diskEntries; // total number of entries
|
||||
let index = mainHeader.offset; // offset of first CEN header
|
||||
|
||||
for (let i = 0; i < totalEntries; i++) {
|
||||
let tmp = index;
|
||||
const entry = new ZipEntry(inBuffer);
|
||||
|
||||
entry.header = inBuffer.slice(tmp, tmp += Utils.Constants.CENHDR);
|
||||
entry.entryName = inBuffer.slice(tmp, tmp += entry.header.fileNameLength);
|
||||
|
||||
index += entry.header.entryHeaderSize;
|
||||
|
||||
callback(entry);
|
||||
}
|
||||
}
|
||||
|
||||
function readEntries() {
|
||||
loadedEntries = true;
|
||||
entryTable = {};
|
||||
entryList = new Array(mainHeader.diskEntries); // total number of entries
|
||||
var index = mainHeader.offset; // offset of first CEN header
|
||||
for (var i = 0; i < entryList.length; i++) {
|
||||
|
||||
var tmp = index,
|
||||
entry = new ZipEntry(inBuffer);
|
||||
entry.header = inBuffer.slice(tmp, tmp += Utils.Constants.CENHDR);
|
||||
|
||||
entry.entryName = inBuffer.slice(tmp, tmp += entry.header.fileNameLength);
|
||||
|
||||
if (entry.header.extraLength) {
|
||||
entry.extra = inBuffer.slice(tmp, tmp += entry.header.extraLength);
|
||||
}
|
||||
|
||||
if (entry.header.commentLength)
|
||||
entry.comment = inBuffer.slice(tmp, tmp + entry.header.commentLength);
|
||||
|
||||
index += entry.header.entryHeaderSize;
|
||||
|
||||
entryList[i] = entry;
|
||||
entryTable[entry.entryName] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
function readMainHeader() {
|
||||
var i = inBuffer.length - Utils.Constants.ENDHDR, // END header size
|
||||
max = Math.max(0, i - 0xFFFF), // 0xFFFF is the max zip file comment length
|
||||
n = max,
|
||||
endStart = inBuffer.length,
|
||||
endOffset = -1, // Start offset of the END header
|
||||
commentEnd = 0;
|
||||
|
||||
for (i; i >= n; i--) {
|
||||
if (inBuffer[i] !== 0x50) continue; // quick check that the byte is 'P'
|
||||
if (inBuffer.readUInt32LE(i) === Utils.Constants.ENDSIG) { // "PK\005\006"
|
||||
endOffset = i;
|
||||
commentEnd = i;
|
||||
endStart = i + Utils.Constants.ENDHDR;
|
||||
// We already found a regular signature, let's look just a bit further to check if there's any zip64 signature
|
||||
n = i - Utils.Constants.END64HDR;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inBuffer.readUInt32LE(i) === Utils.Constants.END64SIG) {
|
||||
// Found a zip64 signature, let's continue reading the whole zip64 record
|
||||
n = max;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inBuffer.readUInt32LE(i) == Utils.Constants.ZIP64SIG) {
|
||||
// Found the zip64 record, let's determine it's size
|
||||
endOffset = i;
|
||||
endStart = i + Utils.readBigUInt64LE(inBuffer, i + Utils.Constants.ZIP64SIZE) + Utils.Constants.ZIP64LEAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!~endOffset)
|
||||
throw new Error(Utils.Errors.INVALID_FORMAT);
|
||||
|
||||
mainHeader.loadFromBinary(inBuffer.slice(endOffset, endStart));
|
||||
if (mainHeader.commentLength) {
|
||||
_comment = inBuffer.slice(commentEnd + Utils.Constants.ENDHDR);
|
||||
}
|
||||
// readEntries();
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Returns an array of ZipEntry objects existent in the current opened archive
|
||||
* @return Array
|
||||
*/
|
||||
get entries() {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
return entryList;
|
||||
},
|
||||
|
||||
/**
|
||||
* Archive comment
|
||||
* @return {String}
|
||||
*/
|
||||
get comment() {
|
||||
return _comment.toString();
|
||||
},
|
||||
set comment(val) {
|
||||
mainHeader.commentLength = val.length;
|
||||
_comment = val;
|
||||
},
|
||||
|
||||
getEntryCount: function() {
|
||||
if (!loadedEntries) {
|
||||
return mainHeader.diskEntries;
|
||||
}
|
||||
|
||||
return entryList.length;
|
||||
},
|
||||
|
||||
forEach: function(callback) {
|
||||
if (!loadedEntries) {
|
||||
iterateEntries(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
entryList.forEach(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a reference to the entry with the given name or null if entry is inexistent
|
||||
*
|
||||
* @param entryName
|
||||
* @return ZipEntry
|
||||
*/
|
||||
getEntry: function (/*String*/entryName) {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
return entryTable[entryName] || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the given entry to the entry list
|
||||
*
|
||||
* @param entry
|
||||
*/
|
||||
setEntry: function (/*ZipEntry*/entry) {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
entryList.push(entry);
|
||||
entryTable[entry.entryName] = entry;
|
||||
mainHeader.totalEntries = entryList.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the entry with the given name from the entry list.
|
||||
*
|
||||
* If the entry is a directory, then all nested files and directories will be removed
|
||||
* @param entryName
|
||||
*/
|
||||
deleteEntry: function (/*String*/entryName) {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
var entry = entryTable[entryName];
|
||||
if (entry && entry.isDirectory) {
|
||||
var _self = this;
|
||||
this.getEntryChildren(entry).forEach(function (child) {
|
||||
if (child.entryName !== entryName) {
|
||||
_self.deleteEntry(child.entryName)
|
||||
}
|
||||
})
|
||||
}
|
||||
entryList.splice(entryList.indexOf(entry), 1);
|
||||
delete(entryTable[entryName]);
|
||||
mainHeader.totalEntries = entryList.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterates and returns all nested files and directories of the given entry
|
||||
*
|
||||
* @param entry
|
||||
* @return Array
|
||||
*/
|
||||
getEntryChildren: function (/*ZipEntry*/entry) {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
var list = [],
|
||||
name = entry.entryName,
|
||||
len = name.length;
|
||||
|
||||
entryList.forEach(function (zipEntry) {
|
||||
if (zipEntry.entryName.substr(0, len) === name) {
|
||||
list.push(zipEntry);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the zip file
|
||||
*
|
||||
* @return Buffer
|
||||
*/
|
||||
compressToBuffer: function () {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
if (entryList.length > 1) {
|
||||
entryList.sort(function (a, b) {
|
||||
var nameA = a.entryName.toLowerCase();
|
||||
var nameB = b.entryName.toLowerCase();
|
||||
if (nameA < nameB) {
|
||||
return -1
|
||||
}
|
||||
if (nameA > nameB) {
|
||||
return 1
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
var totalSize = 0,
|
||||
dataBlock = [],
|
||||
entryHeaders = [],
|
||||
dindex = 0;
|
||||
|
||||
mainHeader.size = 0;
|
||||
mainHeader.offset = 0;
|
||||
|
||||
entryList.forEach(function (entry) {
|
||||
// compress data and set local and entry header accordingly. Reason why is called first
|
||||
var compressedData = entry.getCompressedData();
|
||||
// data header
|
||||
entry.header.offset = dindex;
|
||||
var dataHeader = entry.header.dataHeaderToBinary();
|
||||
var entryNameLen = entry.rawEntryName.length;
|
||||
var extra = entry.extra.toString();
|
||||
var postHeader = Buffer.alloc(entryNameLen + extra.length);
|
||||
entry.rawEntryName.copy(postHeader, 0);
|
||||
postHeader.fill(extra, entryNameLen);
|
||||
|
||||
var dataLength = dataHeader.length + postHeader.length + compressedData.length;
|
||||
|
||||
dindex += dataLength;
|
||||
|
||||
dataBlock.push(dataHeader);
|
||||
dataBlock.push(postHeader);
|
||||
dataBlock.push(compressedData);
|
||||
|
||||
var entryHeader = entry.packHeader();
|
||||
entryHeaders.push(entryHeader);
|
||||
mainHeader.size += entryHeader.length;
|
||||
totalSize += (dataLength + entryHeader.length);
|
||||
});
|
||||
|
||||
totalSize += mainHeader.mainHeaderSize; // also includes zip file comment length
|
||||
// point to end of data and beginning of central directory first record
|
||||
mainHeader.offset = dindex;
|
||||
|
||||
dindex = 0;
|
||||
var outBuffer = Buffer.alloc(totalSize);
|
||||
dataBlock.forEach(function (content) {
|
||||
content.copy(outBuffer, dindex); // write data blocks
|
||||
dindex += content.length;
|
||||
});
|
||||
entryHeaders.forEach(function (content) {
|
||||
content.copy(outBuffer, dindex); // write central directory entries
|
||||
dindex += content.length;
|
||||
});
|
||||
|
||||
var mh = mainHeader.toBinary();
|
||||
if (_comment) {
|
||||
Buffer.from(_comment).copy(mh, Utils.Constants.ENDHDR); // add zip file comment
|
||||
}
|
||||
|
||||
mh.copy(outBuffer, dindex); // write main header
|
||||
|
||||
return outBuffer
|
||||
},
|
||||
|
||||
toAsyncBuffer: function (/*Function*/onSuccess, /*Function*/onFail, /*Function*/onItemStart, /*Function*/onItemEnd) {
|
||||
if (!loadedEntries) {
|
||||
readEntries();
|
||||
}
|
||||
if (entryList.length > 1) {
|
||||
entryList.sort(function (a, b) {
|
||||
var nameA = a.entryName.toLowerCase();
|
||||
var nameB = b.entryName.toLowerCase();
|
||||
if (nameA > nameB) {
|
||||
return -1
|
||||
}
|
||||
if (nameA < nameB) {
|
||||
return 1
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
var totalSize = 0,
|
||||
dataBlock = [],
|
||||
entryHeaders = [],
|
||||
dindex = 0;
|
||||
|
||||
mainHeader.size = 0;
|
||||
mainHeader.offset = 0;
|
||||
|
||||
var compress = function (entryList) {
|
||||
var self = arguments.callee;
|
||||
if (entryList.length) {
|
||||
var entry = entryList.pop();
|
||||
var name = entry.entryName + entry.extra.toString();
|
||||
if (onItemStart) onItemStart(name);
|
||||
entry.getCompressedDataAsync(function (compressedData) {
|
||||
if (onItemEnd) onItemEnd(name);
|
||||
|
||||
entry.header.offset = dindex;
|
||||
// data header
|
||||
var dataHeader = entry.header.dataHeaderToBinary();
|
||||
var postHeader;
|
||||
try {
|
||||
postHeader = Buffer.alloc(name.length, name); // using alloc will work on node 5.x+
|
||||
} catch(e){
|
||||
postHeader = new Buffer(name); // use deprecated method if alloc fails...
|
||||
}
|
||||
var dataLength = dataHeader.length + postHeader.length + compressedData.length;
|
||||
|
||||
dindex += dataLength;
|
||||
|
||||
dataBlock.push(dataHeader);
|
||||
dataBlock.push(postHeader);
|
||||
dataBlock.push(compressedData);
|
||||
|
||||
var entryHeader = entry.packHeader();
|
||||
entryHeaders.push(entryHeader);
|
||||
mainHeader.size += entryHeader.length;
|
||||
totalSize += (dataLength + entryHeader.length);
|
||||
|
||||
if (entryList.length) {
|
||||
self(entryList);
|
||||
} else {
|
||||
|
||||
|
||||
totalSize += mainHeader.mainHeaderSize; // also includes zip file comment length
|
||||
// point to end of data and beginning of central directory first record
|
||||
mainHeader.offset = dindex;
|
||||
|
||||
dindex = 0;
|
||||
var outBuffer = Buffer.alloc(totalSize);
|
||||
dataBlock.forEach(function (content) {
|
||||
content.copy(outBuffer, dindex); // write data blocks
|
||||
dindex += content.length;
|
||||
});
|
||||
entryHeaders.forEach(function (content) {
|
||||
content.copy(outBuffer, dindex); // write central directory entries
|
||||
dindex += content.length;
|
||||
});
|
||||
|
||||
var mh = mainHeader.toBinary();
|
||||
if (_comment) {
|
||||
_comment.copy(mh, Utils.Constants.ENDHDR); // add zip file comment
|
||||
}
|
||||
|
||||
mh.copy(outBuffer, dindex); // write main header
|
||||
|
||||
onSuccess(outBuffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
compress(entryList);
|
||||
}
|
||||
}
|
||||
};
|
||||
Generated
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
sudo: false
|
||||
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "4"
|
||||
- "5"
|
||||
- "6"
|
||||
- "7"
|
||||
- "8"
|
||||
- "9"
|
||||
- "10"
|
||||
|
||||
install:
|
||||
- PATH="`npm bin`:`npm bin -g`:$PATH"
|
||||
# Install dependencies and build
|
||||
- npm install
|
||||
|
||||
script:
|
||||
# Output useful info for debugging
|
||||
- node --version
|
||||
- npm --version
|
||||
# Run tests
|
||||
- npm test
|
||||
Generated
Vendored
-113
@@ -1,113 +0,0 @@
|
||||
|
||||
4.2.0 / 2018-01-15
|
||||
==================
|
||||
|
||||
* Add support for returning an `http.Agent` instance
|
||||
* Optimize promisifying logic
|
||||
* Set `timeout` to null for proper cleanup
|
||||
* Remove Node.js <= 0.11.3 special-casing from test case
|
||||
|
||||
4.1.2 / 2017-11-20
|
||||
==================
|
||||
|
||||
* test Node 9 on Travis
|
||||
* ensure that `https.get()` uses the patched `https.request()`
|
||||
|
||||
4.1.1 / 2017-07-20
|
||||
==================
|
||||
|
||||
* Correct `https.request()` with a String (#9)
|
||||
|
||||
4.1.0 / 2017-06-26
|
||||
==================
|
||||
|
||||
* mix in Agent options into Request options
|
||||
* throw when nothing is returned from agent-base callback
|
||||
* do not modify the options object for https requests
|
||||
|
||||
4.0.1 / 2017-06-13
|
||||
==================
|
||||
|
||||
* add `this` context tests and fixes
|
||||
|
||||
4.0.0 / 2017-06-06
|
||||
==================
|
||||
|
||||
* drop support for Node.js < 4
|
||||
* drop old versions of Node.js from Travis-CI
|
||||
* specify Node.js >= 4.0.0 in `engines.node`
|
||||
* remove more old code
|
||||
* remove "extend" dependency
|
||||
* remove "semver" dependency
|
||||
* make the Promise logic a bit cleaner
|
||||
* add async function pseudo-example to README
|
||||
* use direct return in README example
|
||||
|
||||
3.0.0 / 2017-06-02
|
||||
==================
|
||||
|
||||
* drop support for Node.js v0.8 and v0.10
|
||||
* add support for async, Promises, and direct return
|
||||
* add a couple `options` test cases
|
||||
* implement a `"timeout"` option
|
||||
* rename main file to `index.js`
|
||||
* test Node 8 on Travis
|
||||
|
||||
2.1.1 / 2017-05-30
|
||||
==================
|
||||
|
||||
* Revert [`fe2162e`](https://github.com/TooTallNate/node-agent-base/commit/fe2162e0ba18123f5b301cba4de1e9dd74e437cd) and [`270bdc9`](https://github.com/TooTallNate/node-agent-base/commit/270bdc92eb8e3bd0444d1e5266e8e9390aeb3095) (fixes #7)
|
||||
|
||||
2.1.0 / 2017-05-26
|
||||
==================
|
||||
|
||||
* unref is not supported for node < 0.9.1 (@pi0)
|
||||
* add tests to dangling socket (@pi0)
|
||||
* check unref() is supported (@pi0)
|
||||
* fix dangling sockets problem (@pi0)
|
||||
* add basic "ws" module tests
|
||||
* make `Agent` be subclassable
|
||||
* turn `addRequest()` into a named function
|
||||
* test: Node.js v4 likes to call `cork` on the stream (#3, @tomhughes)
|
||||
* travis: test node v4, v5, v6 and v7
|
||||
|
||||
2.0.1 / 2015-09-10
|
||||
==================
|
||||
|
||||
* package: update "semver" to v5.0.1 for WebPack (#1, @vhpoet)
|
||||
|
||||
2.0.0 / 2015-07-10
|
||||
==================
|
||||
|
||||
* refactor to patch Node.js core for more consistent `opts` values
|
||||
* ensure that HTTP(s) default port numbers are always given
|
||||
* test: use ssl-cert-snakeoil SSL certs
|
||||
* test: add tests for arbitrary options
|
||||
* README: add API section
|
||||
* README: make the Agent HTTP/HTTPS generic in the example
|
||||
* README: use SVG for Travis-CI badge
|
||||
|
||||
1.0.2 / 2015-06-27
|
||||
==================
|
||||
|
||||
* agent: set `req._hadError` to true after emitting "error"
|
||||
* package: update "mocha" to v2
|
||||
* test: add artificial HTTP GET request test
|
||||
* test: add artificial data events test
|
||||
* test: fix artifical GET response test on node > v0.11.3
|
||||
* test: use a real timeout for the async error test
|
||||
|
||||
1.0.1 / 2013-09-09
|
||||
==================
|
||||
|
||||
* Fix passing an "error" object to the callback function on the first tick
|
||||
|
||||
1.0.0 / 2013-09-09
|
||||
==================
|
||||
|
||||
* New API: now you pass a callback function directly
|
||||
|
||||
0.0.1 / 2013-07-09
|
||||
==================
|
||||
|
||||
* Initial release
|
||||
Generated
Vendored
-145
@@ -1,145 +0,0 @@
|
||||
agent-base
|
||||
==========
|
||||
### Turn a function into an [`http.Agent`][http.Agent] instance
|
||||
[](https://travis-ci.org/TooTallNate/node-agent-base)
|
||||
|
||||
This module provides an `http.Agent` generator. That is, you pass it an async
|
||||
callback function, and it returns a new `http.Agent` instance that will invoke the
|
||||
given callback function when sending outbound HTTP requests.
|
||||
|
||||
#### Some subclasses:
|
||||
|
||||
Here's some more interesting uses of `agent-base`.
|
||||
Send a pull request to list yours!
|
||||
|
||||
* [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints
|
||||
* [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints
|
||||
* [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS
|
||||
* [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS (v4a) proxy `http.Agent` implementation for HTTP and HTTPS
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install with `npm`:
|
||||
|
||||
``` bash
|
||||
$ npm install agent-base
|
||||
```
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Here's a minimal example that creates a new `net.Socket` connection to the server
|
||||
for every HTTP request (i.e. the equivalent of `agent: false` option):
|
||||
|
||||
```js
|
||||
var net = require('net');
|
||||
var tls = require('tls');
|
||||
var url = require('url');
|
||||
var http = require('http');
|
||||
var agent = require('agent-base');
|
||||
|
||||
var endpoint = 'http://nodejs.org/api/';
|
||||
var parsed = url.parse(endpoint);
|
||||
|
||||
// This is the important part!
|
||||
parsed.agent = agent(function (req, opts) {
|
||||
var socket;
|
||||
// `secureEndpoint` is true when using the https module
|
||||
if (opts.secureEndpoint) {
|
||||
socket = tls.connect(opts);
|
||||
} else {
|
||||
socket = net.connect(opts);
|
||||
}
|
||||
return socket;
|
||||
});
|
||||
|
||||
// Everything else works just like normal...
|
||||
http.get(parsed, function (res) {
|
||||
console.log('"response" event!', res.headers);
|
||||
res.pipe(process.stdout);
|
||||
});
|
||||
```
|
||||
|
||||
Returning a Promise or using an `async` function is also supported:
|
||||
|
||||
```js
|
||||
agent(async function (req, opts) {
|
||||
await sleep(1000);
|
||||
// etc…
|
||||
});
|
||||
```
|
||||
|
||||
Return another `http.Agent` instance to "pass through" the responsibility
|
||||
for that HTTP request to that agent:
|
||||
|
||||
```js
|
||||
agent(function (req, opts) {
|
||||
return opts.secureEndpoint ? https.globalAgent : http.globalAgent;
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
## Agent(Function callback[, Object options]) → [http.Agent][]
|
||||
|
||||
Creates a base `http.Agent` that will execute the callback function `callback`
|
||||
for every HTTP request that it is used as the `agent` for. The callback function
|
||||
is responsible for creating a `stream.Duplex` instance of some kind that will be
|
||||
used as the underlying socket in the HTTP request.
|
||||
|
||||
The `options` object accepts the following properties:
|
||||
|
||||
* `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional).
|
||||
|
||||
The callback function should have the following signature:
|
||||
|
||||
### callback(http.ClientRequest req, Object options, Function cb) → undefined
|
||||
|
||||
The ClientRequest `req` can be accessed to read request headers and
|
||||
and the path, etc. The `options` object contains the options passed
|
||||
to the `http.request()`/`https.request()` function call, and is formatted
|
||||
to be directly passed to `net.connect()`/`tls.connect()`, or however
|
||||
else you want a Socket to be created. Pass the created socket to
|
||||
the callback function `cb` once created, and the HTTP request will
|
||||
continue to proceed.
|
||||
|
||||
If the `https` module is used to invoke the HTTP request, then the
|
||||
`secureEndpoint` property on `options` _will be set to `true`_.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
|
||||
|
||||
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.
|
||||
|
||||
[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent
|
||||
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
|
||||
[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent
|
||||
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
|
||||
[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent
|
||||
Generated
Vendored
-43
@@ -1,43 +0,0 @@
|
||||
// Type definitions for agent-base 4.2.1
|
||||
// Project: https://github.com/TooTallNate/node-agent-base
|
||||
// Definitions by: Christopher Quadflieg <https://github.com/Shinigami92>
|
||||
|
||||
/// <reference types="node" />
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
declare namespace Agent {
|
||||
export type AgentCallback = (
|
||||
req?: any,
|
||||
opts?: {
|
||||
secureEndpoint: boolean;
|
||||
}
|
||||
) => void;
|
||||
|
||||
export interface AgentOptions {
|
||||
timeout?: number;
|
||||
host?: string;
|
||||
port?: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface Agent extends EventEmitter {
|
||||
_promisifiedCallback: boolean;
|
||||
timeout: number | null;
|
||||
options?: AgentOptions;
|
||||
callback: AgentCallback;
|
||||
addRequest: (req?: any, opts?: any) => void;
|
||||
freeSocket: (socket: any, opts: any) => void;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base `http.Agent` implementation.
|
||||
* No pooling/keep-alive is implemented by default.
|
||||
*/
|
||||
declare function Agent(opts?: Agent.AgentOptions): Agent.Agent;
|
||||
declare function Agent(
|
||||
callback: Agent.AgentCallback,
|
||||
opts?: Agent.AgentOptions
|
||||
): Agent.Agent;
|
||||
|
||||
export = Agent;
|
||||
Generated
Vendored
-170
@@ -1,170 +0,0 @@
|
||||
'use strict';
|
||||
require('./patch-core');
|
||||
const inherits = require('util').inherits;
|
||||
const promisify = require('es6-promisify');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
module.exports = Agent;
|
||||
|
||||
function isAgent(v) {
|
||||
return v && typeof v.addRequest === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Base `http.Agent` implementation.
|
||||
* No pooling/keep-alive is implemented by default.
|
||||
*
|
||||
* @param {Function} callback
|
||||
* @api public
|
||||
*/
|
||||
function Agent(callback, _opts) {
|
||||
if (!(this instanceof Agent)) {
|
||||
return new Agent(callback, _opts);
|
||||
}
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
// The callback gets promisified if it has 3 parameters
|
||||
// (i.e. it has a callback function) lazily
|
||||
this._promisifiedCallback = false;
|
||||
|
||||
let opts = _opts;
|
||||
if ('function' === typeof callback) {
|
||||
this.callback = callback;
|
||||
} else if (callback) {
|
||||
opts = callback;
|
||||
}
|
||||
|
||||
// timeout for the socket to be returned from the callback
|
||||
this.timeout = (opts && opts.timeout) || null;
|
||||
|
||||
this.options = opts;
|
||||
}
|
||||
inherits(Agent, EventEmitter);
|
||||
|
||||
/**
|
||||
* Override this function in your subclass!
|
||||
*/
|
||||
Agent.prototype.callback = function callback(req, opts) {
|
||||
throw new Error(
|
||||
'"agent-base" has no default implementation, you must subclass and override `callback()`'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by node-core's "_http_client.js" module when creating
|
||||
* a new HTTP request with this Agent instance.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
Agent.prototype.addRequest = function addRequest(req, _opts) {
|
||||
const ownOpts = Object.assign({}, _opts);
|
||||
|
||||
// Set default `host` for HTTP to localhost
|
||||
if (null == ownOpts.host) {
|
||||
ownOpts.host = 'localhost';
|
||||
}
|
||||
|
||||
// Set default `port` for HTTP if none was explicitly specified
|
||||
if (null == ownOpts.port) {
|
||||
ownOpts.port = ownOpts.secureEndpoint ? 443 : 80;
|
||||
}
|
||||
|
||||
const opts = Object.assign({}, this.options, ownOpts);
|
||||
|
||||
if (opts.host && opts.path) {
|
||||
// If both a `host` and `path` are specified then it's most likely the
|
||||
// result of a `url.parse()` call... we need to remove the `path` portion so
|
||||
// that `net.connect()` doesn't attempt to open that as a unix socket file.
|
||||
delete opts.path;
|
||||
}
|
||||
|
||||
delete opts.agent;
|
||||
delete opts.hostname;
|
||||
delete opts._defaultAgent;
|
||||
delete opts.defaultPort;
|
||||
delete opts.createConnection;
|
||||
|
||||
// Hint to use "Connection: close"
|
||||
// XXX: non-documented `http` module API :(
|
||||
req._last = true;
|
||||
req.shouldKeepAlive = false;
|
||||
|
||||
// Create the `stream.Duplex` instance
|
||||
let timeout;
|
||||
let timedOut = false;
|
||||
const timeoutMs = this.timeout;
|
||||
const freeSocket = this.freeSocket;
|
||||
|
||||
function onerror(err) {
|
||||
if (req._hadError) return;
|
||||
req.emit('error', err);
|
||||
// For Safety. Some additional errors might fire later on
|
||||
// and we need to make sure we don't double-fire the error event.
|
||||
req._hadError = true;
|
||||
}
|
||||
|
||||
function ontimeout() {
|
||||
timeout = null;
|
||||
timedOut = true;
|
||||
const err = new Error(
|
||||
'A "socket" was not created for HTTP request before ' + timeoutMs + 'ms'
|
||||
);
|
||||
err.code = 'ETIMEOUT';
|
||||
onerror(err);
|
||||
}
|
||||
|
||||
function callbackError(err) {
|
||||
if (timedOut) return;
|
||||
if (timeout != null) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
onerror(err);
|
||||
}
|
||||
|
||||
function onsocket(socket) {
|
||||
if (timedOut) return;
|
||||
if (timeout != null) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
if (isAgent(socket)) {
|
||||
// `socket` is actually an http.Agent instance, so relinquish
|
||||
// responsibility for this `req` to the Agent from here on
|
||||
socket.addRequest(req, opts);
|
||||
} else if (socket) {
|
||||
function onfree() {
|
||||
freeSocket(socket, opts);
|
||||
}
|
||||
socket.on('free', onfree);
|
||||
req.onSocket(socket);
|
||||
} else {
|
||||
const err = new Error(
|
||||
'no Duplex stream was returned to agent-base for `' + req.method + ' ' + req.path + '`'
|
||||
);
|
||||
onerror(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._promisifiedCallback && this.callback.length >= 3) {
|
||||
// Legacy callback function - convert to a Promise
|
||||
this.callback = promisify(this.callback, this);
|
||||
this._promisifiedCallback = true;
|
||||
}
|
||||
|
||||
if (timeoutMs > 0) {
|
||||
timeout = setTimeout(ontimeout, timeoutMs);
|
||||
}
|
||||
|
||||
try {
|
||||
Promise.resolve(this.callback(req, opts)).then(onsocket, callbackError);
|
||||
} catch (err) {
|
||||
Promise.reject(err).catch(callbackError);
|
||||
}
|
||||
};
|
||||
|
||||
Agent.prototype.freeSocket = function freeSocket(socket, opts) {
|
||||
// TODO reuse sockets
|
||||
socket.destroy();
|
||||
};
|
||||
Generated
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "agent-base",
|
||||
"version": "4.3.0",
|
||||
"description": "Turn a function into an `http.Agent` instance",
|
||||
"main": "./index.js",
|
||||
"scripts": {
|
||||
"test": "mocha --reporter spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/TooTallNate/node-agent-base.git"
|
||||
},
|
||||
"keywords": [
|
||||
"http",
|
||||
"agent",
|
||||
"base",
|
||||
"barebones",
|
||||
"https"
|
||||
],
|
||||
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/TooTallNate/node-agent-base/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/es6-promisify": "^5.0.0",
|
||||
"@types/node": "^10.5.3",
|
||||
"mocha": "^3.4.2",
|
||||
"ws": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promisify": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz"
|
||||
,"_integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg=="
|
||||
,"_from": "agent-base@4.3.0"
|
||||
}
|
||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
const url = require('url');
|
||||
const https = require('https');
|
||||
|
||||
/**
|
||||
* This currently needs to be applied to all Node.js versions
|
||||
* in order to determine if the `req` is an HTTP or HTTPS request.
|
||||
*
|
||||
* There is currently no PR attempting to move this property upstream.
|
||||
*/
|
||||
const patchMarker = "__agent_base_https_request_patched__";
|
||||
if (!https.request[patchMarker]) {
|
||||
https.request = (function(request) {
|
||||
return function(_options, cb) {
|
||||
let options;
|
||||
if (typeof _options === 'string') {
|
||||
options = url.parse(_options);
|
||||
} else {
|
||||
options = Object.assign({}, _options);
|
||||
}
|
||||
if (null == options.port) {
|
||||
options.port = 443;
|
||||
}
|
||||
options.secureEndpoint = true;
|
||||
return request.call(https, options, cb);
|
||||
};
|
||||
})(https.request);
|
||||
https.request[patchMarker] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed for Node.js >= 9.0.0 to make sure `https.get()` uses the
|
||||
* patched `https.request()`.
|
||||
*
|
||||
* Ref: https://github.com/nodejs/node/commit/5118f31
|
||||
*/
|
||||
https.get = function (_url, _options, cb) {
|
||||
let options;
|
||||
if (typeof _url === 'string' && _options && typeof _options !== 'function') {
|
||||
options = Object.assign({}, url.parse(_url), _options);
|
||||
} else if (!_options && !cb) {
|
||||
options = _url;
|
||||
} else if (!cb) {
|
||||
options = _url;
|
||||
cb = _options;
|
||||
}
|
||||
|
||||
const req = https.request(options, cb);
|
||||
req.end();
|
||||
return req;
|
||||
};
|
||||
Generated
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWwIBAAKBgQCzURxIqzer0ACAbX/lHdsn4Gd9PLKrf7EeDYfIdV0HZKPD8WDr
|
||||
bBx2/fBu0OW2sjnzv/SVZbJ0DAuPE/p0+eT0qb2qC10iz9iTD7ribd7gxhirVb8y
|
||||
b3fBjXsxc8V8p4Ny1LcvNSqCjwUbJqdRogfoJeTiqPM58z5sNzuv5iq7iwIDAQAB
|
||||
AoGAPMQy4olrP0UotlzlJ36bowLP70ffgHCwU+/f4NWs5fF78c3du0oSx1w820Dd
|
||||
Z7E0JF8bgnlJJTxjumPZz0RUCugrEHBKJmzEz3cxF5E3+7NvteZcjKn9D67RrM5x
|
||||
1/uSZ9cqKE9cYvY4fSuHx18diyZ4axR/wB1Pea2utjjDM+ECQQDb9ZbmmaWMiRpQ
|
||||
5Up+loxP7BZNPsEVsm+DVJmEFbaFgGfncWBqSIqnPNjMwTwj0OigTwCAEGPkfRVW
|
||||
T0pbYWCxAkEA0LK7SCTwzyDmhASUalk0x+3uCAA6ryFdwJf/wd8TRAvVOmkTEldX
|
||||
uJ7ldLvfrONYO3v56uKTU/SoNdZYzKtO+wJAX2KM4ctXYy5BXztPpr2acz4qHa1N
|
||||
Bh+vBAC34fOYhyQ76r3b1btHhWZ5jbFuZwm9F2erC94Ps5IaoqcX07DSwQJAPKGw
|
||||
h2U0EPkd/3zVIZCJJQya+vgWFIs9EZcXVtvYXQyTBkVApTN66MhBIYjzkub5205J
|
||||
bVQmOV37AKklY1DhwQJAA1wos0cYxro02edzatxd0DIR2r4qqOqLkw6BhYHhq6HJ
|
||||
ZvIcQkHqdSXzdETFc01I1znDGGIrJHcnvKWgBPoEUg==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
Generated
Vendored
-12
@@ -1,12 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1TCCAT4CCQDV5mPlzm9+izANBgkqhkiG9w0BAQUFADAvMS0wKwYDVQQDEyQ3
|
||||
NTI3YmQ3Ny1hYjNlLTQ3NGItYWNlNy1lZWQ2MDUzOTMxZTcwHhcNMTUwNzA2MjI0
|
||||
NTA3WhcNMjUwNzAzMjI0NTA3WjAvMS0wKwYDVQQDEyQ3NTI3YmQ3Ny1hYjNlLTQ3
|
||||
NGItYWNlNy1lZWQ2MDUzOTMxZTcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
|
||||
ALNRHEirN6vQAIBtf+Ud2yfgZ308sqt/sR4Nh8h1XQdko8PxYOtsHHb98G7Q5bay
|
||||
OfO/9JVlsnQMC48T+nT55PSpvaoLXSLP2JMPuuJt3uDGGKtVvzJvd8GNezFzxXyn
|
||||
g3LUty81KoKPBRsmp1GiB+gl5OKo8znzPmw3O6/mKruLAgMBAAEwDQYJKoZIhvcN
|
||||
AQEFBQADgYEACzoHUF8UV2Z6541Q2wKEA0UFUzmUjf/E1XwBO+1P15ZZ64uw34B4
|
||||
1RwMPtAo9RY/PmICTWtNxWGxkzwb2JtDWtnxVER/lF8k2XcXPE76fxTHJF/BKk9J
|
||||
QU8OTD1dd9gHCBviQB9TqntRZ5X7axjtuWjb2umY+owBYzAHZkp1HKI=
|
||||
-----END CERTIFICATE-----
|
||||
Generated
Vendored
-728
@@ -1,728 +0,0 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var fs = require('fs');
|
||||
var url = require('url');
|
||||
var net = require('net');
|
||||
var tls = require('tls');
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
var WebSocket = require('ws');
|
||||
var assert = require('assert');
|
||||
var events = require('events');
|
||||
var inherits = require('util').inherits;
|
||||
var Agent = require('../');
|
||||
|
||||
var PassthroughAgent = Agent(function(req, opts) {
|
||||
return opts.secureEndpoint ? https.globalAgent : http.globalAgent;
|
||||
});
|
||||
|
||||
describe('Agent', function() {
|
||||
describe('subclass', function() {
|
||||
it('should be subclassable', function(done) {
|
||||
function MyAgent() {
|
||||
Agent.call(this);
|
||||
}
|
||||
inherits(MyAgent, Agent);
|
||||
|
||||
MyAgent.prototype.callback = function(req, opts, fn) {
|
||||
assert.equal(req.path, '/foo');
|
||||
assert.equal(req.getHeader('host'), '127.0.0.1:1234');
|
||||
assert.equal(opts.secureEndpoint, true);
|
||||
done();
|
||||
};
|
||||
|
||||
var info = url.parse('https://127.0.0.1:1234/foo');
|
||||
info.agent = new MyAgent();
|
||||
https.get(info);
|
||||
});
|
||||
});
|
||||
describe('options', function() {
|
||||
it('should support an options Object as first argument', function() {
|
||||
var agent = new Agent({ timeout: 1000 });
|
||||
assert.equal(1000, agent.timeout);
|
||||
});
|
||||
it('should support an options Object as second argument', function() {
|
||||
var agent = new Agent(function() {}, { timeout: 1000 });
|
||||
assert.equal(1000, agent.timeout);
|
||||
});
|
||||
it('should be mixed in with HTTP request options', function(done) {
|
||||
var agent = new Agent({
|
||||
host: 'my-proxy.com',
|
||||
port: 3128,
|
||||
foo: 'bar'
|
||||
});
|
||||
agent.callback = function(req, opts, fn) {
|
||||
assert.equal('bar', opts.foo);
|
||||
assert.equal('a', opts.b);
|
||||
|
||||
// `host` and `port` are special-cases, and should always be
|
||||
// overwritten in the request `opts` inside the agent-base callback
|
||||
assert.equal('localhost', opts.host);
|
||||
assert.equal(80, opts.port);
|
||||
done();
|
||||
};
|
||||
var opts = {
|
||||
b: 'a',
|
||||
agent: agent
|
||||
};
|
||||
http.get(opts);
|
||||
});
|
||||
});
|
||||
describe('`this` context', function() {
|
||||
it('should be the Agent instance', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent();
|
||||
agent.callback = function() {
|
||||
called = true;
|
||||
assert.equal(this, agent);
|
||||
};
|
||||
var info = url.parse('http://127.0.0.1/foo');
|
||||
info.agent = agent;
|
||||
var req = http.get(info);
|
||||
req.on('error', function(err) {
|
||||
assert(/no Duplex stream was returned/.test(err.message));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be the Agent instance with callback signature', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent();
|
||||
agent.callback = function(req, opts, fn) {
|
||||
called = true;
|
||||
assert.equal(this, agent);
|
||||
fn();
|
||||
};
|
||||
var info = url.parse('http://127.0.0.1/foo');
|
||||
info.agent = agent;
|
||||
var req = http.get(info);
|
||||
req.on('error', function(err) {
|
||||
assert(/no Duplex stream was returned/.test(err.message));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('"error" event', function() {
|
||||
it('should be invoked on `http.ClientRequest` instance if `callback()` has not been defined', function(
|
||||
done
|
||||
) {
|
||||
var agent = new Agent();
|
||||
var info = url.parse('http://127.0.0.1/foo');
|
||||
info.agent = agent;
|
||||
var req = http.get(info);
|
||||
req.on('error', function(err) {
|
||||
assert.equal(
|
||||
'"agent-base" has no default implementation, you must subclass and override `callback()`',
|
||||
err.message
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be invoked on `http.ClientRequest` instance if Error passed to callback function on the first tick', function(
|
||||
done
|
||||
) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
fn(new Error('is this caught?'));
|
||||
});
|
||||
var info = url.parse('http://127.0.0.1/foo');
|
||||
info.agent = agent;
|
||||
var req = http.get(info);
|
||||
req.on('error', function(err) {
|
||||
assert.equal('is this caught?', err.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be invoked on `http.ClientRequest` instance if Error passed to callback function after the first tick', function(
|
||||
done
|
||||
) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
setTimeout(function() {
|
||||
fn(new Error('is this caught?'));
|
||||
}, 10);
|
||||
});
|
||||
var info = url.parse('http://127.0.0.1/foo');
|
||||
info.agent = agent;
|
||||
var req = http.get(info);
|
||||
req.on('error', function(err) {
|
||||
assert.equal('is this caught?', err.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('artificial "streams"', function() {
|
||||
it('should send a GET request', function(done) {
|
||||
var stream = new events.EventEmitter();
|
||||
|
||||
// needed for the `http` module to call .write() on the stream
|
||||
stream.writable = true;
|
||||
|
||||
stream.write = function(str) {
|
||||
assert(0 == str.indexOf('GET / HTTP/1.1'));
|
||||
done();
|
||||
};
|
||||
|
||||
// needed for `http` module in Node.js 4
|
||||
stream.cork = function() {};
|
||||
|
||||
var opts = {
|
||||
method: 'GET',
|
||||
host: '127.0.0.1',
|
||||
path: '/',
|
||||
port: 80,
|
||||
agent: new Agent(function(req, opts, fn) {
|
||||
fn(null, stream);
|
||||
})
|
||||
};
|
||||
var req = http.request(opts);
|
||||
req.end();
|
||||
});
|
||||
it('should receive a GET response', function(done) {
|
||||
var stream = new events.EventEmitter();
|
||||
var opts = {
|
||||
method: 'GET',
|
||||
host: '127.0.0.1',
|
||||
path: '/',
|
||||
port: 80,
|
||||
agent: new Agent(function(req, opts, fn) {
|
||||
fn(null, stream);
|
||||
})
|
||||
};
|
||||
var req = http.request(opts, function(res) {
|
||||
assert.equal('1.0', res.httpVersion);
|
||||
assert.equal(200, res.statusCode);
|
||||
assert.equal('bar', res.headers.foo);
|
||||
assert.deepEqual(['1', '2'], res.headers['set-cookie']);
|
||||
done();
|
||||
});
|
||||
|
||||
// have to wait for the "socket" event since `http.ClientRequest`
|
||||
// doesn't *actually* attach the listeners to the "stream" until
|
||||
// this happens
|
||||
req.once('socket', function() {
|
||||
var buf = Buffer.from(
|
||||
'HTTP/1.0 200\r\n' +
|
||||
'Foo: bar\r\n' +
|
||||
'Set-Cookie: 1\r\n' +
|
||||
'Set-Cookie: 2\r\n\r\n'
|
||||
);
|
||||
stream.emit('data', buf);
|
||||
});
|
||||
|
||||
req.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"http" module', function() {
|
||||
var server;
|
||||
var port;
|
||||
|
||||
// setup test HTTP server
|
||||
before(function(done) {
|
||||
server = http.createServer();
|
||||
server.listen(0, function() {
|
||||
port = server.address().port;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// shut down test HTTP server
|
||||
after(function(done) {
|
||||
server.once('close', function() {
|
||||
done();
|
||||
});
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('should work for basic HTTP requests', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
called = true;
|
||||
var socket = net.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/foo');
|
||||
info.agent = agent;
|
||||
http.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should support direct return in `connect()`', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts) {
|
||||
called = true;
|
||||
return net.connect(opts);
|
||||
});
|
||||
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/foo');
|
||||
info.agent = agent;
|
||||
http.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should support returning a Promise in `connect()`', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
called = true;
|
||||
resolve(net.connect(opts));
|
||||
});
|
||||
});
|
||||
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/foo');
|
||||
info.agent = agent;
|
||||
http.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set the `Connection: close` response header', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
called = true;
|
||||
var socket = net.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Url', req.url);
|
||||
assert.equal('close', req.headers.connection);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/bar');
|
||||
info.agent = agent;
|
||||
http.get(info, function(res) {
|
||||
assert.equal('/bar', res.headers['x-url']);
|
||||
assert.equal('close', res.headers.connection);
|
||||
assert(gotReq);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass through options from `http.request()`', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
assert.equal('google.com', opts.host);
|
||||
assert.equal('bar', opts.foo);
|
||||
done();
|
||||
});
|
||||
|
||||
http.get({
|
||||
host: 'google.com',
|
||||
foo: 'bar',
|
||||
agent: agent
|
||||
});
|
||||
});
|
||||
|
||||
it('should default to port 80', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
assert.equal(80, opts.port);
|
||||
done();
|
||||
});
|
||||
|
||||
// (probably) not hitting a real HTTP server here,
|
||||
// so no need to add a httpServer request listener
|
||||
http.get({
|
||||
host: '127.0.0.1',
|
||||
path: '/foo',
|
||||
agent: agent
|
||||
});
|
||||
});
|
||||
|
||||
it('should support the "timeout" option', function(done) {
|
||||
// ensure we timeout after the "error" event had a chance to trigger
|
||||
this.timeout(1000);
|
||||
this.slow(800);
|
||||
|
||||
var agent = new Agent(
|
||||
function(req, opts, fn) {
|
||||
// this function will time out
|
||||
},
|
||||
{ timeout: 100 }
|
||||
);
|
||||
|
||||
var opts = url.parse('http://nodejs.org');
|
||||
opts.agent = agent;
|
||||
|
||||
var req = http.get(opts);
|
||||
req.once('error', function(err) {
|
||||
assert.equal('ETIMEOUT', err.code);
|
||||
req.abort();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should free sockets after use', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
var socket = net.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/foo');
|
||||
info.agent = agent;
|
||||
http.get(info, function(res) {
|
||||
res.socket.emit('free');
|
||||
assert.equal(true, res.socket.destroyed);
|
||||
assert(gotReq);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('PassthroughAgent', function() {
|
||||
it('should pass through to `http.globalAgent`', function(done) {
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('http://127.0.0.1:' + port + '/foo');
|
||||
info.agent = PassthroughAgent;
|
||||
http.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"https" module', function() {
|
||||
var server;
|
||||
var port;
|
||||
|
||||
// setup test HTTPS server
|
||||
before(function(done) {
|
||||
var options = {
|
||||
key: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.key'),
|
||||
cert: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.pem')
|
||||
};
|
||||
server = https.createServer(options);
|
||||
server.listen(0, function() {
|
||||
port = server.address().port;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// shut down test HTTP server
|
||||
after(function(done) {
|
||||
server.once('close', function() {
|
||||
done();
|
||||
});
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('should not modify the passed in Options object', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
called = true;
|
||||
assert.equal(true, opts.secureEndpoint);
|
||||
assert.equal(443, opts.port);
|
||||
assert.equal('localhost', opts.host);
|
||||
});
|
||||
var opts = { agent: agent };
|
||||
var req = https.request(opts);
|
||||
assert.equal(true, called);
|
||||
assert.equal(false, 'secureEndpoint' in opts);
|
||||
assert.equal(false, 'port' in opts);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should work with a String URL', function(done) {
|
||||
var endpoint = 'https://127.0.0.1:' + port;
|
||||
var req = https.get(endpoint);
|
||||
|
||||
// it's gonna error out since `rejectUnauthorized` is not being passed in
|
||||
req.on('error', function(err) {
|
||||
assert.equal(err.code, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should work for basic HTTPS requests', function(done) {
|
||||
var called = false;
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
called = true;
|
||||
assert(opts.secureEndpoint);
|
||||
var socket = tls.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
// add HTTPS server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('https://127.0.0.1:' + port + '/foo');
|
||||
info.agent = agent;
|
||||
info.rejectUnauthorized = false;
|
||||
https.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass through options from `https.request()`', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
assert.equal('google.com', opts.host);
|
||||
assert.equal('bar', opts.foo);
|
||||
done();
|
||||
});
|
||||
|
||||
https.get({
|
||||
host: 'google.com',
|
||||
foo: 'bar',
|
||||
agent: agent
|
||||
});
|
||||
});
|
||||
|
||||
it('should support the 3-argument `https.get()`', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
assert.equal('google.com', opts.host);
|
||||
assert.equal('/q', opts.pathname || opts.path);
|
||||
assert.equal('881', opts.port);
|
||||
assert.equal('bar', opts.foo);
|
||||
done();
|
||||
});
|
||||
|
||||
https.get(
|
||||
'https://google.com:881/q',
|
||||
{
|
||||
host: 'google.com',
|
||||
foo: 'bar',
|
||||
agent: agent
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should default to port 443', function(done) {
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
assert.equal(true, opts.secureEndpoint);
|
||||
assert.equal(false, opts.rejectUnauthorized);
|
||||
assert.equal(443, opts.port);
|
||||
done();
|
||||
});
|
||||
|
||||
// (probably) not hitting a real HTTPS server here,
|
||||
// so no need to add a httpsServer request listener
|
||||
https.get({
|
||||
host: '127.0.0.1',
|
||||
path: '/foo',
|
||||
agent: agent,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
});
|
||||
|
||||
it('should not re-patch https.request', () => {
|
||||
var patchModulePath = "../patch-core";
|
||||
var patchedRequest = https.request;
|
||||
|
||||
delete require.cache[require.resolve(patchModulePath)];
|
||||
require(patchModulePath);
|
||||
|
||||
assert.equal(patchedRequest, https.request);
|
||||
assert.equal(true, https.request.__agent_base_https_request_patched__);
|
||||
});
|
||||
|
||||
describe('PassthroughAgent', function() {
|
||||
it('should pass through to `https.globalAgent`', function(done) {
|
||||
// add HTTP server "request" listener
|
||||
var gotReq = false;
|
||||
server.once('request', function(req, res) {
|
||||
gotReq = true;
|
||||
res.setHeader('X-Foo', 'bar');
|
||||
res.setHeader('X-Url', req.url);
|
||||
res.end();
|
||||
});
|
||||
|
||||
var info = url.parse('https://127.0.0.1:' + port + '/foo');
|
||||
info.agent = PassthroughAgent;
|
||||
info.rejectUnauthorized = false;
|
||||
https.get(info, function(res) {
|
||||
assert.equal('bar', res.headers['x-foo']);
|
||||
assert.equal('/foo', res.headers['x-url']);
|
||||
assert(gotReq);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"ws" server', function() {
|
||||
var wss;
|
||||
var server;
|
||||
var port;
|
||||
|
||||
// setup test HTTP server
|
||||
before(function(done) {
|
||||
server = http.createServer();
|
||||
wss = new WebSocket.Server({ server: server });
|
||||
server.listen(0, function() {
|
||||
port = server.address().port;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// shut down test HTTP server
|
||||
after(function(done) {
|
||||
server.once('close', function() {
|
||||
done();
|
||||
});
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('should work for basic WebSocket connections', function(done) {
|
||||
function onconnection(ws) {
|
||||
ws.on('message', function(data) {
|
||||
assert.equal('ping', data);
|
||||
ws.send('pong');
|
||||
});
|
||||
}
|
||||
wss.on('connection', onconnection);
|
||||
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
var socket = net.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
var client = new WebSocket('ws://127.0.0.1:' + port + '/', {
|
||||
agent: agent
|
||||
});
|
||||
|
||||
client.on('open', function() {
|
||||
client.send('ping');
|
||||
});
|
||||
|
||||
client.on('message', function(data) {
|
||||
assert.equal('pong', data);
|
||||
client.close();
|
||||
wss.removeListener('connection', onconnection);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('"wss" server', function() {
|
||||
var wss;
|
||||
var server;
|
||||
var port;
|
||||
|
||||
// setup test HTTP server
|
||||
before(function(done) {
|
||||
var options = {
|
||||
key: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.key'),
|
||||
cert: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.pem')
|
||||
};
|
||||
server = https.createServer(options);
|
||||
wss = new WebSocket.Server({ server: server });
|
||||
server.listen(0, function() {
|
||||
port = server.address().port;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// shut down test HTTP server
|
||||
after(function(done) {
|
||||
server.once('close', function() {
|
||||
done();
|
||||
});
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('should work for secure WebSocket connections', function(done) {
|
||||
function onconnection(ws) {
|
||||
ws.on('message', function(data) {
|
||||
assert.equal('ping', data);
|
||||
ws.send('pong');
|
||||
});
|
||||
}
|
||||
wss.on('connection', onconnection);
|
||||
|
||||
var agent = new Agent(function(req, opts, fn) {
|
||||
var socket = tls.connect(opts);
|
||||
fn(null, socket);
|
||||
});
|
||||
|
||||
var client = new WebSocket('wss://127.0.0.1:' + port + '/', {
|
||||
agent: agent,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
client.on('open', function() {
|
||||
client.send('ping');
|
||||
});
|
||||
|
||||
client.on('message', function(data) {
|
||||
assert.equal('pong', data);
|
||||
client.close();
|
||||
wss.removeListener('connection', onconnection);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
Generated
Vendored
-14
@@ -1,14 +0,0 @@
|
||||
Copyright (c) 2015, Rebecca Turner <me@re-becca.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/aproba/README.md
Generated
Vendored
-94
@@ -1,94 +0,0 @@
|
||||
aproba
|
||||
======
|
||||
|
||||
A ridiculously light-weight function argument validator
|
||||
|
||||
```
|
||||
var validate = require("aproba")
|
||||
|
||||
function myfunc(a, b, c) {
|
||||
// `a` must be a string, `b` a number, `c` a function
|
||||
validate('SNF', arguments) // [a,b,c] is also valid
|
||||
}
|
||||
|
||||
myfunc('test', 23, function () {}) // ok
|
||||
myfunc(123, 23, function () {}) // type error
|
||||
myfunc('test', 23) // missing arg error
|
||||
myfunc('test', 23, function () {}, true) // too many args error
|
||||
|
||||
```
|
||||
|
||||
Valid types are:
|
||||
|
||||
| type | description
|
||||
| :--: | :----------
|
||||
| * | matches any type
|
||||
| A | `Array.isArray` OR an `arguments` object
|
||||
| S | typeof == string
|
||||
| N | typeof == number
|
||||
| F | typeof == function
|
||||
| O | typeof == object and not type A and not type E
|
||||
| B | typeof == boolean
|
||||
| E | `instanceof Error` OR `null` **(special: see below)**
|
||||
| Z | == `null`
|
||||
|
||||
Validation failures throw one of three exception types, distinguished by a
|
||||
`code` property of `EMISSINGARG`, `EINVALIDTYPE` or `ETOOMANYARGS`.
|
||||
|
||||
If you pass in an invalid type then it will throw with a code of
|
||||
`EUNKNOWNTYPE`.
|
||||
|
||||
If an **error** argument is found and is not null then the remaining
|
||||
arguments are optional. That is, if you say `ESO` then that's like using a
|
||||
non-magical `E` in: `E|ESO|ZSO`.
|
||||
|
||||
### But I have optional arguments?!
|
||||
|
||||
You can provide more than one signature by separating them with pipes `|`.
|
||||
If any signature matches the arguments then they'll be considered valid.
|
||||
|
||||
So for example, say you wanted to write a signature for
|
||||
`fs.createWriteStream`. The docs for it describe it thusly:
|
||||
|
||||
```
|
||||
fs.createWriteStream(path[, options])
|
||||
```
|
||||
|
||||
This would be a signature of `SO|S`. That is, a string and and object, or
|
||||
just a string.
|
||||
|
||||
Now, if you read the full `fs` docs, you'll see that actually path can ALSO
|
||||
be a buffer. And options can be a string, that is:
|
||||
```
|
||||
path <String> | <Buffer>
|
||||
options <String> | <Object>
|
||||
```
|
||||
|
||||
To reproduce this you have to fully enumerate all of the possible
|
||||
combinations and that implies a signature of `SO|SS|OO|OS|S|O`. The
|
||||
awkwardness is a feature: It reminds you of the complexity you're adding to
|
||||
your API when you do this sort of thing.
|
||||
|
||||
|
||||
### Browser support
|
||||
|
||||
This has no dependencies and should work in browsers, though you'll have
|
||||
noisier stack traces.
|
||||
|
||||
### Why this exists
|
||||
|
||||
I wanted a very simple argument validator. It needed to do two things:
|
||||
|
||||
1. Be more concise and easier to use than assertions
|
||||
|
||||
2. Not encourage an infinite bikeshed of DSLs
|
||||
|
||||
This is why types are specified by a single character and there's no such
|
||||
thing as an optional argument.
|
||||
|
||||
This is not intended to validate user data. This is specifically about
|
||||
asserting the interface of your functions.
|
||||
|
||||
If you need greater validation, I encourage you to write them by hand or
|
||||
look elsewhere.
|
||||
|
||||
Generated
Vendored
-105
@@ -1,105 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
function isArguments (thingy) {
|
||||
return thingy != null && typeof thingy === 'object' && thingy.hasOwnProperty('callee')
|
||||
}
|
||||
|
||||
var types = {
|
||||
'*': {label: 'any', check: function () { return true }},
|
||||
A: {label: 'array', check: function (thingy) { return Array.isArray(thingy) || isArguments(thingy) }},
|
||||
S: {label: 'string', check: function (thingy) { return typeof thingy === 'string' }},
|
||||
N: {label: 'number', check: function (thingy) { return typeof thingy === 'number' }},
|
||||
F: {label: 'function', check: function (thingy) { return typeof thingy === 'function' }},
|
||||
O: {label: 'object', check: function (thingy) { return typeof thingy === 'object' && thingy != null && !types.A.check(thingy) && !types.E.check(thingy) }},
|
||||
B: {label: 'boolean', check: function (thingy) { return typeof thingy === 'boolean' }},
|
||||
E: {label: 'error', check: function (thingy) { return thingy instanceof Error }},
|
||||
Z: {label: 'null', check: function (thingy) { return thingy == null }}
|
||||
}
|
||||
|
||||
function addSchema (schema, arity) {
|
||||
var group = arity[schema.length] = arity[schema.length] || []
|
||||
if (group.indexOf(schema) === -1) group.push(schema)
|
||||
}
|
||||
|
||||
var validate = module.exports = function (rawSchemas, args) {
|
||||
if (arguments.length !== 2) throw wrongNumberOfArgs(['SA'], arguments.length)
|
||||
if (!rawSchemas) throw missingRequiredArg(0, 'rawSchemas')
|
||||
if (!args) throw missingRequiredArg(1, 'args')
|
||||
if (!types.S.check(rawSchemas)) throw invalidType(0, ['string'], rawSchemas)
|
||||
if (!types.A.check(args)) throw invalidType(1, ['array'], args)
|
||||
var schemas = rawSchemas.split('|')
|
||||
var arity = {}
|
||||
|
||||
schemas.forEach(function (schema) {
|
||||
for (var ii = 0; ii < schema.length; ++ii) {
|
||||
var type = schema[ii]
|
||||
if (!types[type]) throw unknownType(ii, type)
|
||||
}
|
||||
if (/E.*E/.test(schema)) throw moreThanOneError(schema)
|
||||
addSchema(schema, arity)
|
||||
if (/E/.test(schema)) {
|
||||
addSchema(schema.replace(/E.*$/, 'E'), arity)
|
||||
addSchema(schema.replace(/E/, 'Z'), arity)
|
||||
if (schema.length === 1) addSchema('', arity)
|
||||
}
|
||||
})
|
||||
var matching = arity[args.length]
|
||||
if (!matching) {
|
||||
throw wrongNumberOfArgs(Object.keys(arity), args.length)
|
||||
}
|
||||
for (var ii = 0; ii < args.length; ++ii) {
|
||||
var newMatching = matching.filter(function (schema) {
|
||||
var type = schema[ii]
|
||||
var typeCheck = types[type].check
|
||||
return typeCheck(args[ii])
|
||||
})
|
||||
if (!newMatching.length) {
|
||||
var labels = matching.map(function (schema) {
|
||||
return types[schema[ii]].label
|
||||
}).filter(function (schema) { return schema != null })
|
||||
throw invalidType(ii, labels, args[ii])
|
||||
}
|
||||
matching = newMatching
|
||||
}
|
||||
}
|
||||
|
||||
function missingRequiredArg (num) {
|
||||
return newException('EMISSINGARG', 'Missing required argument #' + (num + 1))
|
||||
}
|
||||
|
||||
function unknownType (num, type) {
|
||||
return newException('EUNKNOWNTYPE', 'Unknown type ' + type + ' in argument #' + (num + 1))
|
||||
}
|
||||
|
||||
function invalidType (num, expectedTypes, value) {
|
||||
var valueType
|
||||
Object.keys(types).forEach(function (typeCode) {
|
||||
if (types[typeCode].check(value)) valueType = types[typeCode].label
|
||||
})
|
||||
return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' +
|
||||
englishList(expectedTypes) + ' but got ' + valueType)
|
||||
}
|
||||
|
||||
function englishList (list) {
|
||||
return list.join(', ').replace(/, ([^,]+)$/, ' or $1')
|
||||
}
|
||||
|
||||
function wrongNumberOfArgs (expected, got) {
|
||||
var english = englishList(expected)
|
||||
var args = expected.every(function (ex) { return ex.length === 1 })
|
||||
? 'argument'
|
||||
: 'arguments'
|
||||
return newException('EWRONGARGCOUNT', 'Expected ' + english + ' ' + args + ' but got ' + got)
|
||||
}
|
||||
|
||||
function moreThanOneError (schema) {
|
||||
return newException('ETOOMANYERRORTYPES',
|
||||
'Only one error type per argument signature is allowed, more than one found in "' + schema + '"')
|
||||
}
|
||||
|
||||
function newException (code, msg) {
|
||||
var e = new Error(msg)
|
||||
e.code = code
|
||||
if (Error.captureStackTrace) Error.captureStackTrace(e, validate)
|
||||
return e
|
||||
}
|
||||
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"name": "aproba",
|
||||
"version": "1.2.0",
|
||||
"description": "A ridiculously light-weight argument validator (now browser friendly)",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"standard": "^10.0.3",
|
||||
"tap": "^10.0.2"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "standard && tap -j3 test/*.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iarna/aproba"
|
||||
},
|
||||
"keywords": [
|
||||
"argument",
|
||||
"validate"
|
||||
],
|
||||
"author": "Rebecca Turner <me@re-becca.org>",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/iarna/aproba/issues"
|
||||
},
|
||||
"homepage": "https://github.com/iarna/aproba"
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz"
|
||||
,"_integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
||||
,"_from": "aproba@1.2.0"
|
||||
}
|
||||
Generated
Vendored
-37
@@ -1,37 +0,0 @@
|
||||
Hi, figured we could actually use a changelog now:
|
||||
|
||||
## 1.1.5 2018-05-24
|
||||
|
||||
* [#92](https://github.com/iarna/are-we-there-yet/pull/92) Fix bug where
|
||||
`finish` would throw errors when including `TrackerStream` objects in
|
||||
`TrackerGroup` collections. (@brianloveswords)
|
||||
|
||||
## 1.1.4 2017-04-21
|
||||
|
||||
* Fix typo in package.json
|
||||
|
||||
## 1.1.3 2017-04-21
|
||||
|
||||
* Improve documentation and limit files included in the distribution.
|
||||
|
||||
## 1.1.2 2016-03-15
|
||||
|
||||
* Add tracker group cycle detection and tests for it
|
||||
|
||||
## 1.1.1 2016-01-29
|
||||
|
||||
* Fix a typo in stream completion tracker
|
||||
|
||||
## 1.1.0 2016-01-29
|
||||
|
||||
* Rewrote completion percent computation to be low impact– no more walking a
|
||||
tree of completion groups every time we need this info. Previously, with
|
||||
medium sized tree of completion groups, even a relatively modest number of
|
||||
calls to the top level `completed()` method would result in absurd numbers
|
||||
of calls overall as it walked down the tree. We now, instead, keep track as
|
||||
we bubble up changes, so the computation is limited to when data changes and
|
||||
to the depth of that one branch, instead of _every_ node. (Plus, we were already
|
||||
incurring _this_ cost, since we already bubbled out changes.)
|
||||
* Moved different tracker types out to their own files.
|
||||
* Made tests test for TOO MANY events too.
|
||||
* Standarized the source code formatting
|
||||
Generated
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
Copyright (c) 2015, Rebecca Turner
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Generated
Vendored
-195
@@ -1,195 +0,0 @@
|
||||
are-we-there-yet
|
||||
----------------
|
||||
|
||||
Track complex hiearchies of asynchronous task completion statuses. This is
|
||||
intended to give you a way of recording and reporting the progress of the big
|
||||
recursive fan-out and gather type workflows that are so common in async.
|
||||
|
||||
What you do with this completion data is up to you, but the most common use case is to
|
||||
feed it to one of the many progress bar modules.
|
||||
|
||||
Most progress bar modules include a rudamentary version of this, but my
|
||||
needs were more complex.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
```javascript
|
||||
var TrackerGroup = require("are-we-there-yet").TrackerGroup
|
||||
|
||||
var top = new TrackerGroup("program")
|
||||
|
||||
var single = top.newItem("one thing", 100)
|
||||
single.completeWork(20)
|
||||
|
||||
console.log(top.completed()) // 0.2
|
||||
|
||||
fs.stat("file", function(er, stat) {
|
||||
if (er) throw er
|
||||
var stream = top.newStream("file", stat.size)
|
||||
console.log(top.completed()) // now 0.1 as single is 50% of the job and is 20% complete
|
||||
// and 50% * 20% == 10%
|
||||
fs.createReadStream("file").pipe(stream).on("data", function (chunk) {
|
||||
// do stuff with chunk
|
||||
})
|
||||
top.on("change", function (name) {
|
||||
// called each time a chunk is read from "file"
|
||||
// top.completed() will start at 0.1 and fill up to 0.6 as the file is read
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Shared Methods
|
||||
==============
|
||||
|
||||
* var completed = tracker.completed()
|
||||
|
||||
Implemented in: `Tracker`, `TrackerGroup`, `TrackerStream`
|
||||
|
||||
Returns the ratio of completed work to work to be done. Range of 0 to 1.
|
||||
|
||||
* tracker.finish()
|
||||
|
||||
Implemented in: `Tracker`, `TrackerGroup`
|
||||
|
||||
Marks the tracker as completed. With a TrackerGroup this marks all of its
|
||||
components as completed.
|
||||
|
||||
Marks all of the components of this tracker as finished, which in turn means
|
||||
that `tracker.completed()` for this will now be 1.
|
||||
|
||||
This will result in one or more `change` events being emitted.
|
||||
|
||||
Events
|
||||
======
|
||||
|
||||
All tracker objects emit `change` events with the following arguments:
|
||||
|
||||
```
|
||||
function (name, completed, tracker)
|
||||
```
|
||||
|
||||
`name` is the name of the tracker that originally emitted the event,
|
||||
or if it didn't have one, the first containing tracker group that had one.
|
||||
|
||||
`completed` is the percent complete (as returned by `tracker.completed()` method).
|
||||
|
||||
`tracker` is the tracker object that you are listening for events on.
|
||||
|
||||
TrackerGroup
|
||||
============
|
||||
|
||||
* var tracker = new TrackerGroup(**name**)
|
||||
|
||||
* **name** *(optional)* - The name of this tracker group, used in change
|
||||
notifications if the component updating didn't have a name. Defaults to undefined.
|
||||
|
||||
Creates a new empty tracker aggregation group. These are trackers whose
|
||||
completion status is determined by the completion status of other trackers.
|
||||
|
||||
* tracker.addUnit(**otherTracker**, **weight**)
|
||||
|
||||
* **otherTracker** - Any of the other are-we-there-yet tracker objects
|
||||
* **weight** *(optional)* - The weight to give the tracker, defaults to 1.
|
||||
|
||||
Adds the **otherTracker** to this aggregation group. The weight determines
|
||||
how long you expect this tracker to take to complete in proportion to other
|
||||
units. So for instance, if you add one tracker with a weight of 1 and
|
||||
another with a weight of 2, you're saying the second will take twice as long
|
||||
to complete as the first. As such, the first will account for 33% of the
|
||||
completion of this tracker and the second will account for the other 67%.
|
||||
|
||||
Returns **otherTracker**.
|
||||
|
||||
* var subGroup = tracker.newGroup(**name**, **weight**)
|
||||
|
||||
The above is exactly equivalent to:
|
||||
|
||||
```javascript
|
||||
var subGroup = tracker.addUnit(new TrackerGroup(name), weight)
|
||||
```
|
||||
|
||||
* var subItem = tracker.newItem(**name**, **todo**, **weight**)
|
||||
|
||||
The above is exactly equivalent to:
|
||||
|
||||
```javascript
|
||||
var subItem = tracker.addUnit(new Tracker(name, todo), weight)
|
||||
```
|
||||
|
||||
* var subStream = tracker.newStream(**name**, **todo**, **weight**)
|
||||
|
||||
The above is exactly equivalent to:
|
||||
|
||||
```javascript
|
||||
var subStream = tracker.addUnit(new TrackerStream(name, todo), weight)
|
||||
```
|
||||
|
||||
* console.log( tracker.debug() )
|
||||
|
||||
Returns a tree showing the completion of this tracker group and all of its
|
||||
children, including recursively entering all of the children.
|
||||
|
||||
Tracker
|
||||
=======
|
||||
|
||||
* var tracker = new Tracker(**name**, **todo**)
|
||||
|
||||
* **name** *(optional)* The name of this counter to report in change
|
||||
events. Defaults to undefined.
|
||||
* **todo** *(optional)* The amount of work todo (a number). Defaults to 0.
|
||||
|
||||
Ordinarily these are constructed as a part of a tracker group (via
|
||||
`newItem`).
|
||||
|
||||
* var completed = tracker.completed()
|
||||
|
||||
Returns the ratio of completed work to work to be done. Range of 0 to 1. If
|
||||
total work to be done is 0 then it will return 0.
|
||||
|
||||
* tracker.addWork(**todo**)
|
||||
|
||||
* **todo** A number to add to the amount of work to be done.
|
||||
|
||||
Increases the amount of work to be done, thus decreasing the completion
|
||||
percentage. Triggers a `change` event.
|
||||
|
||||
* tracker.completeWork(**completed**)
|
||||
|
||||
* **completed** A number to add to the work complete
|
||||
|
||||
Increase the amount of work complete, thus increasing the completion percentage.
|
||||
Will never increase the work completed past the amount of work todo. That is,
|
||||
percentages > 100% are not allowed. Triggers a `change` event.
|
||||
|
||||
* tracker.finish()
|
||||
|
||||
Marks this tracker as finished, tracker.completed() will now be 1. Triggers
|
||||
a `change` event.
|
||||
|
||||
TrackerStream
|
||||
=============
|
||||
|
||||
* var tracker = new TrackerStream(**name**, **size**, **options**)
|
||||
|
||||
* **name** *(optional)* The name of this counter to report in change
|
||||
events. Defaults to undefined.
|
||||
* **size** *(optional)* The number of bytes being sent through this stream.
|
||||
* **options** *(optional)* A hash of stream options
|
||||
|
||||
The tracker stream object is a pass through stream that updates an internal
|
||||
tracker object each time a block passes through. It's intended to track
|
||||
downloads, file extraction and other related activities. You use it by piping
|
||||
your data source into it and then using it as your data source.
|
||||
|
||||
If your data has a length attribute then that's used as the amount of work
|
||||
completed when the chunk is passed through. If it does not (eg, object
|
||||
streams) then each chunk counts as completing 1 unit of work, so your size
|
||||
should be the total number of objects being streamed.
|
||||
|
||||
* tracker.addWork(**todo**)
|
||||
|
||||
* **todo** Increase the expected overall size by **todo** bytes.
|
||||
|
||||
Increases the amount of work to be done, thus decreasing the completion
|
||||
percentage. Triggers a `change` event.
|
||||
Generated
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
'use strict'
|
||||
exports.TrackerGroup = require('./tracker-group.js')
|
||||
exports.Tracker = require('./tracker.js')
|
||||
exports.TrackerStream = require('./tracker-stream.js')
|
||||
Generated
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "are-we-there-yet",
|
||||
"version": "1.1.5",
|
||||
"description": "Keep track of the overall completion of many disparate processes",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "standard && tap test/*.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iarna/are-we-there-yet.git"
|
||||
},
|
||||
"author": "Rebecca Turner (http://re-becca.org)",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/iarna/are-we-there-yet/issues"
|
||||
},
|
||||
"homepage": "https://github.com/iarna/are-we-there-yet",
|
||||
"devDependencies": {
|
||||
"standard": "^11.0.1",
|
||||
"tap": "^12.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"tracker-base.js",
|
||||
"tracker-group.js",
|
||||
"tracker-stream.js",
|
||||
"tracker.js",
|
||||
"CHANGES.md"
|
||||
]
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz"
|
||||
,"_integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w=="
|
||||
,"_from": "are-we-there-yet@1.1.5"
|
||||
}
|
||||
Generated
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
'use strict'
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
var util = require('util')
|
||||
|
||||
var trackerId = 0
|
||||
var TrackerBase = module.exports = function (name) {
|
||||
EventEmitter.call(this)
|
||||
this.id = ++trackerId
|
||||
this.name = name
|
||||
}
|
||||
util.inherits(TrackerBase, EventEmitter)
|
||||
Generated
Vendored
-107
@@ -1,107 +0,0 @@
|
||||
'use strict'
|
||||
var util = require('util')
|
||||
var TrackerBase = require('./tracker-base.js')
|
||||
var Tracker = require('./tracker.js')
|
||||
var TrackerStream = require('./tracker-stream.js')
|
||||
|
||||
var TrackerGroup = module.exports = function (name) {
|
||||
TrackerBase.call(this, name)
|
||||
this.parentGroup = null
|
||||
this.trackers = []
|
||||
this.completion = {}
|
||||
this.weight = {}
|
||||
this.totalWeight = 0
|
||||
this.finished = false
|
||||
this.bubbleChange = bubbleChange(this)
|
||||
}
|
||||
util.inherits(TrackerGroup, TrackerBase)
|
||||
|
||||
function bubbleChange (trackerGroup) {
|
||||
return function (name, completed, tracker) {
|
||||
trackerGroup.completion[tracker.id] = completed
|
||||
if (trackerGroup.finished) return
|
||||
trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup)
|
||||
}
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.nameInTree = function () {
|
||||
var names = []
|
||||
var from = this
|
||||
while (from) {
|
||||
names.unshift(from.name)
|
||||
from = from.parentGroup
|
||||
}
|
||||
return names.join('/')
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.addUnit = function (unit, weight) {
|
||||
if (unit.addUnit) {
|
||||
var toTest = this
|
||||
while (toTest) {
|
||||
if (unit === toTest) {
|
||||
throw new Error(
|
||||
'Attempted to add tracker group ' +
|
||||
unit.name + ' to tree that already includes it ' +
|
||||
this.nameInTree(this))
|
||||
}
|
||||
toTest = toTest.parentGroup
|
||||
}
|
||||
unit.parentGroup = this
|
||||
}
|
||||
this.weight[unit.id] = weight || 1
|
||||
this.totalWeight += this.weight[unit.id]
|
||||
this.trackers.push(unit)
|
||||
this.completion[unit.id] = unit.completed()
|
||||
unit.on('change', this.bubbleChange)
|
||||
if (!this.finished) this.emit('change', unit.name, this.completion[unit.id], unit)
|
||||
return unit
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.completed = function () {
|
||||
if (this.trackers.length === 0) return 0
|
||||
var valPerWeight = 1 / this.totalWeight
|
||||
var completed = 0
|
||||
for (var ii = 0; ii < this.trackers.length; ii++) {
|
||||
var trackerId = this.trackers[ii].id
|
||||
completed += valPerWeight * this.weight[trackerId] * this.completion[trackerId]
|
||||
}
|
||||
return completed
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.newGroup = function (name, weight) {
|
||||
return this.addUnit(new TrackerGroup(name), weight)
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.newItem = function (name, todo, weight) {
|
||||
return this.addUnit(new Tracker(name, todo), weight)
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.newStream = function (name, todo, weight) {
|
||||
return this.addUnit(new TrackerStream(name, todo), weight)
|
||||
}
|
||||
|
||||
TrackerGroup.prototype.finish = function () {
|
||||
this.finished = true
|
||||
if (!this.trackers.length) this.addUnit(new Tracker(), 1, true)
|
||||
for (var ii = 0; ii < this.trackers.length; ii++) {
|
||||
var tracker = this.trackers[ii]
|
||||
tracker.finish()
|
||||
tracker.removeListener('change', this.bubbleChange)
|
||||
}
|
||||
this.emit('change', this.name, 1, this)
|
||||
}
|
||||
|
||||
var buffer = ' '
|
||||
TrackerGroup.prototype.debug = function (depth) {
|
||||
depth = depth || 0
|
||||
var indent = depth ? buffer.substr(0, depth) : ''
|
||||
var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n'
|
||||
this.trackers.forEach(function (tracker) {
|
||||
if (tracker instanceof TrackerGroup) {
|
||||
output += tracker.debug(depth + 1)
|
||||
} else {
|
||||
output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n'
|
||||
}
|
||||
})
|
||||
return output
|
||||
}
|
||||
Generated
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
'use strict'
|
||||
var util = require('util')
|
||||
var stream = require('readable-stream')
|
||||
var delegate = require('delegates')
|
||||
var Tracker = require('./tracker.js')
|
||||
|
||||
var TrackerStream = module.exports = function (name, size, options) {
|
||||
stream.Transform.call(this, options)
|
||||
this.tracker = new Tracker(name, size)
|
||||
this.name = name
|
||||
this.id = this.tracker.id
|
||||
this.tracker.on('change', delegateChange(this))
|
||||
}
|
||||
util.inherits(TrackerStream, stream.Transform)
|
||||
|
||||
function delegateChange (trackerStream) {
|
||||
return function (name, completion, tracker) {
|
||||
trackerStream.emit('change', name, completion, trackerStream)
|
||||
}
|
||||
}
|
||||
|
||||
TrackerStream.prototype._transform = function (data, encoding, cb) {
|
||||
this.tracker.completeWork(data.length ? data.length : 1)
|
||||
this.push(data)
|
||||
cb()
|
||||
}
|
||||
|
||||
TrackerStream.prototype._flush = function (cb) {
|
||||
this.tracker.finish()
|
||||
cb()
|
||||
}
|
||||
|
||||
delegate(TrackerStream.prototype, 'tracker')
|
||||
.method('completed')
|
||||
.method('addWork')
|
||||
.method('finish')
|
||||
Generated
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
'use strict'
|
||||
var util = require('util')
|
||||
var TrackerBase = require('./tracker-base.js')
|
||||
|
||||
var Tracker = module.exports = function (name, todo) {
|
||||
TrackerBase.call(this, name)
|
||||
this.workDone = 0
|
||||
this.workTodo = todo || 0
|
||||
}
|
||||
util.inherits(Tracker, TrackerBase)
|
||||
|
||||
Tracker.prototype.completed = function () {
|
||||
return this.workTodo === 0 ? 0 : this.workDone / this.workTodo
|
||||
}
|
||||
|
||||
Tracker.prototype.addWork = function (work) {
|
||||
this.workTodo += work
|
||||
this.emit('change', this.name, this.completed(), this)
|
||||
}
|
||||
|
||||
Tracker.prototype.completeWork = function (work) {
|
||||
this.workDone += work
|
||||
if (this.workDone > this.workTodo) this.workDone = this.workTodo
|
||||
this.emit('change', this.name, this.completed(), this)
|
||||
}
|
||||
|
||||
Tracker.prototype.finish = function () {
|
||||
this.workTodo = this.workDone = 1
|
||||
this.emit('change', this.name, 1, this)
|
||||
}
|
||||
Generated
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
tidelift: "npm/balanced-match"
|
||||
patreon: juliangruber
|
||||
Generated
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
(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.
|
||||
Generated
Vendored
-97
@@ -1,97 +0,0 @@
|
||||
# balanced-match
|
||||
|
||||
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well!
|
||||
|
||||
[](http://travis-ci.org/juliangruber/balanced-match)
|
||||
[](https://www.npmjs.org/package/balanced-match)
|
||||
|
||||
[](https://ci.testling.com/juliangruber/balanced-match)
|
||||
|
||||
## Example
|
||||
|
||||
Get the first matching pair of braces:
|
||||
|
||||
```js
|
||||
var balanced = require('balanced-match');
|
||||
|
||||
console.log(balanced('{', '}', 'pre{in{nested}}post'));
|
||||
console.log(balanced('{', '}', 'pre{first}between{second}post'));
|
||||
console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'));
|
||||
```
|
||||
|
||||
The matches are:
|
||||
|
||||
```bash
|
||||
$ node example.js
|
||||
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
|
||||
{ start: 3,
|
||||
end: 9,
|
||||
pre: 'pre',
|
||||
body: 'first',
|
||||
post: 'between{second}post' }
|
||||
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### var m = balanced(a, b, str)
|
||||
|
||||
For the first non-nested matching pair of `a` and `b` in `str`, return an
|
||||
object with those keys:
|
||||
|
||||
* **start** the index of the first match of `a`
|
||||
* **end** the index of the matching `b`
|
||||
* **pre** the preamble, `a` and `b` not included
|
||||
* **body** the match, `a` and `b` not included
|
||||
* **post** the postscript, `a` and `b` not included
|
||||
|
||||
If there's no match, `undefined` will be returned.
|
||||
|
||||
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
|
||||
|
||||
### var r = balanced.range(a, b, str)
|
||||
|
||||
For the first non-nested matching pair of `a` and `b` in `str`, return an
|
||||
array with indexes: `[ <a index>, <b index> ]`.
|
||||
|
||||
If there's no match, `undefined` will be returned.
|
||||
|
||||
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```bash
|
||||
npm install balanced-match
|
||||
```
|
||||
|
||||
## Security contact information
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
|
||||
## 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.
|
||||
Generated
Vendored
-62
@@ -1,62 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = balanced;
|
||||
function balanced(a, b, str) {
|
||||
if (a instanceof RegExp) a = maybeMatch(a, str);
|
||||
if (b instanceof RegExp) b = maybeMatch(b, str);
|
||||
|
||||
var r = range(a, b, str);
|
||||
|
||||
return r && {
|
||||
start: r[0],
|
||||
end: r[1],
|
||||
pre: str.slice(0, r[0]),
|
||||
body: str.slice(r[0] + a.length, r[1]),
|
||||
post: str.slice(r[1] + b.length)
|
||||
};
|
||||
}
|
||||
|
||||
function maybeMatch(reg, str) {
|
||||
var m = str.match(reg);
|
||||
return m ? m[0] : null;
|
||||
}
|
||||
|
||||
balanced.range = range;
|
||||
function range(a, b, str) {
|
||||
var begs, beg, left, right, result;
|
||||
var ai = str.indexOf(a);
|
||||
var bi = str.indexOf(b, ai + 1);
|
||||
var i = ai;
|
||||
|
||||
if (ai >= 0 && bi > 0) {
|
||||
if(a===b) {
|
||||
return [ai, bi];
|
||||
}
|
||||
begs = [];
|
||||
left = str.length;
|
||||
|
||||
while (i >= 0 && !result) {
|
||||
if (i == ai) {
|
||||
begs.push(i);
|
||||
ai = str.indexOf(a, i + 1);
|
||||
} else if (begs.length == 1) {
|
||||
result = [ begs.pop(), bi ];
|
||||
} else {
|
||||
beg = begs.pop();
|
||||
if (beg < left) {
|
||||
left = beg;
|
||||
right = bi;
|
||||
}
|
||||
|
||||
bi = str.indexOf(b, i + 1);
|
||||
}
|
||||
|
||||
i = ai < bi && ai >= 0 ? ai : bi;
|
||||
}
|
||||
|
||||
if (begs.length) {
|
||||
result = [ left, right ];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Generated
Vendored
-76
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"_from": "balanced-match@^1.0.0",
|
||||
"_id": "balanced-match@1.0.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"_location": "/balanced-match",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "balanced-match@^1.0.0",
|
||||
"name": "balanced-match",
|
||||
"escapedName": "balanced-match",
|
||||
"rawSpec": "^1.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^1.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/brace-expansion"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"_shasum": "e83e3a7e3f300b34cb9d87f615fa0cbf357690ee",
|
||||
"_spec": "balanced-match@^1.0.0",
|
||||
"_where": "/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/brace-expansion",
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/juliangruber/balanced-match/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Match balanced character pairs, like \"{\" and \"}\"",
|
||||
"devDependencies": {
|
||||
"matcha": "^0.7.0",
|
||||
"tape": "^4.6.0"
|
||||
},
|
||||
"homepage": "https://github.com/juliangruber/balanced-match",
|
||||
"keywords": [
|
||||
"match",
|
||||
"regexp",
|
||||
"test",
|
||||
"balanced",
|
||||
"parse"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "balanced-match",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/juliangruber/balanced-match.git"
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "matcha test/bench.js",
|
||||
"test": "tape test/test.js"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/20..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/25..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
},
|
||||
"version": "1.0.2"
|
||||
}
|
||||
Generated
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
Generated
Vendored
-129
@@ -1,129 +0,0 @@
|
||||
# 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.
|
||||
Generated
Vendored
-201
@@ -1,201 +0,0 @@
|
||||
var concatMap = require('concat-map');
|
||||
var balanced = require('balanced-match');
|
||||
|
||||
module.exports = expandTop;
|
||||
|
||||
var escSlash = '\0SLASH'+Math.random()+'\0';
|
||||
var escOpen = '\0OPEN'+Math.random()+'\0';
|
||||
var escClose = '\0CLOSE'+Math.random()+'\0';
|
||||
var escComma = '\0COMMA'+Math.random()+'\0';
|
||||
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
||||
|
||||
function numeric(str) {
|
||||
return parseInt(str, 10) == str
|
||||
? parseInt(str, 10)
|
||||
: str.charCodeAt(0);
|
||||
}
|
||||
|
||||
function escapeBraces(str) {
|
||||
return str.split('\\\\').join(escSlash)
|
||||
.split('\\{').join(escOpen)
|
||||
.split('\\}').join(escClose)
|
||||
.split('\\,').join(escComma)
|
||||
.split('\\.').join(escPeriod);
|
||||
}
|
||||
|
||||
function unescapeBraces(str) {
|
||||
return str.split(escSlash).join('\\')
|
||||
.split(escOpen).join('{')
|
||||
.split(escClose).join('}')
|
||||
.split(escComma).join(',')
|
||||
.split(escPeriod).join('.');
|
||||
}
|
||||
|
||||
|
||||
// Basically just str.split(","), but handling cases
|
||||
// where we have nested braced sections, which should be
|
||||
// treated as individual members, like {a,{b,c},d}
|
||||
function parseCommaParts(str) {
|
||||
if (!str)
|
||||
return [''];
|
||||
|
||||
var parts = [];
|
||||
var m = balanced('{', '}', str);
|
||||
|
||||
if (!m)
|
||||
return str.split(',');
|
||||
|
||||
var pre = m.pre;
|
||||
var body = m.body;
|
||||
var post = m.post;
|
||||
var p = pre.split(',');
|
||||
|
||||
p[p.length-1] += '{' + body + '}';
|
||||
var postParts = parseCommaParts(post);
|
||||
if (post.length) {
|
||||
p[p.length-1] += postParts.shift();
|
||||
p.push.apply(p, postParts);
|
||||
}
|
||||
|
||||
parts.push.apply(parts, p);
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
function expandTop(str) {
|
||||
if (!str)
|
||||
return [];
|
||||
|
||||
// I don't know why Bash 4.3 does this, but it does.
|
||||
// Anything starting with {} will have the first two bytes preserved
|
||||
// but *only* at the top level, so {},a}b will not expand to anything,
|
||||
// but a{},b}c will be expanded to [a}c,abc].
|
||||
// One could argue that this is a bug in Bash, but since the goal of
|
||||
// this module is to match Bash's rules, we escape a leading {}
|
||||
if (str.substr(0, 2) === '{}') {
|
||||
str = '\\{\\}' + str.substr(2);
|
||||
}
|
||||
|
||||
return expand(escapeBraces(str), true).map(unescapeBraces);
|
||||
}
|
||||
|
||||
function identity(e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
function embrace(str) {
|
||||
return '{' + str + '}';
|
||||
}
|
||||
function isPadded(el) {
|
||||
return /^-?0\d/.test(el);
|
||||
}
|
||||
|
||||
function lte(i, y) {
|
||||
return i <= y;
|
||||
}
|
||||
function gte(i, y) {
|
||||
return i >= y;
|
||||
}
|
||||
|
||||
function expand(str, isTop) {
|
||||
var expansions = [];
|
||||
|
||||
var m = balanced('{', '}', str);
|
||||
if (!m || /\$$/.test(m.pre)) return [str];
|
||||
|
||||
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
||||
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
||||
var isSequence = isNumericSequence || isAlphaSequence;
|
||||
var isOptions = m.body.indexOf(',') >= 0;
|
||||
if (!isSequence && !isOptions) {
|
||||
// {a},b}
|
||||
if (m.post.match(/,.*\}/)) {
|
||||
str = m.pre + '{' + m.body + escClose + m.post;
|
||||
return expand(str);
|
||||
}
|
||||
return [str];
|
||||
}
|
||||
|
||||
var n;
|
||||
if (isSequence) {
|
||||
n = m.body.split(/\.\./);
|
||||
} else {
|
||||
n = parseCommaParts(m.body);
|
||||
if (n.length === 1) {
|
||||
// x{{a,b}}y ==> x{a}y x{b}y
|
||||
n = expand(n[0], false).map(embrace);
|
||||
if (n.length === 1) {
|
||||
var post = m.post.length
|
||||
? expand(m.post, false)
|
||||
: [''];
|
||||
return post.map(function(p) {
|
||||
return m.pre + n[0] + p;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at this point, n is the parts, and we know it's not a comma set
|
||||
// with a single entry.
|
||||
|
||||
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
||||
var pre = m.pre;
|
||||
var post = m.post.length
|
||||
? expand(m.post, false)
|
||||
: [''];
|
||||
|
||||
var N;
|
||||
|
||||
if (isSequence) {
|
||||
var x = numeric(n[0]);
|
||||
var y = numeric(n[1]);
|
||||
var width = Math.max(n[0].length, n[1].length)
|
||||
var incr = n.length == 3
|
||||
? Math.abs(numeric(n[2]))
|
||||
: 1;
|
||||
var test = lte;
|
||||
var reverse = y < x;
|
||||
if (reverse) {
|
||||
incr *= -1;
|
||||
test = gte;
|
||||
}
|
||||
var pad = n.some(isPadded);
|
||||
|
||||
N = [];
|
||||
|
||||
for (var i = x; test(i, y); i += incr) {
|
||||
var c;
|
||||
if (isAlphaSequence) {
|
||||
c = String.fromCharCode(i);
|
||||
if (c === '\\')
|
||||
c = '';
|
||||
} else {
|
||||
c = String(i);
|
||||
if (pad) {
|
||||
var need = width - c.length;
|
||||
if (need > 0) {
|
||||
var z = new Array(need + 1).join('0');
|
||||
if (i < 0)
|
||||
c = '-' + z + c.slice(1);
|
||||
else
|
||||
c = z + c;
|
||||
}
|
||||
}
|
||||
}
|
||||
N.push(c);
|
||||
}
|
||||
} else {
|
||||
N = concatMap(n, function(el) { return expand(el, false) });
|
||||
}
|
||||
|
||||
for (var j = 0; j < N.length; j++) {
|
||||
for (var k = 0; k < post.length; k++) {
|
||||
var expansion = pre + N[j] + post[k];
|
||||
if (!isTop || isSequence || expansion)
|
||||
expansions.push(expansion);
|
||||
}
|
||||
}
|
||||
|
||||
return expansions;
|
||||
}
|
||||
|
||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"name": "brace-expansion",
|
||||
"description": "Brace expansion as known from sh/bash",
|
||||
"version": "1.1.11",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/juliangruber/brace-expansion.git"
|
||||
},
|
||||
"homepage": "https://github.com/juliangruber/brace-expansion",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "tape test/*.js",
|
||||
"gentest": "bash test/generate.sh",
|
||||
"bench": "matcha test/perf/bench.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"matcha": "^0.7.0",
|
||||
"tape": "^4.6.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/20..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/25..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
|
||||
,"_integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="
|
||||
,"_from": "brace-expansion@1.1.11"
|
||||
}
|
||||
Generated
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/chownr/README.md
Generated
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
Like `chown -R`.
|
||||
|
||||
Takes the same arguments as `fs.chown()`
|
||||
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/chownr/chownr.js
Generated
Vendored
-167
@@ -1,167 +0,0 @@
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
/* istanbul ignore next */
|
||||
const LCHOWN = fs.lchown ? 'lchown' : 'chown'
|
||||
/* istanbul ignore next */
|
||||
const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'
|
||||
|
||||
/* istanbul ignore next */
|
||||
const needEISDIRHandled = fs.lchown &&
|
||||
!process.version.match(/v1[1-9]+\./) &&
|
||||
!process.version.match(/v10\.[6-9]/)
|
||||
|
||||
const lchownSync = (path, uid, gid) => {
|
||||
try {
|
||||
return fs[LCHOWNSYNC](path, uid, gid)
|
||||
} catch (er) {
|
||||
if (er.code !== 'ENOENT')
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
const chownSync = (path, uid, gid) => {
|
||||
try {
|
||||
return fs.chownSync(path, uid, gid)
|
||||
} catch (er) {
|
||||
if (er.code !== 'ENOENT')
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
const handleEISDIR =
|
||||
needEISDIRHandled ? (path, uid, gid, cb) => er => {
|
||||
// Node prior to v10 had a very questionable implementation of
|
||||
// fs.lchown, which would always try to call fs.open on a directory
|
||||
// Fall back to fs.chown in those cases.
|
||||
if (!er || er.code !== 'EISDIR')
|
||||
cb(er)
|
||||
else
|
||||
fs.chown(path, uid, gid, cb)
|
||||
}
|
||||
: (_, __, ___, cb) => cb
|
||||
|
||||
/* istanbul ignore next */
|
||||
const handleEISDirSync =
|
||||
needEISDIRHandled ? (path, uid, gid) => {
|
||||
try {
|
||||
return lchownSync(path, uid, gid)
|
||||
} catch (er) {
|
||||
if (er.code !== 'EISDIR')
|
||||
throw er
|
||||
chownSync(path, uid, gid)
|
||||
}
|
||||
}
|
||||
: (path, uid, gid) => lchownSync(path, uid, gid)
|
||||
|
||||
// fs.readdir could only accept an options object as of node v6
|
||||
const nodeVersion = process.version
|
||||
let readdir = (path, options, cb) => fs.readdir(path, options, cb)
|
||||
let readdirSync = (path, options) => fs.readdirSync(path, options)
|
||||
/* istanbul ignore next */
|
||||
if (/^v4\./.test(nodeVersion))
|
||||
readdir = (path, options, cb) => fs.readdir(path, cb)
|
||||
|
||||
const chown = (cpath, uid, gid, cb) => {
|
||||
fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, er => {
|
||||
// Skip ENOENT error
|
||||
cb(er && er.code !== 'ENOENT' ? er : null)
|
||||
}))
|
||||
}
|
||||
|
||||
const chownrKid = (p, child, uid, gid, cb) => {
|
||||
if (typeof child === 'string')
|
||||
return fs.lstat(path.resolve(p, child), (er, stats) => {
|
||||
// Skip ENOENT error
|
||||
if (er)
|
||||
return cb(er.code !== 'ENOENT' ? er : null)
|
||||
stats.name = child
|
||||
chownrKid(p, stats, uid, gid, cb)
|
||||
})
|
||||
|
||||
if (child.isDirectory()) {
|
||||
chownr(path.resolve(p, child.name), uid, gid, er => {
|
||||
if (er)
|
||||
return cb(er)
|
||||
const cpath = path.resolve(p, child.name)
|
||||
chown(cpath, uid, gid, cb)
|
||||
})
|
||||
} else {
|
||||
const cpath = path.resolve(p, child.name)
|
||||
chown(cpath, uid, gid, cb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const chownr = (p, uid, gid, cb) => {
|
||||
readdir(p, { withFileTypes: true }, (er, children) => {
|
||||
// any error other than ENOTDIR or ENOTSUP means it's not readable,
|
||||
// or doesn't exist. give up.
|
||||
if (er) {
|
||||
if (er.code === 'ENOENT')
|
||||
return cb()
|
||||
else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
|
||||
return cb(er)
|
||||
}
|
||||
if (er || !children.length)
|
||||
return chown(p, uid, gid, cb)
|
||||
|
||||
let len = children.length
|
||||
let errState = null
|
||||
const then = er => {
|
||||
if (errState)
|
||||
return
|
||||
if (er)
|
||||
return cb(errState = er)
|
||||
if (-- len === 0)
|
||||
return chown(p, uid, gid, cb)
|
||||
}
|
||||
|
||||
children.forEach(child => chownrKid(p, child, uid, gid, then))
|
||||
})
|
||||
}
|
||||
|
||||
const chownrKidSync = (p, child, uid, gid) => {
|
||||
if (typeof child === 'string') {
|
||||
try {
|
||||
const stats = fs.lstatSync(path.resolve(p, child))
|
||||
stats.name = child
|
||||
child = stats
|
||||
} catch (er) {
|
||||
if (er.code === 'ENOENT')
|
||||
return
|
||||
else
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
if (child.isDirectory())
|
||||
chownrSync(path.resolve(p, child.name), uid, gid)
|
||||
|
||||
handleEISDirSync(path.resolve(p, child.name), uid, gid)
|
||||
}
|
||||
|
||||
const chownrSync = (p, uid, gid) => {
|
||||
let children
|
||||
try {
|
||||
children = readdirSync(p, { withFileTypes: true })
|
||||
} catch (er) {
|
||||
if (er.code === 'ENOENT')
|
||||
return
|
||||
else if (er.code === 'ENOTDIR' || er.code === 'ENOTSUP')
|
||||
return handleEISDirSync(p, uid, gid)
|
||||
else
|
||||
throw er
|
||||
}
|
||||
|
||||
if (children && children.length)
|
||||
children.forEach(child => chownrKidSync(p, child, uid, gid))
|
||||
|
||||
return handleEISDirSync(p, uid, gid)
|
||||
}
|
||||
|
||||
module.exports = chownr
|
||||
chownr.sync = chownrSync
|
||||
Generated
Vendored
-33
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"name": "chownr",
|
||||
"description": "like `chown -R`",
|
||||
"version": "1.1.4",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/chownr.git"
|
||||
},
|
||||
"main": "chownr.js",
|
||||
"files": [
|
||||
"chownr.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"mkdirp": "0.3",
|
||||
"rimraf": "^2.7.1",
|
||||
"tap": "^14.10.6"
|
||||
},
|
||||
"tap": {
|
||||
"check-coverage": true
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap",
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"prepublishOnly": "git push origin --follow-tags"
|
||||
},
|
||||
"license": "ISC"
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz"
|
||||
,"_integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
,"_from": "chownr@1.1.4"
|
||||
}
|
||||
Generated
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
/* eslint-disable babel/new-cap, xo/throw-new-error */
|
||||
'use strict';
|
||||
module.exports = function (str, pos) {
|
||||
if (str === null || str === undefined) {
|
||||
throw TypeError();
|
||||
}
|
||||
|
||||
str = String(str);
|
||||
|
||||
var size = str.length;
|
||||
var i = pos ? Number(pos) : 0;
|
||||
|
||||
if (Number.isNaN(i)) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= size) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var first = str.charCodeAt(i);
|
||||
|
||||
if (first >= 0xD800 && first <= 0xDBFF && size > i + 1) {
|
||||
var second = str.charCodeAt(i + 1);
|
||||
|
||||
if (second >= 0xDC00 && second <= 0xDFFF) {
|
||||
return ((first - 0xD800) * 0x400) + second - 0xDC00 + 0x10000;
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
};
|
||||
Generated
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Generated
Vendored
-42
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"name": "code-point-at",
|
||||
"version": "1.1.0",
|
||||
"description": "ES2015 `String#codePointAt()` ponyfill",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/code-point-at",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"es2015",
|
||||
"ponyfill",
|
||||
"polyfill",
|
||||
"shim",
|
||||
"string",
|
||||
"str",
|
||||
"code",
|
||||
"point",
|
||||
"at",
|
||||
"codepoint",
|
||||
"unicode"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "^0.16.0"
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz"
|
||||
,"_integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
,"_from": "code-point-at@1.1.0"
|
||||
}
|
||||
Generated
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
# code-point-at [](https://travis-ci.org/sindresorhus/code-point-at)
|
||||
|
||||
> ES2015 [`String#codePointAt()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) [ponyfill](https://ponyfill.com)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save code-point-at
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var codePointAt = require('code-point-at');
|
||||
|
||||
codePointAt('🐴');
|
||||
//=> 128052
|
||||
|
||||
codePointAt('abc', 2);
|
||||
//=> 99
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### codePointAt(input, [position])
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
Generated
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
||||
Generated
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
This software is released under the MIT license:
|
||||
|
||||
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.
|
||||
Generated
Vendored
-62
@@ -1,62 +0,0 @@
|
||||
concat-map
|
||||
==========
|
||||
|
||||
Concatenative mapdashery.
|
||||
|
||||
[](http://ci.testling.com/substack/node-concat-map)
|
||||
|
||||
[](http://travis-ci.org/substack/node-concat-map)
|
||||
|
||||
example
|
||||
=======
|
||||
|
||||
``` js
|
||||
var concatMap = require('concat-map');
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
console.dir(ys);
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
```
|
||||
[ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]
|
||||
```
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
``` js
|
||||
var concatMap = require('concat-map')
|
||||
```
|
||||
|
||||
concatMap(xs, fn)
|
||||
-----------------
|
||||
|
||||
Return an array of concatenated elements by calling `fn(x, i)` for each element
|
||||
`x` and each index `i` in the array `xs`.
|
||||
|
||||
When `fn(x, i)` returns an array, its result will be concatenated with the
|
||||
result array. If `fn(x, i)` returns anything else, that value will be pushed
|
||||
onto the end of the result array.
|
||||
|
||||
install
|
||||
=======
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install concat-map
|
||||
```
|
||||
|
||||
license
|
||||
=======
|
||||
|
||||
MIT
|
||||
|
||||
notes
|
||||
=====
|
||||
|
||||
This module was written while sitting high above the ground in a tree.
|
||||
Generated
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
var concatMap = require('../');
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
console.dir(ys);
|
||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
module.exports = function (xs, fn) {
|
||||
var res = [];
|
||||
for (var i = 0; i < xs.length; i++) {
|
||||
var x = fn(xs[i], i);
|
||||
if (isArray(x)) res.push.apply(res, x);
|
||||
else res.push(x);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
var isArray = Array.isArray || function (xs) {
|
||||
return Object.prototype.toString.call(xs) === '[object Array]';
|
||||
};
|
||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"name" : "concat-map",
|
||||
"description" : "concatenative mapdashery",
|
||||
"version" : "0.0.1",
|
||||
"repository" : {
|
||||
"type" : "git",
|
||||
"url" : "git://github.com/substack/node-concat-map.git"
|
||||
},
|
||||
"main" : "index.js",
|
||||
"keywords" : [
|
||||
"concat",
|
||||
"concatMap",
|
||||
"map",
|
||||
"functional",
|
||||
"higher-order"
|
||||
],
|
||||
"directories" : {
|
||||
"example" : "example",
|
||||
"test" : "test"
|
||||
},
|
||||
"scripts" : {
|
||||
"test" : "tape test/*.js"
|
||||
},
|
||||
"devDependencies" : {
|
||||
"tape" : "~2.4.0"
|
||||
},
|
||||
"license" : "MIT",
|
||||
"author" : {
|
||||
"name" : "James Halliday",
|
||||
"email" : "mail@substack.net",
|
||||
"url" : "http://substack.net"
|
||||
},
|
||||
"testling" : {
|
||||
"files" : "test/*.js",
|
||||
"browsers" : {
|
||||
"ie" : [ 6, 7, 8, 9 ],
|
||||
"ff" : [ 3.5, 10, 15.0 ],
|
||||
"chrome" : [ 10, 22 ],
|
||||
"safari" : [ 5.1 ],
|
||||
"opera" : [ 12 ]
|
||||
}
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
,"_integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
,"_from": "concat-map@0.0.1"
|
||||
}
|
||||
Generated
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
var concatMap = require('../');
|
||||
var test = require('tape');
|
||||
|
||||
test('empty or not', function (t) {
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ixes = [];
|
||||
var ys = concatMap(xs, function (x, ix) {
|
||||
ixes.push(ix);
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
t.same(ys, [ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]);
|
||||
t.same(ixes, [ 0, 1, 2, 3, 4, 5 ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('always something', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x === 'b' ? [ 'B', 'B', 'B' ] : [ x ];
|
||||
});
|
||||
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('scalars', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x === 'b' ? [ 'B', 'B', 'B' ] : x;
|
||||
});
|
||||
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('undefs', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function () {});
|
||||
t.same(ys, [ undefined, undefined, undefined, undefined ]);
|
||||
t.end();
|
||||
});
|
||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
Copyright (c) 2014, Rebecca Turner <me@re-becca.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Generated
Vendored
-145
@@ -1,145 +0,0 @@
|
||||
# Console Control Strings
|
||||
|
||||
A library of cross-platform tested terminal/console command strings for
|
||||
doing things like color and cursor positioning. This is a subset of both
|
||||
ansi and vt100. All control codes included work on both Windows & Unix-like
|
||||
OSes, except where noted.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var consoleControl = require('console-control-strings')
|
||||
|
||||
console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
|
||||
process.stdout.write(consoleControl.goto(75, 10))
|
||||
```
|
||||
|
||||
## Why Another?
|
||||
|
||||
There are tons of libraries similar to this one. I wanted one that was:
|
||||
|
||||
1. Very clear about compatibility goals.
|
||||
2. Could emit, for instance, a start color code without an end one.
|
||||
3. Returned strings w/o writing to streams.
|
||||
4. Was not weighed down with other unrelated baggage.
|
||||
|
||||
## Functions
|
||||
|
||||
### var code = consoleControl.up(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines up.
|
||||
|
||||
### var code = consoleControl.down(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines down.
|
||||
|
||||
### var code = consoleControl.forward(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines righ.
|
||||
|
||||
### var code = consoleControl.back(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines left.
|
||||
|
||||
### var code = consoleControl.nextLine(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines down and to the beginning of
|
||||
the line.
|
||||
|
||||
### var code = consoleControl.previousLine(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines up and to the beginning of
|
||||
the line.
|
||||
|
||||
### var code = consoleControl.eraseData()
|
||||
|
||||
Returns the escape sequence to erase everything from the current cursor
|
||||
position to the bottom right of the screen. This is line based, so it
|
||||
erases the remainder of the current line and all following lines.
|
||||
|
||||
### var code = consoleControl.eraseLine()
|
||||
|
||||
Returns the escape sequence to erase to the end of the current line.
|
||||
|
||||
### var code = consoleControl.goto(_x_, _y_)
|
||||
|
||||
Returns the escape sequence to move the cursor to the designated position.
|
||||
Note that the origin is _1, 1_ not _0, 0_.
|
||||
|
||||
### var code = consoleControl.gotoSOL()
|
||||
|
||||
Returns the escape sequence to move the cursor to the beginning of the
|
||||
current line. (That is, it returns a carriage return, `\r`.)
|
||||
|
||||
### var code = consoleControl.beep()
|
||||
|
||||
Returns the escape sequence to cause the termianl to beep. (That is, it
|
||||
returns unicode character `\x0007`, a Control-G.)
|
||||
|
||||
### var code = consoleControl.hideCursor()
|
||||
|
||||
Returns the escape sequence to hide the cursor.
|
||||
|
||||
### var code = consoleControl.showCursor()
|
||||
|
||||
Returns the escape sequence to show the cursor.
|
||||
|
||||
### var code = consoleControl.color(_colors = []_)
|
||||
|
||||
### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
|
||||
|
||||
Returns the escape sequence to set the current terminal display attributes
|
||||
(mostly colors). Arguments can either be a list of attributes or an array
|
||||
of attributes. The difference between passing in an array or list of colors
|
||||
and calling `.color` separately for each one, is that in the former case a
|
||||
single escape sequence will be produced where as in the latter each change
|
||||
will have its own distinct escape sequence. Each attribute can be one of:
|
||||
|
||||
* Reset:
|
||||
* **reset** – Reset all attributes to the terminal default.
|
||||
* Styles:
|
||||
* **bold** – Display text as bold. In some terminals this means using a
|
||||
bold font, in others this means changing the color. In some it means
|
||||
both.
|
||||
* **italic** – Display text as italic. This is not available in most Windows terminals.
|
||||
* **underline** – Underline text. This is not available in most Windows Terminals.
|
||||
* **inverse** – Invert the foreground and background colors.
|
||||
* **stopBold** – Do not display text as bold.
|
||||
* **stopItalic** – Do not display text as italic.
|
||||
* **stopUnderline** – Do not underline text.
|
||||
* **stopInverse** – Do not invert foreground and background.
|
||||
* Colors:
|
||||
* **white**
|
||||
* **black**
|
||||
* **blue**
|
||||
* **cyan**
|
||||
* **green**
|
||||
* **magenta**
|
||||
* **red**
|
||||
* **yellow**
|
||||
* **grey** / **brightBlack**
|
||||
* **brightRed**
|
||||
* **brightGreen**
|
||||
* **brightYellow**
|
||||
* **brightBlue**
|
||||
* **brightMagenta**
|
||||
* **brightCyan**
|
||||
* **brightWhite**
|
||||
* Background Colors:
|
||||
* **bgWhite**
|
||||
* **bgBlack**
|
||||
* **bgBlue**
|
||||
* **bgCyan**
|
||||
* **bgGreen**
|
||||
* **bgMagenta**
|
||||
* **bgRed**
|
||||
* **bgYellow**
|
||||
* **bgGrey** / **bgBrightBlack**
|
||||
* **bgBrightRed**
|
||||
* **bgBrightGreen**
|
||||
* **bgBrightYellow**
|
||||
* **bgBrightBlue**
|
||||
* **bgBrightMagenta**
|
||||
* **bgBrightCyan**
|
||||
* **bgBrightWhite**
|
||||
|
||||
Generated
Vendored
-140
@@ -1,140 +0,0 @@
|
||||
# Console Control Strings
|
||||
|
||||
A library of cross-platform tested terminal/console command strings for
|
||||
doing things like color and cursor positioning. This is a subset of both
|
||||
ansi and vt100. All control codes included work on both Windows & Unix-like
|
||||
OSes, except where noted.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var consoleControl = require('console-control-strings')
|
||||
|
||||
console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
|
||||
process.stdout.write(consoleControl.goto(75, 10))
|
||||
```
|
||||
|
||||
## Why Another?
|
||||
|
||||
There are tons of libraries similar to this one. I wanted one that was:
|
||||
|
||||
1. Very clear about compatibility goals.
|
||||
2. Could emit, for instance, a start color code without an end one.
|
||||
3. Returned strings w/o writing to streams.
|
||||
4. Was not weighed down with other unrelated baggage.
|
||||
|
||||
## Functions
|
||||
|
||||
### var code = consoleControl.up(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines up.
|
||||
|
||||
### var code = consoleControl.down(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines down.
|
||||
|
||||
### var code = consoleControl.forward(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines righ.
|
||||
|
||||
### var code = consoleControl.back(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines left.
|
||||
|
||||
### var code = consoleControl.nextLine(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines down and to the beginning of
|
||||
the line.
|
||||
|
||||
### var code = consoleControl.previousLine(_num = 1_)
|
||||
|
||||
Returns the escape sequence to move _num_ lines up and to the beginning of
|
||||
the line.
|
||||
|
||||
### var code = consoleControl.eraseData()
|
||||
|
||||
Returns the escape sequence to erase everything from the current cursor
|
||||
position to the bottom right of the screen. This is line based, so it
|
||||
erases the remainder of the current line and all following lines.
|
||||
|
||||
### var code = consoleControl.eraseLine()
|
||||
|
||||
Returns the escape sequence to erase to the end of the current line.
|
||||
|
||||
### var code = consoleControl.goto(_x_, _y_)
|
||||
|
||||
Returns the escape sequence to move the cursor to the designated position.
|
||||
Note that the origin is _1, 1_ not _0, 0_.
|
||||
|
||||
### var code = consoleControl.gotoSOL()
|
||||
|
||||
Returns the escape sequence to move the cursor to the beginning of the
|
||||
current line. (That is, it returns a carriage return, `\r`.)
|
||||
|
||||
### var code = consoleControl.hideCursor()
|
||||
|
||||
Returns the escape sequence to hide the cursor.
|
||||
|
||||
### var code = consoleControl.showCursor()
|
||||
|
||||
Returns the escape sequence to show the cursor.
|
||||
|
||||
### var code = consoleControl.color(_colors = []_)
|
||||
|
||||
### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
|
||||
|
||||
Returns the escape sequence to set the current terminal display attributes
|
||||
(mostly colors). Arguments can either be a list of attributes or an array
|
||||
of attributes. The difference between passing in an array or list of colors
|
||||
and calling `.color` separately for each one, is that in the former case a
|
||||
single escape sequence will be produced where as in the latter each change
|
||||
will have its own distinct escape sequence. Each attribute can be one of:
|
||||
|
||||
* Reset:
|
||||
* **reset** – Reset all attributes to the terminal default.
|
||||
* Styles:
|
||||
* **bold** – Display text as bold. In some terminals this means using a
|
||||
bold font, in others this means changing the color. In some it means
|
||||
both.
|
||||
* **italic** – Display text as italic. This is not available in most Windows terminals.
|
||||
* **underline** – Underline text. This is not available in most Windows Terminals.
|
||||
* **inverse** – Invert the foreground and background colors.
|
||||
* **stopBold** – Do not display text as bold.
|
||||
* **stopItalic** – Do not display text as italic.
|
||||
* **stopUnderline** – Do not underline text.
|
||||
* **stopInverse** – Do not invert foreground and background.
|
||||
* Colors:
|
||||
* **white**
|
||||
* **black**
|
||||
* **blue**
|
||||
* **cyan**
|
||||
* **green**
|
||||
* **magenta**
|
||||
* **red**
|
||||
* **yellow**
|
||||
* **grey** / **brightBlack**
|
||||
* **brightRed**
|
||||
* **brightGreen**
|
||||
* **brightYellow**
|
||||
* **brightBlue**
|
||||
* **brightMagenta**
|
||||
* **brightCyan**
|
||||
* **brightWhite**
|
||||
* Background Colors:
|
||||
* **bgWhite**
|
||||
* **bgBlack**
|
||||
* **bgBlue**
|
||||
* **bgCyan**
|
||||
* **bgGreen**
|
||||
* **bgMagenta**
|
||||
* **bgRed**
|
||||
* **bgYellow**
|
||||
* **bgGrey** / **bgBrightBlack**
|
||||
* **bgBrightRed**
|
||||
* **bgBrightGreen**
|
||||
* **bgBrightYellow**
|
||||
* **bgBrightBlue**
|
||||
* **bgBrightMagenta**
|
||||
* **bgBrightCyan**
|
||||
* **bgBrightWhite**
|
||||
|
||||
Generated
Vendored
-125
@@ -1,125 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
// These tables borrowed from `ansi`
|
||||
|
||||
var prefix = '\x1b['
|
||||
|
||||
exports.up = function up (num) {
|
||||
return prefix + (num || '') + 'A'
|
||||
}
|
||||
|
||||
exports.down = function down (num) {
|
||||
return prefix + (num || '') + 'B'
|
||||
}
|
||||
|
||||
exports.forward = function forward (num) {
|
||||
return prefix + (num || '') + 'C'
|
||||
}
|
||||
|
||||
exports.back = function back (num) {
|
||||
return prefix + (num || '') + 'D'
|
||||
}
|
||||
|
||||
exports.nextLine = function nextLine (num) {
|
||||
return prefix + (num || '') + 'E'
|
||||
}
|
||||
|
||||
exports.previousLine = function previousLine (num) {
|
||||
return prefix + (num || '') + 'F'
|
||||
}
|
||||
|
||||
exports.horizontalAbsolute = function horizontalAbsolute (num) {
|
||||
if (num == null) throw new Error('horizontalAboslute requires a column to position to')
|
||||
return prefix + num + 'G'
|
||||
}
|
||||
|
||||
exports.eraseData = function eraseData () {
|
||||
return prefix + 'J'
|
||||
}
|
||||
|
||||
exports.eraseLine = function eraseLine () {
|
||||
return prefix + 'K'
|
||||
}
|
||||
|
||||
exports.goto = function (x, y) {
|
||||
return prefix + y + ';' + x + 'H'
|
||||
}
|
||||
|
||||
exports.gotoSOL = function () {
|
||||
return '\r'
|
||||
}
|
||||
|
||||
exports.beep = function () {
|
||||
return '\x07'
|
||||
}
|
||||
|
||||
exports.hideCursor = function hideCursor () {
|
||||
return prefix + '?25l'
|
||||
}
|
||||
|
||||
exports.showCursor = function showCursor () {
|
||||
return prefix + '?25h'
|
||||
}
|
||||
|
||||
var colors = {
|
||||
reset: 0,
|
||||
// styles
|
||||
bold: 1,
|
||||
italic: 3,
|
||||
underline: 4,
|
||||
inverse: 7,
|
||||
// resets
|
||||
stopBold: 22,
|
||||
stopItalic: 23,
|
||||
stopUnderline: 24,
|
||||
stopInverse: 27,
|
||||
// colors
|
||||
white: 37,
|
||||
black: 30,
|
||||
blue: 34,
|
||||
cyan: 36,
|
||||
green: 32,
|
||||
magenta: 35,
|
||||
red: 31,
|
||||
yellow: 33,
|
||||
bgWhite: 47,
|
||||
bgBlack: 40,
|
||||
bgBlue: 44,
|
||||
bgCyan: 46,
|
||||
bgGreen: 42,
|
||||
bgMagenta: 45,
|
||||
bgRed: 41,
|
||||
bgYellow: 43,
|
||||
|
||||
grey: 90,
|
||||
brightBlack: 90,
|
||||
brightRed: 91,
|
||||
brightGreen: 92,
|
||||
brightYellow: 93,
|
||||
brightBlue: 94,
|
||||
brightMagenta: 95,
|
||||
brightCyan: 96,
|
||||
brightWhite: 97,
|
||||
|
||||
bgGrey: 100,
|
||||
bgBrightBlack: 100,
|
||||
bgBrightRed: 101,
|
||||
bgBrightGreen: 102,
|
||||
bgBrightYellow: 103,
|
||||
bgBrightBlue: 104,
|
||||
bgBrightMagenta: 105,
|
||||
bgBrightCyan: 106,
|
||||
bgBrightWhite: 107
|
||||
}
|
||||
|
||||
exports.color = function color (colorWith) {
|
||||
if (arguments.length !== 1 || !Array.isArray(colorWith)) {
|
||||
colorWith = Array.prototype.slice.call(arguments)
|
||||
}
|
||||
return prefix + colorWith.map(colorNameToCode).join(';') + 'm'
|
||||
}
|
||||
|
||||
function colorNameToCode (color) {
|
||||
if (colors[color] != null) return colors[color]
|
||||
throw new Error('Unknown color or style name: ' + color)
|
||||
}
|
||||
Generated
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "console-control-strings",
|
||||
"version": "1.1.0",
|
||||
"description": "A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning. This is a subset of both ansi and vt100. All control codes included work on both Windows & Unix-like OSes, except where noted.",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && tap test/*.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iarna/console-control-strings"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org/)",
|
||||
"license": "ISC",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"index.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"standard": "^7.1.2",
|
||||
"tap": "^5.7.2"
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz"
|
||||
,"_integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
,"_from": "console-control-strings@1.1.0"
|
||||
}
|
||||
Generated
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
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.
|
||||
Generated
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
# core-util-is
|
||||
|
||||
The `util.is*` functions introduced in Node v0.12.
|
||||
Generated
Vendored
-604
@@ -1,604 +0,0 @@
|
||||
diff --git a/lib/util.js b/lib/util.js
|
||||
index a03e874..9074e8e 100644
|
||||
--- a/lib/util.js
|
||||
+++ b/lib/util.js
|
||||
@@ -19,430 +19,6 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-var formatRegExp = /%[sdj%]/g;
|
||||
-exports.format = function(f) {
|
||||
- if (!isString(f)) {
|
||||
- var objects = [];
|
||||
- for (var i = 0; i < arguments.length; i++) {
|
||||
- objects.push(inspect(arguments[i]));
|
||||
- }
|
||||
- return objects.join(' ');
|
||||
- }
|
||||
-
|
||||
- var i = 1;
|
||||
- var args = arguments;
|
||||
- var len = args.length;
|
||||
- var str = String(f).replace(formatRegExp, function(x) {
|
||||
- if (x === '%%') return '%';
|
||||
- if (i >= len) return x;
|
||||
- switch (x) {
|
||||
- case '%s': return String(args[i++]);
|
||||
- case '%d': return Number(args[i++]);
|
||||
- case '%j':
|
||||
- try {
|
||||
- return JSON.stringify(args[i++]);
|
||||
- } catch (_) {
|
||||
- return '[Circular]';
|
||||
- }
|
||||
- default:
|
||||
- return x;
|
||||
- }
|
||||
- });
|
||||
- for (var x = args[i]; i < len; x = args[++i]) {
|
||||
- if (isNull(x) || !isObject(x)) {
|
||||
- str += ' ' + x;
|
||||
- } else {
|
||||
- str += ' ' + inspect(x);
|
||||
- }
|
||||
- }
|
||||
- return str;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-// Mark that a method should not be used.
|
||||
-// Returns a modified function which warns once by default.
|
||||
-// If --no-deprecation is set, then it is a no-op.
|
||||
-exports.deprecate = function(fn, msg) {
|
||||
- // Allow for deprecating things in the process of starting up.
|
||||
- if (isUndefined(global.process)) {
|
||||
- return function() {
|
||||
- return exports.deprecate(fn, msg).apply(this, arguments);
|
||||
- };
|
||||
- }
|
||||
-
|
||||
- if (process.noDeprecation === true) {
|
||||
- return fn;
|
||||
- }
|
||||
-
|
||||
- var warned = false;
|
||||
- function deprecated() {
|
||||
- if (!warned) {
|
||||
- if (process.throwDeprecation) {
|
||||
- throw new Error(msg);
|
||||
- } else if (process.traceDeprecation) {
|
||||
- console.trace(msg);
|
||||
- } else {
|
||||
- console.error(msg);
|
||||
- }
|
||||
- warned = true;
|
||||
- }
|
||||
- return fn.apply(this, arguments);
|
||||
- }
|
||||
-
|
||||
- return deprecated;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-var debugs = {};
|
||||
-var debugEnviron;
|
||||
-exports.debuglog = function(set) {
|
||||
- if (isUndefined(debugEnviron))
|
||||
- debugEnviron = process.env.NODE_DEBUG || '';
|
||||
- set = set.toUpperCase();
|
||||
- if (!debugs[set]) {
|
||||
- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
||||
- var pid = process.pid;
|
||||
- debugs[set] = function() {
|
||||
- var msg = exports.format.apply(exports, arguments);
|
||||
- console.error('%s %d: %s', set, pid, msg);
|
||||
- };
|
||||
- } else {
|
||||
- debugs[set] = function() {};
|
||||
- }
|
||||
- }
|
||||
- return debugs[set];
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Echos the value of a value. Trys to print the value out
|
||||
- * in the best way possible given the different types.
|
||||
- *
|
||||
- * @param {Object} obj The object to print out.
|
||||
- * @param {Object} opts Optional options object that alters the output.
|
||||
- */
|
||||
-/* legacy: obj, showHidden, depth, colors*/
|
||||
-function inspect(obj, opts) {
|
||||
- // default options
|
||||
- var ctx = {
|
||||
- seen: [],
|
||||
- stylize: stylizeNoColor
|
||||
- };
|
||||
- // legacy...
|
||||
- if (arguments.length >= 3) ctx.depth = arguments[2];
|
||||
- if (arguments.length >= 4) ctx.colors = arguments[3];
|
||||
- if (isBoolean(opts)) {
|
||||
- // legacy...
|
||||
- ctx.showHidden = opts;
|
||||
- } else if (opts) {
|
||||
- // got an "options" object
|
||||
- exports._extend(ctx, opts);
|
||||
- }
|
||||
- // set default options
|
||||
- if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
||||
- if (isUndefined(ctx.depth)) ctx.depth = 2;
|
||||
- if (isUndefined(ctx.colors)) ctx.colors = false;
|
||||
- if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
||||
- if (ctx.colors) ctx.stylize = stylizeWithColor;
|
||||
- return formatValue(ctx, obj, ctx.depth);
|
||||
-}
|
||||
-exports.inspect = inspect;
|
||||
-
|
||||
-
|
||||
-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||
-inspect.colors = {
|
||||
- 'bold' : [1, 22],
|
||||
- 'italic' : [3, 23],
|
||||
- 'underline' : [4, 24],
|
||||
- 'inverse' : [7, 27],
|
||||
- 'white' : [37, 39],
|
||||
- 'grey' : [90, 39],
|
||||
- 'black' : [30, 39],
|
||||
- 'blue' : [34, 39],
|
||||
- 'cyan' : [36, 39],
|
||||
- 'green' : [32, 39],
|
||||
- 'magenta' : [35, 39],
|
||||
- 'red' : [31, 39],
|
||||
- 'yellow' : [33, 39]
|
||||
-};
|
||||
-
|
||||
-// Don't use 'blue' not visible on cmd.exe
|
||||
-inspect.styles = {
|
||||
- 'special': 'cyan',
|
||||
- 'number': 'yellow',
|
||||
- 'boolean': 'yellow',
|
||||
- 'undefined': 'grey',
|
||||
- 'null': 'bold',
|
||||
- 'string': 'green',
|
||||
- 'date': 'magenta',
|
||||
- // "name": intentionally not styling
|
||||
- 'regexp': 'red'
|
||||
-};
|
||||
-
|
||||
-
|
||||
-function stylizeWithColor(str, styleType) {
|
||||
- var style = inspect.styles[styleType];
|
||||
-
|
||||
- if (style) {
|
||||
- return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
||||
- '\u001b[' + inspect.colors[style][1] + 'm';
|
||||
- } else {
|
||||
- return str;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function stylizeNoColor(str, styleType) {
|
||||
- return str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function arrayToHash(array) {
|
||||
- var hash = {};
|
||||
-
|
||||
- array.forEach(function(val, idx) {
|
||||
- hash[val] = true;
|
||||
- });
|
||||
-
|
||||
- return hash;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatValue(ctx, value, recurseTimes) {
|
||||
- // Provide a hook for user-specified inspect functions.
|
||||
- // Check that value is an object with an inspect function on it
|
||||
- if (ctx.customInspect &&
|
||||
- value &&
|
||||
- isFunction(value.inspect) &&
|
||||
- // Filter out the util module, it's inspect function is special
|
||||
- value.inspect !== exports.inspect &&
|
||||
- // Also filter out any prototype objects using the circular check.
|
||||
- !(value.constructor && value.constructor.prototype === value)) {
|
||||
- var ret = value.inspect(recurseTimes, ctx);
|
||||
- if (!isString(ret)) {
|
||||
- ret = formatValue(ctx, ret, recurseTimes);
|
||||
- }
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- // Primitive types cannot have properties
|
||||
- var primitive = formatPrimitive(ctx, value);
|
||||
- if (primitive) {
|
||||
- return primitive;
|
||||
- }
|
||||
-
|
||||
- // Look up the keys of the object.
|
||||
- var keys = Object.keys(value);
|
||||
- var visibleKeys = arrayToHash(keys);
|
||||
-
|
||||
- if (ctx.showHidden) {
|
||||
- keys = Object.getOwnPropertyNames(value);
|
||||
- }
|
||||
-
|
||||
- // Some type of object without properties can be shortcutted.
|
||||
- if (keys.length === 0) {
|
||||
- if (isFunction(value)) {
|
||||
- var name = value.name ? ': ' + value.name : '';
|
||||
- return ctx.stylize('[Function' + name + ']', 'special');
|
||||
- }
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- }
|
||||
- if (isDate(value)) {
|
||||
- return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
||||
- }
|
||||
- if (isError(value)) {
|
||||
- return formatError(value);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- var base = '', array = false, braces = ['{', '}'];
|
||||
-
|
||||
- // Make Array say that they are Array
|
||||
- if (isArray(value)) {
|
||||
- array = true;
|
||||
- braces = ['[', ']'];
|
||||
- }
|
||||
-
|
||||
- // Make functions say that they are functions
|
||||
- if (isFunction(value)) {
|
||||
- var n = value.name ? ': ' + value.name : '';
|
||||
- base = ' [Function' + n + ']';
|
||||
- }
|
||||
-
|
||||
- // Make RegExps say that they are RegExps
|
||||
- if (isRegExp(value)) {
|
||||
- base = ' ' + RegExp.prototype.toString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make dates with properties first say the date
|
||||
- if (isDate(value)) {
|
||||
- base = ' ' + Date.prototype.toUTCString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make error with message first say the error
|
||||
- if (isError(value)) {
|
||||
- base = ' ' + formatError(value);
|
||||
- }
|
||||
-
|
||||
- if (keys.length === 0 && (!array || value.length == 0)) {
|
||||
- return braces[0] + base + braces[1];
|
||||
- }
|
||||
-
|
||||
- if (recurseTimes < 0) {
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- } else {
|
||||
- return ctx.stylize('[Object]', 'special');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ctx.seen.push(value);
|
||||
-
|
||||
- var output;
|
||||
- if (array) {
|
||||
- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||||
- } else {
|
||||
- output = keys.map(function(key) {
|
||||
- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- ctx.seen.pop();
|
||||
-
|
||||
- return reduceToSingleString(output, base, braces);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatPrimitive(ctx, value) {
|
||||
- if (isUndefined(value))
|
||||
- return ctx.stylize('undefined', 'undefined');
|
||||
- if (isString(value)) {
|
||||
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||||
- .replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"') + '\'';
|
||||
- return ctx.stylize(simple, 'string');
|
||||
- }
|
||||
- if (isNumber(value)) {
|
||||
- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
|
||||
- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
|
||||
- if (value === 0 && 1 / value < 0)
|
||||
- return ctx.stylize('-0', 'number');
|
||||
- return ctx.stylize('' + value, 'number');
|
||||
- }
|
||||
- if (isBoolean(value))
|
||||
- return ctx.stylize('' + value, 'boolean');
|
||||
- // For some reason typeof null is "object", so special case here.
|
||||
- if (isNull(value))
|
||||
- return ctx.stylize('null', 'null');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatError(value) {
|
||||
- return '[' + Error.prototype.toString.call(value) + ']';
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||||
- var output = [];
|
||||
- for (var i = 0, l = value.length; i < l; ++i) {
|
||||
- if (hasOwnProperty(value, String(i))) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- String(i), true));
|
||||
- } else {
|
||||
- output.push('');
|
||||
- }
|
||||
- }
|
||||
- keys.forEach(function(key) {
|
||||
- if (!key.match(/^\d+$/)) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- key, true));
|
||||
- }
|
||||
- });
|
||||
- return output;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||||
- var name, str, desc;
|
||||
- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
||||
- if (desc.get) {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Getter/Setter]', 'special');
|
||||
- } else {
|
||||
- str = ctx.stylize('[Getter]', 'special');
|
||||
- }
|
||||
- } else {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Setter]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (!hasOwnProperty(visibleKeys, key)) {
|
||||
- name = '[' + key + ']';
|
||||
- }
|
||||
- if (!str) {
|
||||
- if (ctx.seen.indexOf(desc.value) < 0) {
|
||||
- if (isNull(recurseTimes)) {
|
||||
- str = formatValue(ctx, desc.value, null);
|
||||
- } else {
|
||||
- str = formatValue(ctx, desc.value, recurseTimes - 1);
|
||||
- }
|
||||
- if (str.indexOf('\n') > -1) {
|
||||
- if (array) {
|
||||
- str = str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n').substr(2);
|
||||
- } else {
|
||||
- str = '\n' + str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n');
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
- str = ctx.stylize('[Circular]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (isUndefined(name)) {
|
||||
- if (array && key.match(/^\d+$/)) {
|
||||
- return str;
|
||||
- }
|
||||
- name = JSON.stringify('' + key);
|
||||
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||||
- name = name.substr(1, name.length - 2);
|
||||
- name = ctx.stylize(name, 'name');
|
||||
- } else {
|
||||
- name = name.replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"')
|
||||
- .replace(/(^"|"$)/g, "'");
|
||||
- name = ctx.stylize(name, 'string');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return name + ': ' + str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function reduceToSingleString(output, base, braces) {
|
||||
- var numLinesEst = 0;
|
||||
- var length = output.reduce(function(prev, cur) {
|
||||
- numLinesEst++;
|
||||
- if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||||
- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
||||
- }, 0);
|
||||
-
|
||||
- if (length > 60) {
|
||||
- return braces[0] +
|
||||
- (base === '' ? '' : base + '\n ') +
|
||||
- ' ' +
|
||||
- output.join(',\n ') +
|
||||
- ' ' +
|
||||
- braces[1];
|
||||
- }
|
||||
-
|
||||
- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||||
-}
|
||||
-
|
||||
-
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
function isArray(ar) {
|
||||
@@ -522,166 +98,10 @@ function isPrimitive(arg) {
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
function isBuffer(arg) {
|
||||
- return arg instanceof Buffer;
|
||||
+ return Buffer.isBuffer(arg);
|
||||
}
|
||||
exports.isBuffer = isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function pad(n) {
|
||||
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||||
- 'Oct', 'Nov', 'Dec'];
|
||||
-
|
||||
-// 26 Feb 16:19:34
|
||||
-function timestamp() {
|
||||
- var d = new Date();
|
||||
- var time = [pad(d.getHours()),
|
||||
- pad(d.getMinutes()),
|
||||
- pad(d.getSeconds())].join(':');
|
||||
- return [d.getDate(), months[d.getMonth()], time].join(' ');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// log is just a thin wrapper to console.log that prepends a timestamp
|
||||
-exports.log = function() {
|
||||
- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Inherit the prototype methods from one constructor into another.
|
||||
- *
|
||||
- * The Function.prototype.inherits from lang.js rewritten as a standalone
|
||||
- * function (not on Function.prototype). NOTE: If this file is to be loaded
|
||||
- * during bootstrapping this function needs to be rewritten using some native
|
||||
- * functions as prototype setup using normal JavaScript does not work as
|
||||
- * expected during bootstrapping (see mirror.js in r114903).
|
||||
- *
|
||||
- * @param {function} ctor Constructor function which needs to inherit the
|
||||
- * prototype.
|
||||
- * @param {function} superCtor Constructor function to inherit prototype from.
|
||||
- */
|
||||
-exports.inherits = function(ctor, superCtor) {
|
||||
- ctor.super_ = superCtor;
|
||||
- ctor.prototype = Object.create(superCtor.prototype, {
|
||||
- constructor: {
|
||||
- value: ctor,
|
||||
- enumerable: false,
|
||||
- writable: true,
|
||||
- configurable: true
|
||||
- }
|
||||
- });
|
||||
-};
|
||||
-
|
||||
-exports._extend = function(origin, add) {
|
||||
- // Don't do anything if add isn't an object
|
||||
- if (!add || !isObject(add)) return origin;
|
||||
-
|
||||
- var keys = Object.keys(add);
|
||||
- var i = keys.length;
|
||||
- while (i--) {
|
||||
- origin[keys[i]] = add[keys[i]];
|
||||
- }
|
||||
- return origin;
|
||||
-};
|
||||
-
|
||||
-function hasOwnProperty(obj, prop) {
|
||||
- return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// Deprecated old stuff.
|
||||
-
|
||||
-exports.p = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- console.error(exports.inspect(arguments[i]));
|
||||
- }
|
||||
-}, 'util.p: Use console.error() instead');
|
||||
-
|
||||
-
|
||||
-exports.exec = exports.deprecate(function() {
|
||||
- return require('child_process').exec.apply(this, arguments);
|
||||
-}, 'util.exec is now called `child_process.exec`.');
|
||||
-
|
||||
-
|
||||
-exports.print = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(String(arguments[i]));
|
||||
- }
|
||||
-}, 'util.print: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.puts = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.puts: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.debug = exports.deprecate(function(x) {
|
||||
- process.stderr.write('DEBUG: ' + x + '\n');
|
||||
-}, 'util.debug: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.error = exports.deprecate(function(x) {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stderr.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.error: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.pump = exports.deprecate(function(readStream, writeStream, callback) {
|
||||
- var callbackCalled = false;
|
||||
-
|
||||
- function call(a, b, c) {
|
||||
- if (callback && !callbackCalled) {
|
||||
- callback(a, b, c);
|
||||
- callbackCalled = true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- readStream.addListener('data', function(chunk) {
|
||||
- if (writeStream.write(chunk) === false) readStream.pause();
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('drain', function() {
|
||||
- readStream.resume();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('end', function() {
|
||||
- writeStream.end();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('close', function() {
|
||||
- call();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('error', function(err) {
|
||||
- writeStream.end();
|
||||
- call(err);
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('error', function(err) {
|
||||
- readStream.destroy();
|
||||
- call(err);
|
||||
- });
|
||||
-}, 'util.pump(): Use readableStream.pipe() instead');
|
||||
-
|
||||
-
|
||||
-var uv;
|
||||
-exports._errnoException = function(err, syscall) {
|
||||
- if (isUndefined(uv)) uv = process.binding('uv');
|
||||
- var errname = uv.errname(err);
|
||||
- var e = new Error(syscall + ' ' + errname);
|
||||
- e.code = errname;
|
||||
- e.errno = errname;
|
||||
- e.syscall = syscall;
|
||||
- return e;
|
||||
-};
|
||||
+}
|
||||
Generated
Vendored
-107
@@ -1,107 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
|
||||
function isArray(arg) {
|
||||
if (Array.isArray) {
|
||||
return Array.isArray(arg);
|
||||
}
|
||||
return objectToString(arg) === '[object Array]';
|
||||
}
|
||||
exports.isArray = isArray;
|
||||
|
||||
function isBoolean(arg) {
|
||||
return typeof arg === 'boolean';
|
||||
}
|
||||
exports.isBoolean = isBoolean;
|
||||
|
||||
function isNull(arg) {
|
||||
return arg === null;
|
||||
}
|
||||
exports.isNull = isNull;
|
||||
|
||||
function isNullOrUndefined(arg) {
|
||||
return arg == null;
|
||||
}
|
||||
exports.isNullOrUndefined = isNullOrUndefined;
|
||||
|
||||
function isNumber(arg) {
|
||||
return typeof arg === 'number';
|
||||
}
|
||||
exports.isNumber = isNumber;
|
||||
|
||||
function isString(arg) {
|
||||
return typeof arg === 'string';
|
||||
}
|
||||
exports.isString = isString;
|
||||
|
||||
function isSymbol(arg) {
|
||||
return typeof arg === 'symbol';
|
||||
}
|
||||
exports.isSymbol = isSymbol;
|
||||
|
||||
function isUndefined(arg) {
|
||||
return arg === void 0;
|
||||
}
|
||||
exports.isUndefined = isUndefined;
|
||||
|
||||
function isRegExp(re) {
|
||||
return objectToString(re) === '[object RegExp]';
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
function isObject(arg) {
|
||||
return typeof arg === 'object' && arg !== null;
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
|
||||
function isDate(d) {
|
||||
return objectToString(d) === '[object Date]';
|
||||
}
|
||||
exports.isDate = isDate;
|
||||
|
||||
function isError(e) {
|
||||
return (objectToString(e) === '[object Error]' || e instanceof Error);
|
||||
}
|
||||
exports.isError = isError;
|
||||
|
||||
function isFunction(arg) {
|
||||
return typeof arg === 'function';
|
||||
}
|
||||
exports.isFunction = isFunction;
|
||||
|
||||
function isPrimitive(arg) {
|
||||
return arg === null ||
|
||||
typeof arg === 'boolean' ||
|
||||
typeof arg === 'number' ||
|
||||
typeof arg === 'string' ||
|
||||
typeof arg === 'symbol' || // ES6 symbol
|
||||
typeof arg === 'undefined';
|
||||
}
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
exports.isBuffer = Buffer.isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
Generated
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "core-util-is",
|
||||
"version": "1.0.2",
|
||||
"description": "The `util.is*` functions introduced in Node v0.12.",
|
||||
"main": "lib/util.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/core-util-is"
|
||||
},
|
||||
"keywords": [
|
||||
"util",
|
||||
"isBuffer",
|
||||
"isArray",
|
||||
"isNumber",
|
||||
"isString",
|
||||
"isRegExp",
|
||||
"isThis",
|
||||
"isThat",
|
||||
"polyfill"
|
||||
],
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/core-util-is/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^2.3.0"
|
||||
}
|
||||
|
||||
,"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||
,"_integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
,"_from": "core-util-is@1.0.2"
|
||||
}
|
||||
Generated
Vendored
-68
@@ -1,68 +0,0 @@
|
||||
var assert = require('tap');
|
||||
|
||||
var t = require('./lib/util');
|
||||
|
||||
assert.equal(t.isArray([]), true);
|
||||
assert.equal(t.isArray({}), false);
|
||||
|
||||
assert.equal(t.isBoolean(null), false);
|
||||
assert.equal(t.isBoolean(true), true);
|
||||
assert.equal(t.isBoolean(false), true);
|
||||
|
||||
assert.equal(t.isNull(null), true);
|
||||
assert.equal(t.isNull(undefined), false);
|
||||
assert.equal(t.isNull(false), false);
|
||||
assert.equal(t.isNull(), false);
|
||||
|
||||
assert.equal(t.isNullOrUndefined(null), true);
|
||||
assert.equal(t.isNullOrUndefined(undefined), true);
|
||||
assert.equal(t.isNullOrUndefined(false), false);
|
||||
assert.equal(t.isNullOrUndefined(), true);
|
||||
|
||||
assert.equal(t.isNumber(null), false);
|
||||
assert.equal(t.isNumber('1'), false);
|
||||
assert.equal(t.isNumber(1), true);
|
||||
|
||||
assert.equal(t.isString(null), false);
|
||||
assert.equal(t.isString('1'), true);
|
||||
assert.equal(t.isString(1), false);
|
||||
|
||||
assert.equal(t.isSymbol(null), false);
|
||||
assert.equal(t.isSymbol('1'), false);
|
||||
assert.equal(t.isSymbol(1), false);
|
||||
assert.equal(t.isSymbol(Symbol()), true);
|
||||
|
||||
assert.equal(t.isUndefined(null), false);
|
||||
assert.equal(t.isUndefined(undefined), true);
|
||||
assert.equal(t.isUndefined(false), false);
|
||||
assert.equal(t.isUndefined(), true);
|
||||
|
||||
assert.equal(t.isRegExp(null), false);
|
||||
assert.equal(t.isRegExp('1'), false);
|
||||
assert.equal(t.isRegExp(new RegExp()), true);
|
||||
|
||||
assert.equal(t.isObject({}), true);
|
||||
assert.equal(t.isObject([]), true);
|
||||
assert.equal(t.isObject(new RegExp()), true);
|
||||
assert.equal(t.isObject(new Date()), true);
|
||||
|
||||
assert.equal(t.isDate(null), false);
|
||||
assert.equal(t.isDate('1'), false);
|
||||
assert.equal(t.isDate(new Date()), true);
|
||||
|
||||
assert.equal(t.isError(null), false);
|
||||
assert.equal(t.isError({ err: true }), false);
|
||||
assert.equal(t.isError(new Error()), true);
|
||||
|
||||
assert.equal(t.isFunction(null), false);
|
||||
assert.equal(t.isFunction({ }), false);
|
||||
assert.equal(t.isFunction(function() {}), true);
|
||||
|
||||
assert.equal(t.isPrimitive(null), true);
|
||||
assert.equal(t.isPrimitive(''), true);
|
||||
assert.equal(t.isPrimitive(0), true);
|
||||
assert.equal(t.isPrimitive(new Date()), false);
|
||||
|
||||
assert.equal(t.isBuffer(null), false);
|
||||
assert.equal(t.isBuffer({}), false);
|
||||
assert.equal(t.isBuffer(new Buffer(0)), true);
|
||||
Loaded 100 of 590 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user