This commit is contained in:
FAREAST\renhel 2020-10-09 16:40:28 +08:00
Родитель 338a4ffa92
Коммит 20b5c81db5
19 изменённых файлов: 6115 добавлений и 3 удалений

5
.gitignore поставляемый
Просмотреть файл

@ -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

32
iterator/.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -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"
]
}
]
}

3
iterator/.vscode/settings.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib"
}

17
iterator/CHANGELOG.json Normal file
Просмотреть файл

@ -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"
}
]
}
}
]
}

11
iterator/CHANGELOG.md Normal file
Просмотреть файл

@ -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

21
iterator/LICENSE Normal file
Просмотреть файл

@ -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

9
iterator/README.md Normal file
Просмотреть файл

@ -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

72
iterator/package.json Normal file
Просмотреть файл

@ -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"
}
}

531
iterator/src/index.ts Normal file
Просмотреть файл

@ -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>()
);

549
iterator/src/test/test.ts Normal file
Просмотреть файл

@ -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)
})
})

197
iterator/test-results.xml Normal file
Просмотреть файл

@ -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>

58
iterator/tsconfig.json Normal file
Просмотреть файл

@ -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. */
}
}

46
iterator/tslint.json Normal file
Просмотреть файл

@ -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
}
]