add iterator
This commit is contained in:
Родитель
338a4ffa92
Коммит
20b5c81db5
|
@ -102,3 +102,8 @@ dist
|
|||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Rush files
|
||||
common/temp/**
|
||||
package-deps.json
|
||||
.rush
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,67 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See the @microsoft/rush package's LICENSE file for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
|
||||
//
|
||||
// This script is intended for usage in an automated build environment where the Rush command may not have
|
||||
// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
|
||||
// specified in the rush.json configuration file (if not already installed), and then pass a command-line to it.
|
||||
// An example usage would be:
|
||||
//
|
||||
// node common/scripts/install-run-rush.js install
|
||||
//
|
||||
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const install_run_1 = require("./install-run");
|
||||
const PACKAGE_NAME = '@microsoft/rush';
|
||||
const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION';
|
||||
function _getRushVersion() {
|
||||
const rushPreviewVersion = process.env[RUSH_PREVIEW_VERSION];
|
||||
if (rushPreviewVersion !== undefined) {
|
||||
console.log(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`);
|
||||
return rushPreviewVersion;
|
||||
}
|
||||
const rushJsonFolder = install_run_1.findRushJsonFolder();
|
||||
const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME);
|
||||
try {
|
||||
const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8');
|
||||
// Use a regular expression to parse out the rushVersion value because rush.json supports comments,
|
||||
// but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script.
|
||||
const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/);
|
||||
return rushJsonMatches[1];
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` +
|
||||
"The 'rushVersion' field is either not assigned in rush.json or was specified " +
|
||||
'using an unexpected syntax.');
|
||||
}
|
||||
}
|
||||
function _run() {
|
||||
const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv;
|
||||
// Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the
|
||||
// appropriate binary inside the rush package to run
|
||||
const scriptName = path.basename(scriptPath);
|
||||
const bin = scriptName.toLowerCase() === 'install-run-rushx.js' ? 'rushx' : 'rush';
|
||||
if (!nodePath || !scriptPath) {
|
||||
throw new Error('Unexpected exception: could not detect node path or script path');
|
||||
}
|
||||
if (process.argv.length < 3) {
|
||||
console.log(`Usage: ${scriptName} <command> [args...]`);
|
||||
if (scriptName === 'install-run-rush.js') {
|
||||
console.log(`Example: ${scriptName} build --to myproject`);
|
||||
}
|
||||
else {
|
||||
console.log(`Example: ${scriptName} custom-command`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
install_run_1.runWithErrorAndStatusCode(() => {
|
||||
const version = _getRushVersion();
|
||||
console.log(`The rush.json configuration requests Rush version ${version}`);
|
||||
return install_run_1.installAndRun(PACKAGE_NAME, version, bin, packageBinArgs);
|
||||
});
|
||||
}
|
||||
_run();
|
||||
//# sourceMappingURL=install-run-rush.js.map
|
|
@ -0,0 +1,18 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See the @microsoft/rush package's LICENSE file for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
|
||||
//
|
||||
// This script is intended for usage in an automated build environment where the Rush command may not have
|
||||
// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
|
||||
// specified in the rush.json configuration file (if not already installed), and then pass a command-line to the
|
||||
// rushx command.
|
||||
//
|
||||
// An example usage would be:
|
||||
//
|
||||
// node common/scripts/install-run-rushx.js custom-command
|
||||
//
|
||||
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
|
||||
require("./install-run-rush");
|
||||
//# sourceMappingURL=install-run-rushx.js.map
|
|
@ -0,0 +1,451 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See the @microsoft/rush package's LICENSE file for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
|
||||
//
|
||||
// This script is intended for usage in an automated build environment where a Node tool may not have
|
||||
// been preinstalled, or may have an unpredictable version. This script will automatically install the specified
|
||||
// version of the specified tool (if not already installed), and then pass a command-line to it.
|
||||
// An example usage would be:
|
||||
//
|
||||
// node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io
|
||||
//
|
||||
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
|
||||
const childProcess = require("child_process");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
exports.RUSH_JSON_FILENAME = 'rush.json';
|
||||
const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER';
|
||||
const INSTALLED_FLAG_FILENAME = 'installed.flag';
|
||||
const NODE_MODULES_FOLDER_NAME = 'node_modules';
|
||||
const PACKAGE_JSON_FILENAME = 'package.json';
|
||||
/**
|
||||
* Parse a package specifier (in the form of name\@version) into name and version parts.
|
||||
*/
|
||||
function _parsePackageSpecifier(rawPackageSpecifier) {
|
||||
rawPackageSpecifier = (rawPackageSpecifier || '').trim();
|
||||
const separatorIndex = rawPackageSpecifier.lastIndexOf('@');
|
||||
let name;
|
||||
let version = undefined;
|
||||
if (separatorIndex === 0) {
|
||||
// The specifier starts with a scope and doesn't have a version specified
|
||||
name = rawPackageSpecifier;
|
||||
}
|
||||
else if (separatorIndex === -1) {
|
||||
// The specifier doesn't have a version
|
||||
name = rawPackageSpecifier;
|
||||
}
|
||||
else {
|
||||
name = rawPackageSpecifier.substring(0, separatorIndex);
|
||||
version = rawPackageSpecifier.substring(separatorIndex + 1);
|
||||
}
|
||||
if (!name) {
|
||||
throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`);
|
||||
}
|
||||
return { name, version };
|
||||
}
|
||||
/**
|
||||
* As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims
|
||||
* unusable lines from the .npmrc file.
|
||||
*
|
||||
* Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in
|
||||
* the .npmrc file to provide different authentication tokens for different registry.
|
||||
* However, if the environment variable is undefined, it expands to an empty string, which
|
||||
* produces a valid-looking mapping with an invalid URL that causes an error. Instead,
|
||||
* we'd prefer to skip that line and continue looking in other places such as the user's
|
||||
* home directory.
|
||||
*
|
||||
* IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities.copyAndTrimNpmrcFile()
|
||||
*/
|
||||
function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) {
|
||||
console.log(`Copying ${sourceNpmrcPath} --> ${targetNpmrcPath}`); // Verbose
|
||||
let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n');
|
||||
npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim());
|
||||
const resultLines = [];
|
||||
// This finds environment variable tokens that look like "${VAR_NAME}"
|
||||
const expansionRegExp = /\$\{([^\}]+)\}/g;
|
||||
// Comment lines start with "#" or ";"
|
||||
const commentRegExp = /^\s*[#;]/;
|
||||
// Trim out lines that reference environment variables that aren't defined
|
||||
for (const line of npmrcFileLines) {
|
||||
let lineShouldBeTrimmed = false;
|
||||
// Ignore comment lines
|
||||
if (!commentRegExp.test(line)) {
|
||||
const environmentVariables = line.match(expansionRegExp);
|
||||
if (environmentVariables) {
|
||||
for (const token of environmentVariables) {
|
||||
// Remove the leading "${" and the trailing "}" from the token
|
||||
const environmentVariableName = token.substring(2, token.length - 1);
|
||||
// Is the environment variable defined?
|
||||
if (!process.env[environmentVariableName]) {
|
||||
// No, so trim this line
|
||||
lineShouldBeTrimmed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineShouldBeTrimmed) {
|
||||
// Example output:
|
||||
// "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}"
|
||||
resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line);
|
||||
}
|
||||
else {
|
||||
resultLines.push(line);
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL));
|
||||
}
|
||||
/**
|
||||
* syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file.
|
||||
* If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder.
|
||||
*
|
||||
* IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc()
|
||||
*/
|
||||
function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish) {
|
||||
const sourceNpmrcPath = path.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish');
|
||||
const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc');
|
||||
try {
|
||||
if (fs.existsSync(sourceNpmrcPath)) {
|
||||
_copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath);
|
||||
}
|
||||
else if (fs.existsSync(targetNpmrcPath)) {
|
||||
// If the source .npmrc doesn't exist and there is one in the target, delete the one in the target
|
||||
console.log(`Deleting ${targetNpmrcPath}`); // Verbose
|
||||
fs.unlinkSync(targetNpmrcPath);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Error syncing .npmrc file: ${e}`);
|
||||
}
|
||||
}
|
||||
let _npmPath = undefined;
|
||||
/**
|
||||
* Get the absolute path to the npm executable
|
||||
*/
|
||||
function getNpmPath() {
|
||||
if (!_npmPath) {
|
||||
try {
|
||||
if (os.platform() === 'win32') {
|
||||
// We're on Windows
|
||||
const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString();
|
||||
const lines = whereOutput.split(os.EOL).filter((line) => !!line);
|
||||
// take the last result, we are looking for a .cmd command
|
||||
// see https://github.com/microsoft/rushstack/issues/759
|
||||
_npmPath = lines[lines.length - 1];
|
||||
}
|
||||
else {
|
||||
// We aren't on Windows - assume we're on *NIX or Darwin
|
||||
_npmPath = childProcess.execSync('command -v npm', { stdio: [] }).toString();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to determine the path to the NPM tool: ${e}`);
|
||||
}
|
||||
_npmPath = _npmPath.trim();
|
||||
if (!fs.existsSync(_npmPath)) {
|
||||
throw new Error('The NPM executable does not exist');
|
||||
}
|
||||
}
|
||||
return _npmPath;
|
||||
}
|
||||
exports.getNpmPath = getNpmPath;
|
||||
function _ensureFolder(folderPath) {
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
const parentDir = path.dirname(folderPath);
|
||||
_ensureFolder(parentDir);
|
||||
fs.mkdirSync(folderPath);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create missing directories under the specified base directory, and return the resolved directory.
|
||||
*
|
||||
* Does not support "." or ".." path segments.
|
||||
* Assumes the baseFolder exists.
|
||||
*/
|
||||
function _ensureAndJoinPath(baseFolder, ...pathSegments) {
|
||||
let joinedPath = baseFolder;
|
||||
try {
|
||||
for (let pathSegment of pathSegments) {
|
||||
pathSegment = pathSegment.replace(/[\\\/]/g, '+');
|
||||
joinedPath = path.join(joinedPath, pathSegment);
|
||||
if (!fs.existsSync(joinedPath)) {
|
||||
fs.mkdirSync(joinedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`);
|
||||
}
|
||||
return joinedPath;
|
||||
}
|
||||
function _getRushTempFolder(rushCommonFolder) {
|
||||
const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME];
|
||||
if (rushTempFolder !== undefined) {
|
||||
_ensureFolder(rushTempFolder);
|
||||
return rushTempFolder;
|
||||
}
|
||||
else {
|
||||
return _ensureAndJoinPath(rushCommonFolder, 'temp');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Resolve a package specifier to a static version
|
||||
*/
|
||||
function _resolvePackageVersion(rushCommonFolder, { name, version }) {
|
||||
if (!version) {
|
||||
version = '*'; // If no version is specified, use the latest version
|
||||
}
|
||||
if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) {
|
||||
// If the version contains only characters that we recognize to be used in static version specifiers,
|
||||
// pass the version through
|
||||
return version;
|
||||
}
|
||||
else {
|
||||
// version resolves to
|
||||
try {
|
||||
const rushTempFolder = _getRushTempFolder(rushCommonFolder);
|
||||
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
|
||||
_syncNpmrc(sourceNpmrcFolder, rushTempFolder);
|
||||
const npmPath = getNpmPath();
|
||||
// This returns something that looks like:
|
||||
// @microsoft/rush@3.0.0 '3.0.0'
|
||||
// @microsoft/rush@3.0.1 '3.0.1'
|
||||
// ...
|
||||
// @microsoft/rush@3.0.20 '3.0.20'
|
||||
// <blank line>
|
||||
const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], {
|
||||
cwd: rushTempFolder,
|
||||
stdio: []
|
||||
});
|
||||
if (npmVersionSpawnResult.status !== 0) {
|
||||
throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`);
|
||||
}
|
||||
const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString();
|
||||
const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line);
|
||||
const latestVersion = versionLines[versionLines.length - 1];
|
||||
if (!latestVersion) {
|
||||
throw new Error('No versions found for the specified version range.');
|
||||
}
|
||||
const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/);
|
||||
if (!versionMatches) {
|
||||
throw new Error(`Invalid npm output ${latestVersion}`);
|
||||
}
|
||||
return versionMatches[1];
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
let _rushJsonFolder;
|
||||
/**
|
||||
* Find the absolute path to the folder containing rush.json
|
||||
*/
|
||||
function findRushJsonFolder() {
|
||||
if (!_rushJsonFolder) {
|
||||
let basePath = __dirname;
|
||||
let tempPath = __dirname;
|
||||
do {
|
||||
const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME);
|
||||
if (fs.existsSync(testRushJsonPath)) {
|
||||
_rushJsonFolder = basePath;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
basePath = tempPath;
|
||||
}
|
||||
} while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root
|
||||
if (!_rushJsonFolder) {
|
||||
throw new Error('Unable to find rush.json.');
|
||||
}
|
||||
}
|
||||
return _rushJsonFolder;
|
||||
}
|
||||
exports.findRushJsonFolder = findRushJsonFolder;
|
||||
/**
|
||||
* Detects if the package in the specified directory is installed
|
||||
*/
|
||||
function _isPackageAlreadyInstalled(packageInstallFolder) {
|
||||
try {
|
||||
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
|
||||
if (!fs.existsSync(flagFilePath)) {
|
||||
return false;
|
||||
}
|
||||
const fileContents = fs.readFileSync(flagFilePath).toString();
|
||||
return fileContents.trim() === process.version;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Removes the following files and directories under the specified folder path:
|
||||
* - installed.flag
|
||||
* -
|
||||
* - node_modules
|
||||
*/
|
||||
function _cleanInstallFolder(rushTempFolder, packageInstallFolder) {
|
||||
try {
|
||||
const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME);
|
||||
if (fs.existsSync(flagFile)) {
|
||||
fs.unlinkSync(flagFile);
|
||||
}
|
||||
const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json');
|
||||
if (fs.existsSync(packageLockFile)) {
|
||||
fs.unlinkSync(packageLockFile);
|
||||
}
|
||||
const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME);
|
||||
if (fs.existsSync(nodeModulesFolder)) {
|
||||
const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler');
|
||||
fs.renameSync(nodeModulesFolder, path.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`));
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`);
|
||||
}
|
||||
}
|
||||
function _createPackageJson(packageInstallFolder, name, version) {
|
||||
try {
|
||||
const packageJsonContents = {
|
||||
name: 'ci-rush',
|
||||
version: '0.0.0',
|
||||
dependencies: {
|
||||
[name]: version
|
||||
},
|
||||
description: "DON'T WARN",
|
||||
repository: "DON'T WARN",
|
||||
license: 'MIT'
|
||||
};
|
||||
const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME);
|
||||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2));
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to create package.json: ${e}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Run "npm install" in the package install folder.
|
||||
*/
|
||||
function _installPackage(packageInstallFolder, name, version) {
|
||||
try {
|
||||
console.log(`Installing ${name}...`);
|
||||
const npmPath = getNpmPath();
|
||||
const result = childProcess.spawnSync(npmPath, ['install'], {
|
||||
stdio: 'inherit',
|
||||
cwd: packageInstallFolder,
|
||||
env: process.env
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
throw new Error('"npm install" encountered an error');
|
||||
}
|
||||
console.log(`Successfully installed ${name}@${version}`);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to install package: ${e}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the ".bin" path for the package.
|
||||
*/
|
||||
function _getBinPath(packageInstallFolder, binName) {
|
||||
const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
|
||||
const resolvedBinName = os.platform() === 'win32' ? `${binName}.cmd` : binName;
|
||||
return path.resolve(binFolderPath, resolvedBinName);
|
||||
}
|
||||
/**
|
||||
* Write a flag file to the package's install directory, signifying that the install was successful.
|
||||
*/
|
||||
function _writeFlagFile(packageInstallFolder) {
|
||||
try {
|
||||
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
|
||||
fs.writeFileSync(flagFilePath, process.version);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`);
|
||||
}
|
||||
}
|
||||
function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) {
|
||||
const rushJsonFolder = findRushJsonFolder();
|
||||
const rushCommonFolder = path.join(rushJsonFolder, 'common');
|
||||
const rushTempFolder = _getRushTempFolder(rushCommonFolder);
|
||||
const packageInstallFolder = _ensureAndJoinPath(rushTempFolder, 'install-run', `${packageName}@${packageVersion}`);
|
||||
if (!_isPackageAlreadyInstalled(packageInstallFolder)) {
|
||||
// The package isn't already installed
|
||||
_cleanInstallFolder(rushTempFolder, packageInstallFolder);
|
||||
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
|
||||
_syncNpmrc(sourceNpmrcFolder, packageInstallFolder);
|
||||
_createPackageJson(packageInstallFolder, packageName, packageVersion);
|
||||
_installPackage(packageInstallFolder, packageName, packageVersion);
|
||||
_writeFlagFile(packageInstallFolder);
|
||||
}
|
||||
const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`;
|
||||
const statusMessageLine = new Array(statusMessage.length + 1).join('-');
|
||||
console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL);
|
||||
const binPath = _getBinPath(packageInstallFolder, packageBinName);
|
||||
const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
|
||||
// Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to
|
||||
// assign via the process.env proxy to ensure that we append to the right PATH key.
|
||||
const originalEnvPath = process.env.PATH || '';
|
||||
let result;
|
||||
try {
|
||||
process.env.PATH = [binFolderPath, originalEnvPath].join(path.delimiter);
|
||||
result = childProcess.spawnSync(binPath, packageBinArgs, {
|
||||
stdio: 'inherit',
|
||||
cwd: process.cwd(),
|
||||
env: process.env
|
||||
});
|
||||
}
|
||||
finally {
|
||||
process.env.PATH = originalEnvPath;
|
||||
}
|
||||
if (result.status !== null) {
|
||||
return result.status;
|
||||
}
|
||||
else {
|
||||
throw result.error || new Error('An unknown error occurred.');
|
||||
}
|
||||
}
|
||||
exports.installAndRun = installAndRun;
|
||||
function runWithErrorAndStatusCode(fn) {
|
||||
process.exitCode = 1;
|
||||
try {
|
||||
const exitCode = fn();
|
||||
process.exitCode = exitCode;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL);
|
||||
}
|
||||
}
|
||||
exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode;
|
||||
function _run() {
|
||||
const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv;
|
||||
if (!nodePath) {
|
||||
throw new Error('Unexpected exception: could not detect node path');
|
||||
}
|
||||
if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') {
|
||||
// If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control
|
||||
// to the script that (presumably) imported this file
|
||||
return;
|
||||
}
|
||||
if (process.argv.length < 4) {
|
||||
console.log('Usage: install-run.js <package>@<version> <command> [args...]');
|
||||
console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io');
|
||||
process.exit(1);
|
||||
}
|
||||
runWithErrorAndStatusCode(() => {
|
||||
const rushJsonFolder = findRushJsonFolder();
|
||||
const rushCommonFolder = _ensureAndJoinPath(rushJsonFolder, 'common');
|
||||
const packageSpecifier = _parsePackageSpecifier(rawPackageSpecifier);
|
||||
const name = packageSpecifier.name;
|
||||
const version = _resolvePackageVersion(rushCommonFolder, packageSpecifier);
|
||||
if (packageSpecifier.version !== version) {
|
||||
console.log(`Resolved to ${name}@${version}`);
|
||||
}
|
||||
return installAndRun(name, version, packageBinName, packageBinArgs);
|
||||
});
|
||||
}
|
||||
_run();
|
||||
//# sourceMappingURL=install-run.js.map
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Mocha Tests",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||
"args": [
|
||||
"-u",
|
||||
"tdd",
|
||||
"--timeout",
|
||||
"999999",
|
||||
"--colors",
|
||||
"${workspaceFolder}/dist/test/test.js"
|
||||
],
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"program": "${workspaceFolder}\\index.js",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@ts-common/iterator",
|
||||
"entries": [
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"tag": "@ts-common/iterator_v1.0.0",
|
||||
"date": "Wed, 05 Aug 2020 05:46:49 GMT",
|
||||
"comments": {
|
||||
"patch": [
|
||||
{
|
||||
"comment": "update versions"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# Change Log - @ts-common/iterator
|
||||
|
||||
This log was last generated on Wed, 05 Aug 2020 05:46:49 GMT and should not be manually modified.
|
||||
|
||||
## 1.0.0
|
||||
Wed, 05 Aug 2020 05:46:49 GMT
|
||||
|
||||
### Patches
|
||||
|
||||
- update versions
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
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
|
|
@ -0,0 +1,9 @@
|
|||
# iterator
|
||||
|
||||
[![npm version](https://badge.fury.io/js/%40ts-common%2Fiterator.svg)](https://badge.fury.io/js/%40ts-common%2Fiterator) [![Build Status](https://dev.azure.com/ts-common/ts-common/_apis/build/status/ts-common.iterator)](https://dev.azure.com/ts-common/ts-common/_build/latest?definitionId=3)
|
||||
|
||||
Iterator library for TypeScript and JavaScript
|
||||
|
||||
## fold vs reduce
|
||||
|
||||
https://stackoverflow.com/questions/25158780/difference-between-reduce-and-foldleft-fold-in-functional-programming-particula
|
|
@ -0,0 +1,52 @@
|
|||
# Starter pipeline
|
||||
# Start with a minimal pipeline that you can customize to build and deploy your code.
|
||||
# Add steps that build, run tests, deploy, and more:
|
||||
# https://aka.ms/yaml
|
||||
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
trigger:
|
||||
- master
|
||||
|
||||
steps:
|
||||
|
||||
- task: Npm@1
|
||||
displayName: 'npm install'
|
||||
inputs:
|
||||
verbose: false
|
||||
|
||||
- task: Npm@1
|
||||
displayName: 'npm test'
|
||||
inputs:
|
||||
command: custom
|
||||
verbose: false
|
||||
customCommand: test
|
||||
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFiles: '**/test-results.xml'
|
||||
testRunTitle: 'Test results for JavaScript'
|
||||
|
||||
- task: PublishCodeCoverageResults@1
|
||||
inputs:
|
||||
codeCoverageTool: Cobertura
|
||||
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'
|
||||
reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage'
|
||||
|
||||
- task: Npm@1
|
||||
displayName: 'npm pack'
|
||||
inputs:
|
||||
command: custom
|
||||
verbose: false
|
||||
customCommand: pack
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: drop'
|
||||
inputs:
|
||||
Contents: '*.tgz'
|
||||
TargetFolder: drop
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathtoPublish: $(Build.SourcesDirectory)/drop
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"name": "@openapi-tools-common/iterator",
|
||||
"version": "1.0.0",
|
||||
"description": "Iterator library for JavaScript and TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"tslint": "tslint --project tsconfig.json",
|
||||
"prepack": "npm run build",
|
||||
"test": "tsc && jest"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
"testMatch": [
|
||||
"**/dist/test/*test.js"
|
||||
],
|
||||
"reporters": [
|
||||
"jest-junit",
|
||||
"default"
|
||||
],
|
||||
"collectCoverage": true,
|
||||
"coverageThreshold": {
|
||||
"global": {
|
||||
"branches": 100,
|
||||
"functions": 100,
|
||||
"lines": 100,
|
||||
"statements": 100
|
||||
}
|
||||
},
|
||||
"coveragePathIgnorePatterns": [
|
||||
"/dist/test/"
|
||||
],
|
||||
"coverageReporters": [
|
||||
"cobertura",
|
||||
"text",
|
||||
"html"
|
||||
]
|
||||
},
|
||||
"jest-junit": {
|
||||
"outputDirectory": ".",
|
||||
"outputName": "test-results.xml"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ts-common/iterator.git"
|
||||
},
|
||||
"keywords": [
|
||||
"iterator"
|
||||
],
|
||||
"files": [
|
||||
"dist/index.js",
|
||||
"dist/index.d.ts",
|
||||
"dist/index.d.ts.map",
|
||||
"dist/index.js.map",
|
||||
"src/index.ts"
|
||||
],
|
||||
"author": "Sergey Shandar",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/ts-common/iterator/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ts-common/iterator#readme",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.25",
|
||||
"jest": "^26.1.0",
|
||||
"jest-junit": "^11.0.1",
|
||||
"tslint": "^6.0.0",
|
||||
"tslint-immutable": "^6.0.1",
|
||||
"typescript": "^3.9.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,531 @@
|
|||
export type IterableEx<T> = Iterable<T> & {
|
||||
/**
|
||||
* The function returns an iterator of a this container own enumerable number-keyed value [key, value] pairs.
|
||||
*/
|
||||
readonly entries: () => IterableEx<Entry<T>>;
|
||||
/**
|
||||
* Creates a new sequence whose values are calculated by passing this sequence's elements through the given
|
||||
* function.
|
||||
*/
|
||||
readonly map: <R>(func: (v: T, i: number) => R) => IterableEx<R>;
|
||||
/**
|
||||
* Returns the first element of this sequence or `undefined` if the sequence is empty.
|
||||
*/
|
||||
readonly first: () => T | undefined;
|
||||
/**
|
||||
* The flatMap() method first maps each element using a mapping function, then flattens the result.
|
||||
*/
|
||||
readonly flatMap: <R>(
|
||||
func: (v: T, i: number) => Iterable<R>
|
||||
) => IterableEx<R>;
|
||||
/**
|
||||
* Creates a new sequence whose values are the elements of this sequence which satisfy the specified predicate.
|
||||
*/
|
||||
readonly filter: (func: (v: T, i: number) => boolean) => IterableEx<T>;
|
||||
/**
|
||||
* Creates a new sequence whose values are calculated by passing this sequence's elements through the given
|
||||
* function. If the function `func` returns `undefined`, the item is removed from the sequence.
|
||||
*/
|
||||
readonly filterMap: <R>(
|
||||
func: (v: T, i: number) => R | undefined
|
||||
) => IterableEx<R>;
|
||||
/**
|
||||
* The forEach() method executes a provided function once for each sequence element.
|
||||
*/
|
||||
readonly forEach: (func: (v: T, i: number) => void) => void;
|
||||
/**
|
||||
* Creates a slice of sequence with n elements dropped from the beginning.
|
||||
*/
|
||||
readonly drop: (n?: number) => IterableEx<T>;
|
||||
/**
|
||||
* Creates a new sequence with all of the elements of this one, plus those of the given sequence(s).
|
||||
*/
|
||||
readonly concat: (
|
||||
...input: readonly (Iterable<T> | undefined)[]
|
||||
) => IterableEx<T>;
|
||||
/**
|
||||
* Creates a new sequence comprising the elements from the head of this sequence that satisfy some predicate. Once
|
||||
* an element is encountered that doesn't satisfy the predicate, iteration will stop.
|
||||
*/
|
||||
readonly takeWhile: (func: (v: T, i: number) => boolean) => IterableEx<T>;
|
||||
/**
|
||||
* Creates a slice of sequence with n elements taken from the beginning.
|
||||
*/
|
||||
readonly take: (n?: number) => IterableEx<T>;
|
||||
/**
|
||||
* This method is like find except that it returns the `Entry<T>` of the first element predicate returns truthy for
|
||||
* instead of the element itself. This is useful if the sequence can contain `undefined` values.
|
||||
*/
|
||||
readonly findEntry: (
|
||||
func: (v: T, i: number) => boolean
|
||||
) => Entry<T> | undefined;
|
||||
/**
|
||||
* Searches for the first element in the sequence satisfying a given predicate.
|
||||
*/
|
||||
readonly find: (func: (v: T, i: number) => boolean) => T | undefined;
|
||||
/**
|
||||
* Reduces collection to a value which is the accumulated result of running each element in collection thru
|
||||
* `func`, where each successive invocation is supplied the return value of the previous.
|
||||
*/
|
||||
readonly fold: <A>(func: (a: A, b: T, i: number) => A, init: A) => A;
|
||||
/**
|
||||
* Reduces collection to a value which is the accumulated result of running each element in collection thru
|
||||
* `func`, where each successive invocation is supplied the return value of the previous.
|
||||
*
|
||||
* The first element of collection is used as the initial value.
|
||||
*/
|
||||
readonly reduce: (func: (a: T, b: T, i: number) => T) => T | undefined;
|
||||
/**
|
||||
* Returns the last element of this sequence or `undefined` if the sequence is empty.
|
||||
*/
|
||||
readonly last: () => T | undefined;
|
||||
/**
|
||||
* Checks whether at least one element in this sequence satisfies a given predicate (or, if no predicate is
|
||||
* specified, whether the sequence contains at least one element).
|
||||
*/
|
||||
readonly some: (func?: (v: T, i: number) => boolean) => boolean;
|
||||
/**
|
||||
* Checks whether every element in this sequence satisfies a given predicate.
|
||||
*/
|
||||
readonly every: (func: (v: T, i: number) => boolean) => boolean;
|
||||
/**
|
||||
* Creates a new sequence by combining the elements from this sequence with corresponding elements from the
|
||||
* specified sequence(s).
|
||||
*/
|
||||
readonly zip: (
|
||||
...inputs: readonly (Iterable<T> | undefined)[]
|
||||
) => IterableEx<readonly T[]>;
|
||||
/**
|
||||
* Checks if all items in the sequence are equal to the items in the given sequence `b`.
|
||||
*/
|
||||
readonly isEqual: <B>(
|
||||
b: Iterable<B> | undefined,
|
||||
e?: (ai: T, bi: B) => boolean
|
||||
) => boolean;
|
||||
/**
|
||||
* Creates an array snapshot of a sequence.
|
||||
*/
|
||||
readonly toArray: () => readonly T[];
|
||||
/**
|
||||
* Creates a new array with the same elements as this sequence, but in the opposite order.
|
||||
*/
|
||||
readonly reverse: () => readonly T[];
|
||||
/**
|
||||
* Checks whether the sequence has no elements.
|
||||
*/
|
||||
readonly isEmpty: () => boolean;
|
||||
/**
|
||||
* Creates a new sequence with every unique element from this one appearing exactly once (i.e., with duplicates
|
||||
* removed).
|
||||
*/
|
||||
readonly uniq: (key?: (v: T) => unknown) => IterableEx<T>;
|
||||
/**
|
||||
* Creates a new sequence of accumulated values. It's exclusive scan so it always returns at least one value.
|
||||
*/
|
||||
readonly scan: <A>(
|
||||
func: (a: A, b: T, i: number) => A,
|
||||
init: A
|
||||
) => IterableEx<A>;
|
||||
/**
|
||||
* Firstly, the function maps a state and each element using the `func` function, then flattens the result.
|
||||
*/
|
||||
readonly flatScan: <A, R>(
|
||||
func: (a: A, b: T, i: number) => readonly [A, Iterable<R>],
|
||||
init: A
|
||||
) => IterableEx<R>;
|
||||
};
|
||||
|
||||
export const iterable = <T>(
|
||||
createIterator: () => Iterator<T>
|
||||
): IterableEx<T> => {
|
||||
const it = { [Symbol.iterator]: createIterator };
|
||||
const property = <P extends readonly unknown[], R>(
|
||||
f: (self: Iterable<T>, ...p: P) => R
|
||||
) => (...p: P) => f(it, ...p);
|
||||
return {
|
||||
[Symbol.iterator]: createIterator,
|
||||
concat: property(concat),
|
||||
drop: property(drop),
|
||||
entries: property(entries),
|
||||
every: property(every),
|
||||
filter: property(filter),
|
||||
filterMap: property(filterMap),
|
||||
find: property(find),
|
||||
findEntry: property(findEntry),
|
||||
flatMap: property(flatMap),
|
||||
fold: property(fold),
|
||||
forEach: property(forEach),
|
||||
isEmpty: property(isEmpty),
|
||||
isEqual: property(isEqual),
|
||||
last: property(last),
|
||||
map: property(map),
|
||||
reduce: property(reduce),
|
||||
reverse: property(reverse),
|
||||
some: property(some),
|
||||
take: property(take),
|
||||
takeWhile: property(takeWhile),
|
||||
toArray: property(toArray),
|
||||
uniq: property(uniq),
|
||||
zip: property(zip),
|
||||
scan: property(scan),
|
||||
flatScan: property(flatScan),
|
||||
first: property(first),
|
||||
};
|
||||
};
|
||||
|
||||
export type Entry<T> = readonly [number, T];
|
||||
|
||||
export const ENTRY_KEY = 0;
|
||||
export const ENTRY_VALUE = 1;
|
||||
|
||||
export const chain = <T>(input: readonly T[]): IterableEx<T> =>
|
||||
iterable(() => input[Symbol.iterator]());
|
||||
|
||||
export const entries = <T>(
|
||||
input: Iterable<T> | undefined
|
||||
): IterableEx<Entry<T>> =>
|
||||
iterable(function* () {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (input === undefined) {
|
||||
return;
|
||||
}
|
||||
let index = 0;
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const value of input) {
|
||||
yield [index, value] as const;
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
index += 1;
|
||||
}
|
||||
});
|
||||
|
||||
export const map = <T, I>(
|
||||
input: Iterable<I> | undefined,
|
||||
func: (v: I, i: number) => T
|
||||
): IterableEx<T> =>
|
||||
iterable(function* (): Iterator<T> {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, value] of entries(input)) {
|
||||
yield func(value, index);
|
||||
}
|
||||
});
|
||||
|
||||
export const drop = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
n: number = 1
|
||||
): IterableEx<T> => filter(input, (_, i) => n <= i);
|
||||
|
||||
export const flat = <T>(
|
||||
input: Iterable<Iterable<T> | undefined> | undefined
|
||||
): IterableEx<T> =>
|
||||
iterable(function* (): Iterator<T> {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (input === undefined) {
|
||||
return;
|
||||
}
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const v of input) {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (v !== undefined) {
|
||||
yield* v;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const concat = <T>(
|
||||
...input: readonly (Iterable<T> | undefined)[]
|
||||
): IterableEx<T> => flat(input);
|
||||
|
||||
export const takeWhile = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean
|
||||
): IterableEx<T> =>
|
||||
iterable(function* (): Iterator<T> {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, value] of entries(input)) {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (!func(value, index)) {
|
||||
return;
|
||||
}
|
||||
yield value;
|
||||
}
|
||||
});
|
||||
|
||||
export const take = <T>(input: Iterable<T> | undefined, n: number = 1) =>
|
||||
takeWhile(input, (_, i) => i < n);
|
||||
|
||||
export const findEntry = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean
|
||||
): Entry<T> | undefined => {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const e of entries(input)) {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (func(e[ENTRY_VALUE], e[ENTRY_KEY])) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const find = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean
|
||||
): T | undefined => {
|
||||
const e = findEntry(input, func);
|
||||
return e === undefined ? undefined : e[ENTRY_VALUE];
|
||||
};
|
||||
|
||||
export const flatMap = <T, I>(
|
||||
input: Iterable<I> | undefined,
|
||||
func: (v: I, i: number) => Iterable<T>
|
||||
): IterableEx<T> => flat(map(input, func));
|
||||
|
||||
export const optionalToArray = <T>(v: T | undefined): readonly T[] =>
|
||||
v === undefined ? [] : [v];
|
||||
|
||||
export const filterMap = <T, I>(
|
||||
input: Iterable<I> | undefined,
|
||||
func: (v: I, i: number) => T | undefined
|
||||
): IterableEx<T> => flatMap(input, (v, i) => optionalToArray(func(v, i)));
|
||||
|
||||
export const filter = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean
|
||||
): IterableEx<T> => flatMap(input, (v, i) => (func(v, i) ? [v] : []));
|
||||
|
||||
const infinite = (): IterableEx<void> =>
|
||||
iterable(function* (): Iterator<void> {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
while (true) {
|
||||
yield;
|
||||
}
|
||||
});
|
||||
|
||||
export const generate = <T>(
|
||||
func: (i: number) => T,
|
||||
count?: number
|
||||
): IterableEx<T> =>
|
||||
infinite()
|
||||
.takeWhile((_, i) => i !== count)
|
||||
.map((_, i) => func(i));
|
||||
|
||||
export const repeat = <T>(v: T, count?: number): IterableEx<T> =>
|
||||
generate(() => v, count);
|
||||
|
||||
export const scan = <T, A>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (a: A, b: T, i: number) => A,
|
||||
init: A
|
||||
): IterableEx<A> =>
|
||||
iterable(function* () {
|
||||
let result: A = init;
|
||||
yield result;
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, value] of entries(input)) {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
result = func(result, value, index);
|
||||
yield result;
|
||||
}
|
||||
});
|
||||
|
||||
export const flatScan = <T, A, R>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (a: A, b: T, i: number) => readonly [A, Iterable<R>],
|
||||
init: A
|
||||
): IterableEx<R> =>
|
||||
iterable(function* () {
|
||||
let state = init;
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, value] of entries(input)) {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
const [newState, result] = func(state, value, index);
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
state = newState;
|
||||
yield* result;
|
||||
}
|
||||
});
|
||||
|
||||
export const fold = <T, A>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (a: A, b: T, i: number) => A,
|
||||
init: A
|
||||
): A => {
|
||||
let result: A = init;
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, value] of entries(input)) {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
result = func(result, value, index);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const reduce = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (a: T, b: T, i: number) => T
|
||||
): T | undefined =>
|
||||
fold<T, T | undefined>(
|
||||
input,
|
||||
(a, b, i) => (a !== undefined ? func(a, b, i) : b),
|
||||
undefined
|
||||
);
|
||||
|
||||
export const first = <T>(input: Iterable<T> | undefined): T | undefined => {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (input !== undefined) {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const v of input) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const last = <T>(input: Iterable<T> | undefined): T | undefined =>
|
||||
reduce(input, (_, v) => v);
|
||||
|
||||
export const some = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean = () => true
|
||||
): boolean => findEntry(input, func) !== undefined;
|
||||
|
||||
export const every = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => boolean
|
||||
): boolean => !some(input, (v, i) => !func(v, i));
|
||||
|
||||
export const forEach = <T>(
|
||||
input: Iterable<T> | undefined,
|
||||
func: (v: T, i: number) => void
|
||||
): void => {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
fold<T, void>(
|
||||
input,
|
||||
(_, v, i) => {
|
||||
func(v, i);
|
||||
},
|
||||
undefined
|
||||
);
|
||||
};
|
||||
|
||||
export const sum = (input: Iterable<number> | undefined): number =>
|
||||
fold(input, (a, b) => a + b, 0);
|
||||
|
||||
export const min = (input: Iterable<number> | undefined): number =>
|
||||
fold(input, (a, b) => Math.min(a, b), Infinity);
|
||||
|
||||
export const max = (input: Iterable<number> | undefined): number =>
|
||||
fold(input, (a, b) => Math.max(a, b), -Infinity);
|
||||
|
||||
export const zip = <T>(
|
||||
...inputs: readonly (Iterable<T> | undefined)[]
|
||||
): IterableEx<readonly T[]> =>
|
||||
iterable(function* (): Iterator<readonly T[]> {
|
||||
const iterators = inputs.map((i) =>
|
||||
i === undefined ? [][Symbol.iterator]() : i[Symbol.iterator]()
|
||||
);
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
while (true) {
|
||||
const result = new Array<T>(inputs.length);
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (const [index, it] of entries(iterators)) {
|
||||
const v = it.next();
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (v.done) {
|
||||
return;
|
||||
}
|
||||
// tslint:disable-next-line:no-object-mutation no-expression-statement
|
||||
result[index] = v.value;
|
||||
}
|
||||
yield result;
|
||||
}
|
||||
});
|
||||
|
||||
// TypeScript gives an error in case if type of a and type of b are different
|
||||
export const isStrictEqual = (a: unknown, b: unknown) => a === b;
|
||||
|
||||
export const isEqual = <A, B>(
|
||||
a: Iterable<A> | undefined,
|
||||
b: Iterable<B> | undefined,
|
||||
e: (ai: A, bi: B) => boolean = isStrictEqual
|
||||
): boolean => {
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (isStrictEqual(a, b)) {
|
||||
return true;
|
||||
}
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (a === undefined || b === undefined) {
|
||||
return false;
|
||||
}
|
||||
const ai = a[Symbol.iterator]();
|
||||
const bi = b[Symbol.iterator]();
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
while (true) {
|
||||
const av = ai.next();
|
||||
const bv = bi.next();
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (av.done || bv.done) {
|
||||
return av.done === bv.done;
|
||||
}
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (!e(av.value, bv.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const isArray = <T, U>(v: readonly T[] | U): v is readonly T[] =>
|
||||
v instanceof Array;
|
||||
|
||||
export const toArray = <T>(i: Iterable<T> | undefined): readonly T[] =>
|
||||
i === undefined ? [] : Array.from(i);
|
||||
|
||||
export const reverse = <T>(i: Iterable<T> | undefined): readonly T[] =>
|
||||
fold(i, (a, b) => [b, ...a], new Array<T>());
|
||||
|
||||
export const arrayReverse = <T>(a: readonly T[]): IterableEx<T> =>
|
||||
iterable(function* () {
|
||||
// tslint:disable-next-line:no-loop-statement
|
||||
for (let i = a.length; i > 0; ) {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
i -= 1;
|
||||
yield a[i];
|
||||
}
|
||||
});
|
||||
|
||||
export const isEmpty = <T>(i: Iterable<T> | undefined): boolean =>
|
||||
!some(i, () => true);
|
||||
|
||||
export const join = (
|
||||
i: Iterable<string> | undefined,
|
||||
separator: string
|
||||
): string => {
|
||||
const result = reduce(i, (a, b) => a + separator + b);
|
||||
return result === undefined ? "" : result;
|
||||
};
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
export const empty = <T>() => iterable(function* (): Iterator<T> {});
|
||||
|
||||
export const dropRight = <T>(
|
||||
i: readonly T[] | undefined,
|
||||
n: number = 1
|
||||
): IterableEx<T> => (i === undefined ? empty() : take(i, i.length - n));
|
||||
|
||||
export const uniq = <T>(
|
||||
i: Iterable<T>,
|
||||
key: (v: T) => unknown = (v) => v
|
||||
): IterableEx<T> =>
|
||||
flatScan(
|
||||
i,
|
||||
(set, v: T): readonly [Set<unknown>, readonly T[]] => {
|
||||
const k = key(v);
|
||||
// tslint:disable-next-line:no-if-statement
|
||||
if (!set.has(k)) {
|
||||
// tslint:disable-next-line:no-expression-statement
|
||||
set.add(k);
|
||||
return [set, [v]];
|
||||
}
|
||||
return [set, []];
|
||||
},
|
||||
new Set<unknown>()
|
||||
);
|
|
@ -0,0 +1,549 @@
|
|||
/* tslint:disable */
|
||||
|
||||
import * as _ from "../index"
|
||||
|
||||
describe("map", () => {
|
||||
it("array", () => {
|
||||
const result = _.map([1, 2, 3], x => x * x).toArray()
|
||||
expect([1, 4, 9]).toEqual(result)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = _.map(undefined, x => x).toArray()
|
||||
expect([]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.chain([1, 2, 3]).map(x => x * x))
|
||||
expect([1, 4, 9]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("filter", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.filter([1, 2, 3, 4], x => x % 2 === 0))
|
||||
expect([2, 4]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.iterable(function *() { yield *[1, 2, 3, 4] }).filter(x => x % 2 === 0))
|
||||
expect([2, 4]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("drop", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.drop(["a", "b", "c", "d", "e"], 2))
|
||||
expect(["c", "d", "e"]).toEqual(result)
|
||||
})
|
||||
it("default", () => {
|
||||
const result = Array.from(_.drop(["a", "b", "c", "d", "e"]))
|
||||
expect(["b", "c", "d", "e"]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.iterable(function *() { yield *["a", "b", "c", "d", "e"] }).drop(2))
|
||||
expect(["c", "d", "e"]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("filterMap", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.filterMap([1, 2, 3, 4], x => x))
|
||||
expect([1, 2, 3, 4]).toEqual(result)
|
||||
})
|
||||
it("array with undefined", () => {
|
||||
const result: number[] = Array.from(_.filterMap([1, 2, 3, 4, undefined], x => x))
|
||||
expect([1, 2, 3, 4]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.concat([1, 2, 3, 4]).filterMap(x => x < 3 ? x * 2 : undefined))
|
||||
expect([2, 4]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("flat", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.flat([[1, 2], [2, 3], [3, 4]]))
|
||||
expect([1, 2, 2, 3, 3, 4]).toEqual(result)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = Array.from(_.flat(undefined))
|
||||
expect([]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("flatMap", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.flatMap([1, 2, 3], x => [x, x * 2]))
|
||||
expect([1, 2, 2, 4, 3, 6]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.iterable(() => [1, 2, 3][Symbol.iterator]()).flatMap(x => [x, x * 2]))
|
||||
expect([1, 2, 2, 4, 3, 6]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("repeat", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.repeat("Hello!", 5))
|
||||
expect(["Hello!", "Hello!", "Hello!", "Hello!", "Hello!"]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("zip", () => {
|
||||
it("array", () => {
|
||||
const result = Array.from(_.zip([1, "b", 4], ["a", 2, 6]))
|
||||
expect([[1, "a"], ["b", 2], [4, 6]]).toEqual(result)
|
||||
})
|
||||
it("empty item", () => {
|
||||
const result = Array.from(_.zip([1, "b"], [], ["a", 2]))
|
||||
expect([]).toEqual(result)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = Array.from(_.zip([1, "b"], undefined, ["a", 2]))
|
||||
expect([]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = Array.from(_.concat([1, "b", 4]).zip(["a", 2, 6]))
|
||||
expect([[1, "a"], ["b", 2], [4, 6]]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("generate", () => {
|
||||
it("infinite", () => {
|
||||
const result = Array.from(_.zip(_.repeat(2), [1, 3]))
|
||||
expect([[2, 1], [2, 3]]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("reduce", () => {
|
||||
it("no items", () => {
|
||||
const result = _.reduce([], a => a)
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
it("1", () => {
|
||||
const result = _.reduce([1], (a, b) => a + b)
|
||||
if (result === undefined) {
|
||||
throw new Error("undefined")
|
||||
}
|
||||
expect(1).toEqual(result)
|
||||
})
|
||||
it("2", () => {
|
||||
const result = _.reduce([1, 2], (a, b) => a + b)
|
||||
if (result === undefined) {
|
||||
throw new Error("undefined")
|
||||
}
|
||||
expect(3).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3]).reduce((a, b) => a + b)
|
||||
if (result === undefined) {
|
||||
throw new Error("undefined")
|
||||
}
|
||||
expect(6).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("sum", () => {
|
||||
it("array", () => {
|
||||
const result = _.sum([1, 2, 3])
|
||||
expect(6).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("min", () => {
|
||||
it("3", () => {
|
||||
const result = _.min([1, 2, 3])
|
||||
expect(1).toEqual(result)
|
||||
})
|
||||
it("0", () => {
|
||||
const result = _.min([])
|
||||
expect(Infinity).toEqual(result)
|
||||
})
|
||||
it("negative", () => {
|
||||
const result = _.min([-1, -2, -3])
|
||||
expect(-3).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fold", () => {
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3]).fold((a, b) => a + b, "")
|
||||
expect(result).toEqual("123")
|
||||
})
|
||||
})
|
||||
|
||||
describe("max", () => {
|
||||
it("3", () => {
|
||||
const result = _.max([1, 2, 3])
|
||||
expect(3).toEqual(result)
|
||||
})
|
||||
it("0", () => {
|
||||
const result = _.max([])
|
||||
expect(-Infinity).toEqual(result)
|
||||
})
|
||||
it("negative (to make sure, no zeros are involved", () => {
|
||||
const result = _.max([-2, -3, -4])
|
||||
expect(-2).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("forEach", () => {
|
||||
it("array", () => {
|
||||
let x = 0
|
||||
let ii = 0
|
||||
_.forEach(
|
||||
[1, 2, 4],
|
||||
(v, i) => {
|
||||
x = x + v
|
||||
ii = ii + i
|
||||
})
|
||||
expect(7).toEqual(x)
|
||||
expect(3).toEqual(ii)
|
||||
})
|
||||
it("member", () => {
|
||||
let x = 0
|
||||
let ii = 0
|
||||
_.concat([1, 2, 4]).forEach(
|
||||
(v, i) => {
|
||||
x = x + v
|
||||
ii = ii + i
|
||||
})
|
||||
expect(7).toEqual(x)
|
||||
expect(3).toEqual(ii)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isEqual", () => {
|
||||
it("ref equal", () => {
|
||||
const ref: ReadonlyArray<string> = ["a", "b"]
|
||||
const result = _.isEqual(ref, ref, (a, b) => a === b)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("equal", () => {
|
||||
const result = _.isEqual(["a", "b"], ["a", "b"], (a, b) => a === b)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("length", () => {
|
||||
const result = _.isEqual(["a", "b"], ["a", "b", "c"], (a, b) => a === b)
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("not equal", () => {
|
||||
const result = _.isEqual(["a", "b"], ["a", "c"], (a, b) => a === b)
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("default e", () => {
|
||||
const result = _.isEqual(["a", "b"], ["a", "c"])
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("one undefined", () => {
|
||||
const result = _.isEqual(undefined, "a")
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("both undefined", () => {
|
||||
const result = _.isEqual(undefined, undefined)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat(["a", "b"]).isEqual(["a", "c"])
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("last", () => {
|
||||
it("3", () => {
|
||||
const result = _.last([1, 4, 5, 3])
|
||||
expect(3).toEqual(result)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = _.last([])
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 4, 5, 3, 9]).last()
|
||||
expect(9).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("some", () => {
|
||||
it("some", () => {
|
||||
const result = _.some([1, 2, 3, 4], v => v == 2)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("none", () => {
|
||||
const result = _.some([1, 5, 3, 4], v => v == 2)
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("with undefined", () => {
|
||||
const result = _.some([undefined], () => true)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3, 4]).some(v => v == 4)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("member default, non empty", () => {
|
||||
const result = _.concat([1, 2]).some()
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("member default, empty", () => {
|
||||
const result = _.concat([]).some()
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
})
|
||||
|
||||
function readonlyArrayOrString(v: readonly string[]|string): readonly string[]|string {
|
||||
return v
|
||||
}
|
||||
|
||||
describe("isArray", () => {
|
||||
it("array", () => {
|
||||
const v = readonlyArrayOrString(["5"])
|
||||
if (_.isArray(v)) {
|
||||
expect(1).toEqual(v.length)
|
||||
expect("5").toEqual(v[0])
|
||||
} else {
|
||||
throw Error("`isArray()` returned `false`")
|
||||
}
|
||||
})
|
||||
it("array", () => {
|
||||
const v = readonlyArrayOrString("5")
|
||||
if (_.isArray(v)) {
|
||||
throw Error("`isArray()` returned `true`")
|
||||
|
||||
} else {
|
||||
expect("5").toEqual(v)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("concat", () => {
|
||||
it("several", () => {
|
||||
const result = _.concat([1, 2, 3], [5, 7, 9], [-1])
|
||||
expect([1, 2, 3, 5, 7, 9, -1]).toEqual(_.toArray(result))
|
||||
})
|
||||
it("concat", () => {
|
||||
const result = _.concat([1, 2, 3], [5, 7, 9], undefined, [-1])
|
||||
expect([1, 2, 3, 5, 7, 9, -1]).toEqual(_.toArray(result))
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([91, 140]).concat([1, 2, 3], [5, 7, 9], undefined, [-1])
|
||||
expect([91, 140, 1, 2, 3, 5, 7, 9, -1]).toEqual(_.toArray(result))
|
||||
})
|
||||
})
|
||||
|
||||
describe("toArray", () => {
|
||||
it("undefined", () => {
|
||||
const result = _.toArray(undefined)
|
||||
expect([]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3]).toArray()
|
||||
expect([1, 2, 3]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("every", () => {
|
||||
it("all", () => {
|
||||
const result = _.every([1, 2, 3], v => v > 0)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("not all", () => {
|
||||
const result = _.every([1, 2, 0], v => v > 0)
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3]).every(v => v > 0)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("reverse", () => {
|
||||
it("array", () => {
|
||||
const result = _.reverse([1, 2, 3])
|
||||
expect([3, 2, 1]).toEqual(result)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([1, 2, 3]).reverse()
|
||||
expect([3, 2, 1]).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isEmpty", () => {
|
||||
it("empty", () => {
|
||||
const result = _.isEmpty(undefined)
|
||||
expect(result).toEqual(true)
|
||||
})
|
||||
it("not empty", () => {
|
||||
function *iterator() {
|
||||
yield 23
|
||||
// make sure we never check next item
|
||||
throw new Error()
|
||||
}
|
||||
const result = _.isEmpty(iterator())
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("with undefined", () => {
|
||||
const result = _.isEmpty([undefined])
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([2]).isEmpty()
|
||||
expect(result).toEqual(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("entries", () => {
|
||||
it("member", () => {
|
||||
const result = _.toArray(_.iterable(function *() { yield "a"; yield "b"; yield "c"; }).entries())
|
||||
expect(result).toEqual([[0, "a"], [1, "b"], [2, "c"]])
|
||||
})
|
||||
})
|
||||
|
||||
describe("findEntry", () => {
|
||||
it("some", () => {
|
||||
const result = _.findEntry([0, 1, 0], v => v === 0)
|
||||
expect(result).toEqual([0, 0])
|
||||
})
|
||||
it("none", () => {
|
||||
const result = _.find([0, 1, 0], v => v === 2)
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = _.findEntry([undefined], () => true)
|
||||
expect(result).toEqual([0, undefined])
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([0, 1, 0]).findEntry(v => v === 0)
|
||||
expect(result).toEqual([0, 0])
|
||||
})
|
||||
})
|
||||
|
||||
describe("find", () => {
|
||||
it("some", () => {
|
||||
const result = _.find([0, 1, 0], v => v === 0)
|
||||
expect(result).toEqual(0)
|
||||
})
|
||||
it("none", () => {
|
||||
const result = _.find([0, 1, 0], v => v === 2)
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = _.find([undefined], () => true)
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([0, 1, 0]).find(v => v === 2)
|
||||
expect(result).toEqual(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe("join", () => {
|
||||
it("/", () => {
|
||||
const result = _.join(["aaa", "bb", "c"], "/")
|
||||
expect(result).toEqual("aaa/bb/c")
|
||||
})
|
||||
it("one", () => {
|
||||
const result = _.join(["rrr"], "/")
|
||||
expect(result).toEqual("rrr")
|
||||
})
|
||||
it("empty", () => {
|
||||
const result = _.join([], "/")
|
||||
expect(result).toEqual("")
|
||||
})
|
||||
})
|
||||
|
||||
describe("takeWhile", () => {
|
||||
it("member", () => {
|
||||
const result = _.toArray(_.concat(["a", "b", "c", "d"]).takeWhile(v => v !== "c"))
|
||||
expect(result).toEqual(["a", "b"])
|
||||
})
|
||||
})
|
||||
|
||||
describe("take", () => {
|
||||
it("1", () => {
|
||||
const result = _.toArray(_.take(["a", "b", "c"]))
|
||||
expect(result).toEqual(["a"])
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.toArray(_.concat(["a", "b", "c", "d"]).take(2))
|
||||
expect(result).toEqual(["a", "b"])
|
||||
})
|
||||
})
|
||||
|
||||
describe("dropRight", () => {
|
||||
it("array", () => {
|
||||
const result = _.toArray(_.dropRight(["a", "b", "c", "d", "e"], 2))
|
||||
expect(result).toEqual(["a", "b", "c"])
|
||||
})
|
||||
it("1", () => {
|
||||
const result = _.toArray(_.dropRight(["a", "b", "c", "d", "e"]))
|
||||
expect(result).toEqual(["a", "b", "c", "d"])
|
||||
})
|
||||
it("undefined", () => {
|
||||
const result = _.dropRight(undefined).toArray()
|
||||
expect(result).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("uniq", () => {
|
||||
it("sorted", () => {
|
||||
const result = _.toArray(_.uniq([1, 2, 2, 3]))
|
||||
expect(result).toEqual([1, 2, 3])
|
||||
})
|
||||
it("unsorted", () => {
|
||||
const result = _.toArray(_.uniq([3, 1, 2, 2, 3]))
|
||||
expect(result).toEqual([3, 1, 2])
|
||||
})
|
||||
it("complex", () => {
|
||||
const result = _.toArray(_.uniq(
|
||||
[{ a: 3 }, { a: 1 }, { a: 2 }, { a: 2 }, { a: 3 }],
|
||||
v => v.a
|
||||
))
|
||||
expect(result).toEqual([{ a: 3 }, { a: 1 }, { a: 2 }])
|
||||
})
|
||||
it("member", () => {
|
||||
const result = _.concat([3, 1, 2, 2, 3]).uniq().toArray()
|
||||
expect(result).toEqual([3, 1, 2])
|
||||
})
|
||||
})
|
||||
|
||||
describe("chain", () => {
|
||||
it("Symbol.iterator", () => {
|
||||
const c = _.chain([1, 2])
|
||||
const createIterator = c[Symbol.iterator]
|
||||
const x = _.iterable(createIterator)
|
||||
const result = x.toArray()
|
||||
expect(result).toEqual([1, 2])
|
||||
})
|
||||
it("no this", () => {
|
||||
const c = _.chain([1, 2])
|
||||
const f = c.map
|
||||
const result = f(v => v * 2).toArray()
|
||||
expect(result).toEqual([2, 4])
|
||||
})
|
||||
})
|
||||
|
||||
describe("arrayReverse", () => {
|
||||
it("some value", () => {
|
||||
const c = _.arrayReverse([1, 2, 3])
|
||||
const x = c.last()
|
||||
expect(x).toEqual(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("scan", () => {
|
||||
it("scan", () => {
|
||||
const c = _.chain([56, 27, 155])
|
||||
const r = c.scan((a, v) => a + v, ":").toArray()
|
||||
expect(r).toEqual([":", ":56", ":5627", ":5627155"])
|
||||
})
|
||||
})
|
||||
|
||||
describe("first", () => {
|
||||
it("first", () => {
|
||||
const c = _.chain([2, 3]).first()
|
||||
expect(c).toEqual(2)
|
||||
})
|
||||
it("undefined", () => {
|
||||
const c = _.first(undefined)
|
||||
expect(c).toEqual(undefined)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,197 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="jest tests" tests="96" failures="0" time="4.521">
|
||||
<testsuite name="map" errors="0" failures="0" skipped="0" timestamp="2020-10-09T08:28:06" time="3.862" tests="96">
|
||||
<testcase classname="map array" name="map array" time="0.005">
|
||||
</testcase>
|
||||
<testcase classname="map undefined" name="map undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="map member" name="map member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="filter array" name="filter array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="filter member" name="filter member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="drop array" name="drop array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="drop default" name="drop default" time="0">
|
||||
</testcase>
|
||||
<testcase classname="drop member" name="drop member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="filterMap array" name="filterMap array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="filterMap array with undefined" name="filterMap array with undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="filterMap member" name="filterMap member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="flat array" name="flat array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="flat undefined" name="flat undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="flatMap array" name="flatMap array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="flatMap member" name="flatMap member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="repeat array" name="repeat array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="zip array" name="zip array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="zip empty item" name="zip empty item" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="zip undefined" name="zip undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="zip member" name="zip member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="generate infinite" name="generate infinite" time="0">
|
||||
</testcase>
|
||||
<testcase classname="reduce no items" name="reduce no items" time="0">
|
||||
</testcase>
|
||||
<testcase classname="reduce 1" name="reduce 1" time="0">
|
||||
</testcase>
|
||||
<testcase classname="reduce 2" name="reduce 2" time="0">
|
||||
</testcase>
|
||||
<testcase classname="reduce member" name="reduce member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="sum array" name="sum array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="min 3" name="min 3" time="0">
|
||||
</testcase>
|
||||
<testcase classname="min 0" name="min 0" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="min negative" name="min negative" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="fold member" name="fold member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="max 3" name="max 3" time="0">
|
||||
</testcase>
|
||||
<testcase classname="max 0" name="max 0" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="max negative (to make sure, no zeros are involved" name="max negative (to make sure, no zeros are involved" time="0">
|
||||
</testcase>
|
||||
<testcase classname="forEach array" name="forEach array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="forEach member" name="forEach member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isEqual ref equal" name="isEqual ref equal" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEqual equal" name="isEqual equal" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEqual length" name="isEqual length" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEqual not equal" name="isEqual not equal" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isEqual default e" name="isEqual default e" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEqual one undefined" name="isEqual one undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isEqual both undefined" name="isEqual both undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEqual member" name="isEqual member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="last 3" name="last 3" time="0">
|
||||
</testcase>
|
||||
<testcase classname="last undefined" name="last undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="last member" name="last member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="some some" name="some some" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="some none" name="some none" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="some with undefined" name="some with undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="some member" name="some member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="some member default, non empty" name="some member default, non empty" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="some member default, empty" name="some member default, empty" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isArray array" name="isArray array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isArray array" name="isArray array" time="0">
|
||||
</testcase>
|
||||
<testcase classname="concat several" name="concat several" time="0">
|
||||
</testcase>
|
||||
<testcase classname="concat concat" name="concat concat" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="concat member" name="concat member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="toArray undefined" name="toArray undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="toArray member" name="toArray member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="every all" name="every all" time="0">
|
||||
</testcase>
|
||||
<testcase classname="every not all" name="every not all" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="every member" name="every member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="reverse array" name="reverse array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="reverse member" name="reverse member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEmpty empty" name="isEmpty empty" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isEmpty not empty" name="isEmpty not empty" time="0">
|
||||
</testcase>
|
||||
<testcase classname="isEmpty with undefined" name="isEmpty with undefined" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="isEmpty member" name="isEmpty member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="entries member" name="entries member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="findEntry some" name="findEntry some" time="0">
|
||||
</testcase>
|
||||
<testcase classname="findEntry none" name="findEntry none" time="0">
|
||||
</testcase>
|
||||
<testcase classname="findEntry undefined" name="findEntry undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="findEntry member" name="findEntry member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="find some" name="find some" time="0">
|
||||
</testcase>
|
||||
<testcase classname="find none" name="find none" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="find undefined" name="find undefined" time="0">
|
||||
</testcase>
|
||||
<testcase classname="find member" name="find member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="join /" name="join /" time="0.002">
|
||||
</testcase>
|
||||
<testcase classname="join one" name="join one" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="join empty" name="join empty" time="0">
|
||||
</testcase>
|
||||
<testcase classname="takeWhile member" name="takeWhile member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="take 1" name="take 1" time="0">
|
||||
</testcase>
|
||||
<testcase classname="take member" name="take member" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="dropRight array" name="dropRight array" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="dropRight 1" name="dropRight 1" time="0">
|
||||
</testcase>
|
||||
<testcase classname="dropRight undefined" name="dropRight undefined" time="0.005">
|
||||
</testcase>
|
||||
<testcase classname="uniq sorted" name="uniq sorted" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="uniq unsorted" name="uniq unsorted" time="0">
|
||||
</testcase>
|
||||
<testcase classname="uniq complex" name="uniq complex" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="uniq member" name="uniq member" time="0">
|
||||
</testcase>
|
||||
<testcase classname="chain Symbol.iterator" name="chain Symbol.iterator" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="chain no this" name="chain no this" time="0">
|
||||
</testcase>
|
||||
<testcase classname="arrayReverse some value" name="arrayReverse some value" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="scan scan" name="scan scan" time="0">
|
||||
</testcase>
|
||||
<testcase classname="first first" name="first first" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="first undefined" name="first undefined" time="0">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "es2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation: */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
"sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
"declarationMap": true,
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
"importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": ["tslint:all", "tslint-immutable"],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"semicolon": false,
|
||||
"interface-name": false,
|
||||
"arrow-parens": false,
|
||||
"ordered-imports": false,
|
||||
"forin": false,
|
||||
"interface-over-type-literal": false,
|
||||
"object-literal-sort-keys": false,
|
||||
|
||||
// Recommended built-in rules
|
||||
"no-var-keyword": true,
|
||||
"no-parameter-reassignment": true,
|
||||
"typedef": true,
|
||||
"linebreak-style": false,
|
||||
"newline-before-return": false,
|
||||
"type-literal-delimiter": false,
|
||||
"trailing-comma": false,
|
||||
"prefer-method-signature": false,
|
||||
"member-ordering": false,
|
||||
// this rule has too many false positives.
|
||||
"no-use-before-declare": false,
|
||||
|
||||
// Immutability rules
|
||||
"readonly-keyword": true,
|
||||
"readonly-array": true,
|
||||
"no-let": [true, "ignore-local"],
|
||||
"no-object-mutation": true,
|
||||
"no-delete": true,
|
||||
"no-method-signature": true,
|
||||
"array-type": false,
|
||||
|
||||
// Functional style rules
|
||||
"no-this": true,
|
||||
"no-class": true,
|
||||
"no-mixed-interface": true,
|
||||
"no-expression-statement": true,
|
||||
"no-if-statement": true,
|
||||
"no-loop-statement": true,
|
||||
"strict-comparisons": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
|
@ -117,7 +117,7 @@
|
|||
* Specify a SemVer range to ensure developers use a Node.js version that is appropriate
|
||||
* for your repo.
|
||||
*/
|
||||
"nodeSupportedVersionRange": ">=12.13.0 <13.0.0",
|
||||
"nodeSupportedVersionRange": ">=10.13.0",
|
||||
|
||||
/**
|
||||
* Odd-numbered major versions of Node.js are experimental. Even-numbered releases
|
||||
|
@ -431,8 +431,8 @@
|
|||
// "reviewCategory": "tools"
|
||||
// }
|
||||
{
|
||||
"packageName": "@openapi-tools-common/json-parser",
|
||||
"projectFolder": "json-parser",
|
||||
"packageName": "@openapi-tools-common/iterator",
|
||||
"projectFolder": "iterator",
|
||||
"shouldPublish": true
|
||||
}
|
||||
]
|
||||
|
|
Загрузка…
Ссылка в новой задаче